ast_serialize-0.13.1/PKG-INFO000064400000000000000000000025751046102023000124520ustar00Metadata-Version: 2.4 Name: ast_serialize Version: 0.13.1 Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 Classifier: Programming Language :: Python :: 3.15 Classifier: Programming Language :: Rust Classifier: Topic :: Software Development Classifier: Typing :: Typed License-File: LICENSE License-File: crates/LICENSE Summary: Python bindings for mypy AST serialization Author-email: Jukka Lehtosalo License-Expression: MIT Requires-Python: >=3.7 Description-Content-Type: text/x-rst Project-URL: Homepage, https://github.com/mypyc/ast_serialize Project-URL: Issues, https://github.com/mypyc/ast_serialize/issues ast_serialize - Python Parser and AST Serializer ================================================ This is a fast Python extension for parsing Python files and serializing the AST using the native binary format used by mypy. This will eventually replace the current mypy parser, which uses the Python stdlib ``ast`` module for parsing. ast_serialize-0.13.1/.cargo/config.toml000064400000000000000000000001331046102023000146540ustar00[alias] lint = "clippy --all-targets --locked -- -D warnings" fmt-check = "fmt -- --check" ast_serialize-0.13.1/.github/workflows/build_wheels.yml000064400000000000000000000213411046102023000201330ustar00name: Build wheels on: push: branches: - main pull_request: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true permissions: contents: read jobs: linux: runs-on: ${{ matrix.platform.runner }} strategy: matrix: platform: - runner: ubuntu-22.04 target: x86_64 - runner: ubuntu-22.04 target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 target: armv7 - runner: ubuntu-22.04 target: s390x - runner: ubuntu-22.04 target: ppc64le - runner: ubuntu-24.04 target: riscv64 steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: 3.14 - name: Build abi3 wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14 sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: auto - name: Build CPython 3.14t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: auto - name: Build abi3t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.15t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: auto - name: Upload wheels uses: actions/upload-artifact@v5 with: name: wheels-linux-${{ matrix.platform.target }} path: dist musllinux: runs-on: ${{ matrix.platform.runner }} strategy: matrix: platform: - runner: ubuntu-22.04 target: x86_64 - runner: ubuntu-22.04 target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 target: armv7 - runner: ubuntu-22.04 target: ppc64le - runner: ubuntu-24.04 target: riscv64 steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: 3.14 - name: Build abi3 wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14 sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: musllinux_1_2 - name: Build CPython 3.14t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: musllinux_1_2 - name: Build abi3t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.15t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: musllinux_1_2 - name: Upload wheels uses: actions/upload-artifact@v5 with: name: wheels-musllinux-${{ matrix.platform.target }} path: dist windows: runs-on: ${{ matrix.platform.runner }} strategy: matrix: platform: - runner: windows-latest target: x64 python_arch: x64 - runner: windows-latest target: x86 python_arch: x86 - runner: windows-11-arm target: aarch64 python_arch: arm64 steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: 3.14 architecture: ${{ matrix.platform.python_arch }} - name: Build abi3 wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14 sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Build CPython 3.14t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Build abi3t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.15t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Upload wheels uses: actions/upload-artifact@v5 with: name: wheels-windows-${{ matrix.platform.target }} path: dist macos: runs-on: ${{ matrix.platform.runner }} strategy: matrix: platform: - runner: macos-15-intel target: x86_64 - runner: macos-latest target: aarch64 steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: 3.14 - name: Build abi3 wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14 sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Build CPython 3.14t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.14t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Build abi3t wheel uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --release --out dist -i python3.15t sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Upload wheels uses: actions/upload-artifact@v5 with: name: wheels-macos-${{ matrix.platform.target }} path: dist emscripten: # Emscripten doesn't support stable ABI, so we build version-specific wheels strategy: matrix: python-version: - 3.14 - 3.15 runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} allow-prereleases: true - run: pip install pyodide-build==0.39.0 - id: pyodide-config run: | echo "rust-toolchain=$(pyodide config get rust_toolchain)" >> "$GITHUB_OUTPUT" echo "emscripten-version=$(pyodide config get emscripten_version)" >> "$GITHUB_OUTPUT" echo "pyodide-abi-version=$(pyodide config get pyodide_abi_version)" >> "$GITHUB_OUTPUT" echo "rustflags=$(pyodide config get rustflags)" >> "$GITHUB_OUTPUT" - uses: mymindstorm/setup-emsdk@v16 with: version: ${{ steps.pyodide-config.outputs.emscripten-version }} no-cache: true - name: Build Python ${{ matrix.python-version }} wheel uses: PyO3/maturin-action@v1 env: CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_RUSTFLAGS: ${{ steps.pyodide-config.outputs.rustflags }} MATURIN_PYEMSCRIPTEN_PLATFORM_VERSION: ${{ steps.pyodide-config.outputs.pyodide-abi-version }} with: target: wasm32-unknown-emscripten args: --release --out dist -i python${{ matrix.python-version }} --no-default-features # TODO: we manually force a slightly newer Rust version since Ruff requires it. rust-toolchain: 1.95 sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Upload wheels uses: actions/upload-artifact@v5 with: name: wheels-emscripten-${{ matrix.python-version }} path: dist sdist: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Build sdist uses: PyO3/maturin-action@v1 with: command: sdist args: --out dist - name: Upload sdist uses: actions/upload-artifact@v5 with: name: wheels-sdist path: dist release: if: ${{ github.event_name == 'workflow_dispatch' && github.ref_type == 'tag' }} needs: [linux, musllinux, windows, macos, emscripten, sdist] runs-on: ubuntu-latest permissions: id-token: write steps: - name: Download artifact uses: actions/download-artifact@v4 with: pattern: wheels-* path: dist merge-multiple: true - name: Release to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: skip-existing: true ast_serialize-0.13.1/.github/workflows/test.yml000064400000000000000000000023251046102023000164450ustar00name: Tests on: workflow_dispatch: push: branches: [main] pull_request: paths-ignore: - 'docs/**' - '**/*.rst' - '**/*.md' - .gitignore - CREDITS - LICENSE permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: main: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - name: Run smoke tests on Ubuntu with Python 3.10 python: '3.10' os: ubuntu-24.04-arm - name: Run smoke tests on Windows with Python 3.14 python: '3.14' os: windows-latest - name: Run smoke tests on Ubuntu with Python 3.15t python: '3.15t' os: ubuntu-24.04-arm name: ${{ matrix.name }} timeout-minutes: 5 steps: - uses: actions/checkout@v4 with: persist-credentials: false - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} allow-prereleases: true - run: cargo test - run: pip install -U . - run: python test_ast_serialize.py - run: cargo fmt --check ast_serialize-0.13.1/.gitignore000064400000000000000000000003751046102023000133410ustar00# Rust target/ # Python __pycache__/ *.py[cod] *$py.class *.so .pytest_cache/ .mypy_cache/ *.egg-info/ dist/ build/ # Virtual environments venv/ .venv/ env/ # IDE (but keep .cargo/ for config) .vscode/ .idea/ *.swp *.swo *~ # OS .DS_Store Thumbs.db ast_serialize-0.13.1/AGENTS.md000064400000000000000000000037141046102023000126540ustar00# Overview This repository contains a Python Rust extension that serializes a Ruff AST into binary data. Mypy uses this extension to parse Python code and deserialize the produced AST. This depends on Ruff crates as external git dependencies. # Code structure - Serialization is implemented in ~/src/ast_serialize/src/serialize_ast.rs (and other files in src/) - Deserialization is implemented in ~/src/mypy/mypy/nativeparse.py - Mypy AST is defined in ~/src/mypy/mypy/nodes.py (type annotation AST nodes in ~/src/mypy/mypy/types.py) ## Ruff sources This project depends on Ruff crates as git dependencies (see Cargo.toml). The sources are: - **Git dependency**: Defined in Cargo.toml, pinned to a specific Ruff tag/commit - **Cached location**: After first build, sources are cached in `~/.cargo/git/checkouts/ruff-*/` - **Upstream repo**: https://github.com/astral-sh/ruff To browse Ruff sources: ```bash # Find the cached checkout ls ~/.cargo/git/checkouts/ruff-*/ # Or clone separately git clone https://github.com/astral-sh/ruff ~/src/ruff ``` Key Ruff crates used: - `ruff_python_parser` - Python parser - `ruff_python_ast` - Python AST definitions - `ruff_source_file` - Source file handling (LineIndex) - `ruff_text_size` - Text position types (TextRange, Ranged) # Testing and development - Run `maturin develop` in ~/src/ast_serialize before running Python tests if Rust code has been modified - Add end-to-end tests to ~/src/mypy/test-data/unit/native-parser.test. Look at parse.test in the same directory for the correct output format and how different AST nodes are output - If pytest is not installed, enable virtualenv in ~/venv/mypy to run tests - Pass argument `mypy/test/test_nativeparse.py::NativeParserSuite` to pytest to run the relevant native parser tests - Run Rust unit tests with: `cargo test` ## Updating Ruff dependency To update to a newer Ruff version, edit Cargo.toml and change the `tag` or `rev` parameter for all ruff_* dependencies, then rebuild. ast_serialize-0.13.1/Cargo.lock000064400000000000000000001230211046102023000132500ustar00# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstream" version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse 0.2.7", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstream" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-lossy" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9ca7d0f520afcd6d817970d0b2d5fd7c630c75e7783cae046b8b8a783c5befa" dependencies = [ "anstyle", ] [[package]] name = "anstyle-parse" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-parse" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-svg" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab68e0b71ea68eb6b399ffe1957f26330aeed91f5e578d442a1c2f3df69f6ec1" dependencies = [ "anstyle", "anstyle-lossy", "anstyle-parse 1.0.0", "html-escape", "unicode-width", ] [[package]] name = "anstyle-wincon" version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", "windows-sys", ] [[package]] name = "anyhow" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "attribute-derive" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05832cdddc8f2650cc2cc187cc2e952b8c133a48eb055f35211f61ee81502d77" dependencies = [ "attribute-derive-macro", "derive-where", "manyhow", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "attribute-derive-macro" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a7cdbbd4bd005c5d3e2e9c885e6fa575db4f4a3572335b974d8db853b6beb61" dependencies = [ "collection_literals", "interpolator", "manyhow", "proc-macro-utils", "proc-macro2", "quote", "quote-use", "syn 2.0.114", ] [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "boxcar" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" [[package]] name = "bstr" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "camino" version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" [[package]] name = "castaway" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" dependencies = [ "rustversion", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "char_str" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "576ba56f6ca18ebb069d0d07260407171712aff4dfe15ee3f8982dc16a455bcf" dependencies = [ "castaway", "get-size2", "itoa", "ryu", "serde_core", ] [[package]] name = "clap" version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream 0.6.21", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "clap_lex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "collection_literals" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "compact_str" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79fcda08c33bb58b97008b2cdada6622500e949e060f5913361763121abd2416" dependencies = [ "castaway", "cfg-if", "itoa", "serde", "static_assertions", "zmij", ] [[package]] name = "console" version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", "windows-sys", ] [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crossbeam-queue" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crypto-common" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", ] [[package]] name = "datatest-stable" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a867d7322eb69cf3a68a5426387a25b45cb3b9c5ee41023ee6cea92e2afadd82" dependencies = [ "camino", "fancy-regex", "libtest-mimic", "walkdir", ] [[package]] name = "derive-where" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "drop_bomb" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" [[package]] name = "dyn-clone" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", ] [[package]] name = "escape8259" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" [[package]] name = "escargot" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11c3aea32bc97b500c9ca6a72b768a26e558264303d101d3409cf6d57a9ed0cf" dependencies = [ "log", "serde", "serde_json", ] [[package]] name = "fancy-regex" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" dependencies = [ "bit-set", "regex-automata", "regex-syntax", ] [[package]] name = "fastrand" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "filetime" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", ] [[package]] name = "foldhash" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "get-size-derive2" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c736d226c32e496b8377813b52269e11ad3a48d8373b68862d0364f04fd1229d" dependencies = [ "attribute-derive", "quote", "syn 2.0.114", ] [[package]] name = "get-size2" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b411f34418305908ab15a82ff78958c2a9aee9a272b2a2e663836b20a4e4b9d3" dependencies = [ "compact_str", "get-size-derive2", "hashbrown", "ordermap", "smallvec", "thin-vec", ] [[package]] name = "getopts" version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "getrandom" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi", ] [[package]] name = "glob" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "globset" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" dependencies = [ "aho-corasick", "bstr", "log", "regex-automata", "regex-syntax", ] [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] [[package]] name = "hashlink" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32069d97bb81e38fa67eab65e3393bf804bb85969f2bc06bf13f64aef5aba248" dependencies = [ "hashbrown", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "html-escape" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9356095b4b41197bba32173600e1582792cda618f65d12f68e2e77d273413c5" [[package]] name = "indexmap" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "indoc" version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" dependencies = [ "rustversion", ] [[package]] name = "insta" version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82" dependencies = [ "console", "once_cell", "similar 2.7.0", "tempfile", ] [[package]] name = "interpolator" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" [[package]] name = "intrusive-collections" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4275b20e6057cd7733fd8df8a5a31701e4fe44497dad0f3fa0e1c4fb971506be" [[package]] name = "inventory" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" dependencies = [ "rustversion", ] [[package]] name = "is-macro" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "is_terminal_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "libc" version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libtest-mimic" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14e6ba06f0ade6e504aff834d7c34298e5155c6baca353cc6a4aaff2f9fd7f33" dependencies = [ "anstream 1.0.0", "anstyle", "clap", "escape8259", ] [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "lock_api" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "manyhow" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" dependencies = [ "manyhow-macros", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "manyhow-macros" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" dependencies = [ "proc-macro-utils", "proc-macro2", "quote", ] [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mypy_parser" version = "0.13.1" dependencies = [ "anyhow", "indoc", "pyo3", "ruff_python_ast", "ruff_python_parser", "ruff_source_file", "ruff_text_size", "sha1", "thin-vec", ] [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "ordermap" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7476a5b122ff1fce7208e7ee9dccd0a516e835f5b8b19b8f3c98a34cf757c1" dependencies = [ "indexmap", ] [[package]] name = "os_pipe" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", "windows-sys", ] [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-link", ] [[package]] name = "phf" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", ] [[package]] name = "phf_generator" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", ] [[package]] name = "phf_shared" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "portable-atomic" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "proc-macro-utils" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" dependencies = [ "proc-macro2", "quote", "smallvec", ] [[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b" dependencies = [ "libc", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", ] [[package]] name = "pyo3-build-config" version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9" dependencies = [ "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn 2.0.114", ] [[package]] name = "pyo3-macros-backend" version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "quote" version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] [[package]] name = "quote-use" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" dependencies = [ "quote", "quote-use-macros", ] [[package]] name = "quote-use-macros" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" dependencies = [ "proc-macro-utils", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.17", ] [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "ref-cast" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" dependencies = [ "proc-macro2", "quote", "syn 3.0.3", ] [[package]] name = "regex" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "ruff_annotate_snippets" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "anstream 1.0.0", "anstyle", "memchr", "ruff_annotate_snippets", "snapbox", "unicode-width", ] [[package]] name = "ruff_cache" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "char_str", "filetime", "glob", "globset", "itertools", "regex", "ruff_macros", "seahash", ] [[package]] name = "ruff_macros" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "heck", "itertools", "proc-macro2", "quote", "regex", "ruff_python_trivia", "syn 3.0.3", ] [[package]] name = "ruff_python_ast" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "aho-corasick", "arrayvec", "bitflags", "char_str", "compact_str", "get-size2", "is-macro", "memchr", "ruff_cache", "ruff_macros", "ruff_python_trivia", "ruff_source_file", "ruff_text_size", "rustc-hash", "salsa", "schemars", "serde", "serde_json", "thin-vec", "thiserror", ] [[package]] name = "ruff_python_parser" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "anyhow", "bitflags", "bstr", "datatest-stable", "drop_bomb", "get-size2", "insta", "itertools", "memchr", "ruff_annotate_snippets", "ruff_python_ast", "ruff_python_trivia", "ruff_source_file", "ruff_text_size", "rustc-hash", "serde", "serde_json", "static_assertions", "thin-vec", "unicode-ident", "unicode-normalization", "unicode_names2", "walkdir", ] [[package]] name = "ruff_python_trivia" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "itertools", "ruff_source_file", "ruff_text_size", "rustc-hash", "unicode-ident", ] [[package]] name = "ruff_source_file" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "get-size2", "memchr", "ruff_text_size", "serde", ] [[package]] name = "ruff_text_size" version = "0.0.9-ast-serialize.0.13.1" dependencies = [ "get-size2", "schemars", "serde", "serde_test", "static_assertions", ] [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "salsa" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf0e374215cd2db2b5c75d7b3a99cb0cc052c0595335dfdefc03d4eb08f4aa81" dependencies = [ "boxcar", "compact_str", "crossbeam-queue", "crossbeam-utils", "hashbrown", "hashlink", "indexmap", "intrusive-collections", "inventory", "parking_lot", "portable-atomic", "rustc-hash", "salsa-macro-rules", "salsa-macros", "smallvec", "thin-vec", "tracing", "typeid", ] [[package]] name = "salsa-macro-rules" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85f4b7d4405540bbd6d4ffa52d4322d983f3781954d3073067ac1bdb028459b3" [[package]] name = "salsa-macros" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "445be2bfbb2f67cb663225ecd7bc5a25370c0250fca30f9d8cbad9a913650370" dependencies = [ "proc-macro2", "quote", "syn 3.0.3", ] [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schemars" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" dependencies = [ "dyn-clone", "ref-cast", "schemars_derive", "serde", "serde_json", ] [[package]] name = "schemars_derive" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", "syn 3.0.3", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "serde_derive_internals" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" dependencies = [ "proc-macro2", "quote", "syn 3.0.3", ] [[package]] name = "serde_json" version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", "serde", "serde_core", "zmij", ] [[package]] name = "serde_test" version = "1.0.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" dependencies = [ "serde", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "similar" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "similar" version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85ee016af5d736b69fc89e19254540fa4b5f5492853fb5503920f084011c78b6" dependencies = [ "bstr", ] [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "snapbox" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de56eb4784a2c5c1efede55a0f06fbf481bc12b42b355b9525c15db1e3581a8" dependencies = [ "anstream 1.0.0", "anstyle", "anstyle-svg", "escargot", "libc", "normalize-line-endings", "os_pipe", "serde_json", "similar 3.1.2", "snapbox-macros", "wait-timeout", "windows-sys", ] [[package]] name = "snapbox-macros" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed4a172e483585ebbc7c7f7d1705ca7e3f94f606ed78caa14805673189fd5455" dependencies = [ "anstream 1.0.0", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom 0.4.3", "once_cell", "rustix", "windows-sys", ] [[package]] name = "thin-vec" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79def32ffcd477db1ff26f76dab9e3a91f0bd42a85ca96577089b24623056f9d" dependencies = [ "serde", ] [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "tinyvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tracing" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] [[package]] name = "typeid" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode_names2" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1673eca9782c84de5f81b82e4109dcfb3611c8ba0d52930ec4a9478f547b2dd" dependencies = [ "phf", "unicode_names2_generator", ] [[package]] name = "unicode_names2_generator" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91e5b84611016120197efd7dc93ef76774f4e084cd73c9fb3ea4a86c570c56e" dependencies = [ "getopts", "log", "phf_codegen", "rand", ] [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ "windows-sys", ] [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "zerocopy" version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "zmij" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" ast_serialize-0.13.1/Cargo.toml000064400000000000000000000104061046102023000132750ustar00[package] name = "mypy_parser" version = "0.13.1" publish = false authors = ["Jukka Lehtosalo"] edition = "2021" rust-version = "1.80" license = "MIT" description = "Python extension that serializes Ruff AST for mypy" readme = "README.md" [lib] name = "ast_serialize" crate-type = ["cdylib"] # A workspace for building vendored Ruff crates. # Note we copy workspace values from Ruff 0.16.3 verbatim. [workspace] members = ["crates/*"] resolver = "2" [workspace.package] edition = "2024" rust-version = "1.95" homepage = "https://docs.astral.sh/ruff" documentation = "https://docs.astral.sh/ruff" repository = "https://github.com/astral-sh/ruff" authors = ["Charlie Marsh "] license = "MIT" [workspace.dependencies] aho-corasick = { version = "1.1.3" } anstream = { version = "1.0.0" } anstyle = { version = "1.0.10" } anyhow = { version = "1.0.80" } arrayvec = { version = "0.7.6" } bitflags = { version = "2.5.0" } bstr = { version = "1.9.1" } char_str = { version = "0.0.2" } compact_str = "0.10.0" datatest-stable = { version = "0.3.3" } drop_bomb = { version = "0.1.5" } filetime = { version = "0.2.23" } get-size2 = { version = "0.10.3", features = [ "derive", "smallvec", "hashbrown", "compact-str", "ordermap", "thin-vec", ] } glob = { version = "0.3.1" } globset = { version = "0.4.14" } heck = "0.5.0" insta = { version = "1.35.1" } is-macro = { version = "0.3.5" } itertools = { version = "0.15.0" } memchr = { version = "2.7.1" } proc-macro2 = { version = "1.0.79" } quote = { version = "1.0.23" } regex = { version = "1.10.2" } rustc-hash = { version = "2.0.0" } salsa = { version = "0.28.2", default-features = false, features = [ "compact_str", "macros", "salsa_unstable", "inventory", ] } schemars = { version = "1.0.4" } seahash = { version = "4.1.0" } serde = { version = "1.0.197", features = ["derive"] } serde_json = { version = "1.0.113" } serde_test = { version = "1.0.152" } snapbox = { version = "1.0.0", features = [ "diff", "term-svg", "cmd", "examples", ] } static_assertions = "1.1.0" syn = { version = "3.0.0" } thin-vec = { version = "0.2.14" } thiserror = { version = "2.0.0" } unicode-ident = { version = "1.0.12" } unicode-normalization = { version = "0.1.23" } unicode-width = { version = "0.2.0" } unicode_names2 = { version = "1.2.2" } walkdir = { version = "2.3.2" } # Cross-references between Ruff crates. ruff_annotate_snippets = { path = "crates/ruff_annotate_snippets" } ruff_cache = { path = "crates/ruff_cache" } ruff_macros = { path = "crates/ruff_macros" } ruff_python_ast = { path = "crates/ruff_python_ast" } ruff_python_trivia = { path = "crates/ruff_python_trivia" } ruff_source_file = { path = "crates/ruff_source_file" } ruff_text_size = { path = "crates/ruff_text_size" } [workspace.lints.rust] unsafe_code = "warn" unreachable_pub = "warn" unexpected_cfgs = { level = "warn", check-cfg = [ "cfg(fuzzing)", "cfg(codspeed)", ] } [dependencies] # PyO3 for Python bindings # Base features always enabled; abi3-py39 is added via stable-abi feature pyo3 = { version = "0.29.2", features = ["extension-module"] } # Ruff dependencies for parsing Python (vendored, see above). ruff_python_ast = { path = "crates/ruff_python_ast" } ruff_python_parser = { path = "crates/ruff_python_parser" } ruff_source_file = { path = "crates/ruff_source_file" } ruff_text_size = { path = "crates/ruff_text_size" } # Error handling anyhow = "1.0" # Vec types used by Ruff crates thin-vec = { version = "0.2.14" } # Hashing sha1 = "0.10" [dev-dependencies] indoc = "2" [features] # Default: stable ABI for regular Python 3.9+ default = ["stable-abi"] # Stable ABI wheels (cp39-abi3) - compatible with Python 3.9+ # Stable ABI wheels free-threaded (cp315-abit3t) - compatible with Python 3.15+ stable-abi = ["pyo3/abi3-py39", "pyo3/abi3t-py315"] # Free-threaded Python wheels (cp313t) - for nogil Python free-threaded = [] # Turn off rayon for profiling singlethreaded = [] [lints.rust] unsafe_code = "warn" unreachable_pub = "warn" [lints.clippy] pedantic = { level = "warn", priority = -2 } # Allowed pedantic lints (adjust based on your preferences) missing_errors_doc = "allow" missing_panics_doc = "allow" module_name_repetitions = "allow" # Restriction lints print_stdout = "warn" print_stderr = "warn" dbg_macro = "warn" ast_serialize-0.13.1/LICENSE000064400000000000000000000024011046102023000123460ustar00ast_serialize is licensed under the terms of the MIT license, reproduced below. Ruff crates are licensed under the terms of the MIT license, reproduced in crates/LICENSE. = = = = = The MIT License Copyright (c) 2025-2026 Jukka Lehtosalo and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ast_serialize-0.13.1/README.md000064400000000000000000000115661046102023000126340ustar00# ast_serialize - Python Parser and AST Serializer This is a fast Python extension for parsing Python files and serializing the AST using the native binary format used by mypy. This will eventually replace the current mypy parser, which uses the Python stdlib `ast` module for parsing. **This is work in progress.** ## Development Prerequisites: - Recent Rust toolchain - Python 3.10+ (3.13t or 3.14t for free-threaded builds) - [maturin](https://github.com/PyO3/maturin): `pip install maturin` - Checkout of [mypy repo](https://github.com/python/mypy) for testing Development build (fast compilation, unoptimized): ```bash maturin develop ``` Optimized development build: ```bash maturin develop --release ``` ## Testing **Rust unit tests:** ```bash cargo test ``` **Python integration tests:** Run end-to-end parser and serialization/deserialization tests using mypy's test suite in the new-parser branch: ```bash cd ~/src/mypy [or wherever you have mypy] pytest mypy -k NativeParser ``` Add new test cases to `test-data/unit/native-parser.test` (in the mypy repository). See the main parser test cases in `parse.test` for the expected output format. **Note:** Run `maturin develop` before testing if you've modified Rust code. Use `TEST_NATIVE_PARSER=1 pytest mypy/test/testcheck.py` to run mypy type checking tests using ast_serialize. Note that some tests are still skipped. ## Creating PRs You can create PRs in this repository, and/or in mypy repo. Contributions are welcome! Run mypy tests (see above) to get ideas about bugs and missing functionality. If your contributions needs changes in both mypy and ast_serialize, please mention this in the PR summary. ## Building Wheels ```bash # Build all wheels (stable ABI + free-threaded) ./build_wheels.sh # Or manually: # Stable ABI wheel (Python 3.9+) maturin build --release # Free-threaded wheel (Python 3.13t) maturin build --release --no-default-features --features free-threaded --interpreter python3.13t ``` If you see `Python 3.13t not found`, you'll need to install the free-threaded build of CPython 3.13 in PATH. ## Making a release 1. Bump the version number in `pyproject.toml` and `Cargo.toml` (including vendored crates) in this repository. 2. Update `test_ast_serialize.py` (optional but recommended if the release includes major features). 3. Commit and push (pushing directly to master is fine). 4. Wait until all [builds](https://github.com/mypyc/ast_serialize/actions) complete successfully (no release is triggered yet). 5. Once builds are complete, tag the release (`git tag vX.Y.Z`; `git push origin vX.Y.Z`). 6. Go to the ["Actions" tab](https://github.com/mypyc/ast_serialize/actions) and click "Build wheels" on the left. 7. Click "Run workflow" and pick the newly created tag from the drop-down list. This will build *and upload* the wheels. 8. After the workflow completes, verify that `pip install -U ast-serialize` installs the new version from PyPI using a compiled wheel. 9. Create a PR to update the `ast-serialize` version in `pyproject.toml` in the mypy repository. The process should take about 15 minutes. ## Vendored Ruff crates To facilitate packaging/distributing `ast_serialize` we vendor Ruff crates that are necessary for Ruff parser. They are located in `crates/` directory, and their shared config is in `[workspace]` section of `Cargo.toml`. Note we include a minimal required subset of Ruff (and thus only a subset of its third party dependencies). The process of updating the Ruff crates is following: 1. Clone [Ruff repo](https://github.com/astral-sh/ruff) and checkout the desired tag. 2. Run `python3 bump_ruff_deps.py` (requires `tomlkit` to preserve TOML formatting). This will copy all Ruff crates that we use, will copy versions of all current `[workspace.dependencies]` from Ruff, and will change the versions of the Ruff crates in their `Cargo.toml` files (e.g. `crates/ruff_python_ast/Cargo.toml`) to this format: `-ast-serialize.`, e.g. `0.0.0-ast-serialize.0.8.0`. 3. Fix `cargo test` until it passes. This may require adding new third party dependencies (including more Ruff crates), updating Rust version, and fixing any Ruff internal API changes. ## Using Coding Agents This project is designed to support coding agent assisted development (such as Claude Code, Codex or OpenCode). Notes: * Ensure your coding agent has access to AGENTS.md (e.g. create a CLAUDE.md symbolic link). * For the best experience, clone this repository as `~/src/ast_serialize`, and clone mypy (with the new-parser branch checked out) as `~/src/mypy`. * Have your mypy virtualenv active when starting the coding agent, or place the virtualenv at `~/venv/mypy` (this is referred to in AGENTS.md). ## Acknowledgments This is a wrapper around the [Ruff](https://github.com/astral-sh/ruff) parser. Credits to Ruff maintainers for developing a fast Python parser! ## License MIT ast_serialize-0.13.1/ast_serialize.pyi000064400000000000000000000020241046102023000147230ustar00from typing import TypedDict, type_check_only from typing_extensions import NotRequired, TypeAlias __all__ = ["parse", "parse_type_string"] _TypeIgnores: TypeAlias = list[tuple[int, list[str]]] @type_check_only class ParseError(TypedDict): line: int column: int message: str blocker: NotRequired[bool] code: NotRequired[str] @type_check_only class _ASTData(TypedDict): is_partial_package: bool uses_template_strings: bool mypy_ignores: _TypeIgnores source_hash: str mypy_comments: list[tuple[int, str]] def parse( fnam: str, source: str | bytes | None = None, skip_function_bodies: bool = False, python_version: tuple[int, int] | None = None, platform: str | None = None, always_true: list[str] | None = None, always_false: list[str] | None = None, cache_version: int = 0, ) -> tuple[bytes, list[ParseError], _TypeIgnores, bytes, _ASTData]: ... def parse_type_string( source: str, range: tuple[int, int, int, int], cache_version: int = 0 ) -> bytes: ... ast_serialize-0.13.1/build_wheels.sh000064400000000000000000000023001046102023000143410ustar00#!/usr/bin/env bash # Build script for creating both stable ABI and free-threaded wheels set -e # Exit on error echo "======================================" echo "Building Python wheels for ast_serialize" echo "======================================" echo "" # Build stable ABI wheel for Python 3.9+ echo "📦 Building stable ABI wheel (Python 3.9+)..." maturin build --release --features stable-abi echo "✓ Stable ABI wheel complete" echo "" # Build free-threaded wheel for Python 3.13t (if available) echo "📦 Building free-threaded wheel (Python 3.13t)..." if command -v python3.13t &> /dev/null; then maturin build --release --no-default-features --features free-threaded --interpreter python3.13t echo "✓ Free-threaded wheel complete" else echo "⚠️ Python 3.13t not found - skipping free-threaded build" echo " Install free-threaded Python to build this variant" fi echo "" # List all built wheels echo "======================================" echo "Built wheels:" echo "======================================" ls -lh ../../target/wheels/ast_serialize-*.whl 2>/dev/null || echo "No wheels found in target/wheels/" echo "" echo "Wheels location: $(pwd)/../../target/wheels/" ast_serialize-0.13.1/bump_ruff_deps.py000064400000000000000000000024401046102023000147160ustar00import shutil import subprocess import tomlkit CRATES = [ "ruff_cache", "ruff_python_ast", "ruff_python_trivia", "ruff_text_size", "ruff_annotate_snippets", "ruff_macros", "ruff_python_parser", "ruff_source_file", ] with open("Cargo.toml") as f: local_cargo = tomlkit.load(f) local_version = local_cargo["package"]["version"] for crate in CRATES: shutil.rmtree(f"crates/{crate}") shutil.copytree(f"../ruff/crates/{crate}", f"crates/{crate}") with open(f"crates/{crate}/Cargo.toml") as f: crate_toml = tomlkit.load(f) crate_version = crate_toml["package"]["version"] crate_toml["package"]["version"] = f"{crate_version}-ast-serialize.{local_version}" with open(f"crates/{crate}/Cargo.toml", "w") as f: crate_toml = tomlkit.dump(crate_toml, f) subprocess.run(["git", "add", "-A", "crates"]) with open("../ruff/Cargo.toml") as f: ruff_cargo = tomlkit.load(f) local_deps = local_cargo["workspace"]["dependencies"] ruff_deps = ruff_cargo["workspace"]["dependencies"] for dep in local_deps.copy(): if dep.startswith("ruff_"): continue if dep not in ruff_deps: del local_deps[dep] else: local_deps[dep] = ruff_deps[dep] with open("Cargo.toml", "w") as f: tomlkit.dump(local_cargo, f) ast_serialize-0.13.1/clippy.toml000064400000000000000000000000621046102023000135370ustar00doc-valid-idents = [ "CPython", "PyO3", ] ast_serialize-0.13.1/crates/LICENSE000064400000000000000000000503731046102023000136420ustar00MIT License Copyright (c) 2022 Charles Marsh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. end of terms and conditions The externally maintained libraries from which parts of the Software is derived are: - autoflake, licensed as follows: """ Copyright (C) 2012-2018 Steven Myint Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - autotyping, licensed as follows: """ MIT License Copyright (c) 2023 Jelle Zijlstra Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - Flake8, licensed as follows: """ == Flake8 License (MIT) == Copyright (C) 2011-2013 Tarek Ziade Copyright (C) 2012-2016 Ian Cordasco Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - flake8-eradicate, licensed as follows: """ MIT License Copyright (c) 2018 Nikita Sobolev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - flake8-pyi, licensed as follows: """ The MIT License (MIT) Copyright (c) 2016 Łukasz Langa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - flake8-simplify, licensed as follows: """ MIT License Copyright (c) 2020 Martin Thoma Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - isort, licensed as follows: """ The MIT License (MIT) Copyright (c) 2013 Timothy Edmund Crosley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - pygrep-hooks, licensed as follows: """ Copyright (c) 2018 Anthony Sottile Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - pycodestyle, licensed as follows: """ Copyright © 2006-2009 Johann C. Rocholl Copyright © 2009-2014 Florent Xicluna Copyright © 2014-2020 Ian Lee Licensed under the terms of the Expat License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - pydocstyle, licensed as follows: """ Copyright (c) 2012 GreenSteam, Copyright (c) 2014-2020 Amir Rachum, Copyright (c) 2020 Sambhav Kothari, Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - Pyflakes, licensed as follows: """ Copyright 2005-2011 Divmod, Inc. Copyright 2013-2014 Florent Xicluna Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - Pyright, licensed as follows: """ MIT License Pyright - A static type checker for the Python language Copyright (c) Microsoft Corporation. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE """ - pyupgrade, licensed as follows: """ Copyright (c) 2017 Anthony Sottile Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - rome/tools, licensed under the MIT license: """ MIT License Copyright (c) Rome Tools, Inc. and its affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - RustPython, licensed as follows: """ MIT License Copyright (c) 2020 RustPython Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - rust-analyzer/text-size, licensed under the MIT license: """ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ ast_serialize-0.13.1/crates/ruff_annotate_snippets/Cargo.toml000064400000000000000000000054771046102023000213520ustar00[package] name = "ruff_annotate_snippets" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = "MIT OR Apache-2.0" readme = "README.md" [dependencies] anstyle = { workspace = true } memchr = { workspace = true, optional = true } unicode-width = { workspace = true } [dev-dependencies] ruff_annotate_snippets = { path = ".", features = ["testing-colors"] } anstream = { workspace = true } snapbox = { workspace = true } [features] default = ["std", "simd"] std = ["anstyle/std", "memchr?/std"] simd = ["dep:memchr"] testing-colors = [] # Using upstream lints [lints.rust] rust_2018_idioms = { level = "warn", priority = -1 } unnameable_types = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" [lints.clippy] disallowed_methods = "allow" # HACK: minimize changes from upstream bool_assert_comparison = "allow" branches_sharing_code = "allow" checked_conversions = "warn" collapsible_else_if = "allow" create_dir = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" doc_markdown = "warn" empty_enums = "warn" enum_glob_use = "warn" expl_impl_clone_on_copy = "warn" explicit_deref_methods = "warn" explicit_into_iter_loop = "warn" fallible_impl_from = "warn" filter_map_next = "warn" flat_map_option = "warn" float_cmp_const = "warn" fn_params_excessive_bools = "warn" from_iter_instead_of_collect = "warn" if_same_then_else = "allow" implicit_clone = "warn" imprecise_flops = "warn" inconsistent_struct_constructor = "warn" inefficient_to_string = "warn" infinite_loop = "warn" invalid_upcast_comparisons = "warn" large_digit_groups = "warn" large_stack_arrays = "warn" large_types_passed_by_value = "warn" let_and_return = "allow" # sometimes good to name what you are returning linkedlist = "warn" lossy_float_literal = "warn" macro_use_imports = "warn" mem_forget = "warn" mutex_integer = "warn" needless_continue = "allow" needless_for_each = "warn" negative_feature_names = "warn" path_buf_push_overwrite = "warn" ptr_as_ptr = "warn" rc_mutex = "warn" redundant_feature_names = "warn" ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" result_large_err = "allow" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" str_to_string = "warn" string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" todo = "warn" trait_duplication_in_bounds = "warn" uninlined_format_args = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" [lib] name = "annotate_snippets" test = false ast_serialize-0.13.1/crates/ruff_annotate_snippets/LICENSE-APACHE000064400000000000000000000261361046102023000213410ustar00 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ast_serialize-0.13.1/crates/ruff_annotate_snippets/LICENSE-MIT000064400000000000000000000020461046102023000210430ustar00Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ast_serialize-0.13.1/crates/ruff_annotate_snippets/README.md000064400000000000000000000014651046102023000206720ustar00This is a fork of the [`annotate-snippets` crate]. The principle motivation for this fork, at the time of writing, is [issue #167]. Specifically, we wanted to upgrade our version of `annotate-snippets`, but do so _without_ changing our diagnostic message format. This copy of `annotate-snippets` is basically identical to upstream, but with an extra `Level::None` variant that permits skipping over a new non-optional header emitted by `annotate-snippets`. More generally, it seems plausible that we may want to tweak other aspects of the output format in the future, so it might make sense to stick with our own copy so that we can be masters of our own destiny. [issue #167]: https://github.com/rust-lang/annotate-snippets-rs/issues/167 [`annotate-snippets` crate]: https://github.com/rust-lang/annotate-snippets-rs ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/custom_error.rs000064400000000000000000000022261046102023000243160ustar00use annotate_snippets::renderer::DecorStyle; use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Ztreat-err-as-bug //@ failure-status: 101 //@ error-pattern: aborting due to `-Z treat-err-as-bug=1` //@ error-pattern: [eval_static_initializer] evaluating initializer of static `C` //@ normalize-stderr: "note: .*\n\n" -> "" //@ normalize-stderr: "thread 'rustc' panicked.*:\n.*\n" -> "" //@ rustc-env:RUST_BACKTRACE=0 #![crate_type = "rlib"] pub static C: u32 = 0 - 1; //~^ ERROR could not evaluate static initializer "#; let report = &[Level::ERROR .with_name(Some("error: internal compiler error")) .primary_title("could not evaluate static initializer") .id("E0080") .element( Snippet::source(source).path("$DIR/err.rs").annotation( AnnotationKind::Primary .span(386..391) .label("attempt to compute `0_u32 - 1_u32`, which would overflow"), ), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/custom_error.svg000064400000000000000000000030421046102023000244660ustar00 error: internal compiler error[E0080]: could not evaluate static initializer ╭▸ $DIR/err.rs:11:21 │ 11 │ pub static C: u32 = 0 - 1; ╰╴ ━━━━━ attempt to compute `0_u32 - 1_u32`, which would overflow ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/custom_level.rs000064400000000000000000000040561046102023000242770ustar00use annotate_snippets::renderer::DecorStyle; use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet}; fn main() { let source = r#"// Regression test for issue #114529 // Tests that we do not ICE during const eval for a // break-with-value in contexts where it is illegal #[allow(while_true)] fn main() { [(); { while true { break 9; //~ ERROR `break` with value from a `while` loop }; 51 }]; [(); { while let Some(v) = Some(9) { break v; //~ ERROR `break` with value from a `while` loop }; 51 }]; while true { break (|| { //~ ERROR `break` with value from a `while` loop let local = 9; }); } } "#; let report = &[ Level::ERROR .primary_title("`break` with value from a `while` loop") .id("E0571") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .annotation( AnnotationKind::Primary .span(483..581) .label("can only break with a value inside `loop` or breakable block"), ) .annotation( AnnotationKind::Context .span(462..472) .label("you can't `break` with a value in a `while` loop"), ), ), Level::HELP .with_name(Some("suggestion")) .secondary_title("use `break` on its own without a value inside this `while` loop") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .patch(Patch::new(483..581, "break")), ), ]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/custom_level.svg000064400000000000000000000077151046102023000244570ustar00 error[E0571]: `break` with value from a `while` loop ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 │ 21 │ while true { │ ────────── you can't `break` with a value in a `while` loop 22 │ ┏ break (|| { //~ ERROR `break` with value from a `while` loop 23 │ ┃ let local = 9; 24 │ ┃ }); │ ┗━━━━━━━━━━┛ can only break with a value inside `loop` or breakable block ╰╴ suggestion: use `break` on its own without a value inside this `while` loop ╭╴ 22 - break (|| { //~ ERROR `break` with value from a `while` loop 23 - let local = 9; 24 - }); 22 + break; ╰╴ ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/elide_header.rs000064400000000000000000000012201046102023000241560ustar00use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#"# Docstring followed by a newline def foobar(door, bar={}): """ """ "#; let report = &[Group::with_level(Level::NOTE) .element( Snippet::source(source) .fold(false) .annotation(AnnotationKind::Primary.span(56..58).label("B006")), ) .element(Level::HELP.message("Replace with `None`; initialize within function"))]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/elide_header.svg000064400000000000000000000041721046102023000243420ustar00 ╭▸ 1 │ # Docstring followed by a newline 2 │ 3 │ def foobar(door, bar={}): │ ━━ B006 4 │ """ 5 │ """ │ ╰ help: Replace with `None`; initialize within function ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/expected_type.rs000064400000000000000000000021431046102023000244330ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#" annotations: vec![SourceAnnotation { label: "expected struct `annotate_snippets::snippet::Slice`, found reference" , range: <22, 25>,"#; let report = &[Level::ERROR .primary_title("expected type, found `22`") .element( Snippet::source(source) .line_start(26) .path("examples/footer.rs") .annotation(AnnotationKind::Primary.span(193..195).label( "expected struct `annotate_snippets::snippet::Slice`, found reference", )) .annotation( AnnotationKind::Context .span(34..50) .label("while parsing this struct"), ), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/expected_type.svg000064400000000000000000000042301046102023000246050ustar00 error: expected type, found `22` ╭▸ examples/footer.rs:29:25 │ 26 │ annotations: vec![SourceAnnotation { │ ──────────────── while parsing this struct ┆ 29 │ range: <22, 25>, ╰╴ ━━ expected struct `annotate_snippets::snippet::Slice`, found reference ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/footer.rs000064400000000000000000000016041046102023000230700ustar00use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let report = &[ Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(" slices: vec![\"A\",") .line_start(13) .path("src/multislice.rs") .annotation(AnnotationKind::Primary.span(21..24).label( "expected struct `annotate_snippets::snippet::Slice`, found reference", )), ), Group::with_title(Level::NOTE.secondary_title( "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", )), ]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/footer.svg000064400000000000000000000036011046102023000232420ustar00 error[E0308]: mismatched types ╭▸ src/multislice.rs:13:22 │ 13 │ slices: vec!["A", │ ━━━ expected struct `annotate_snippets::snippet::Slice`, found reference ╰╴ note: expected type: `snippet::Annotation` found type: `__&__snippet::Annotation` ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/format.rs000064400000000000000000000031711046102023000230630ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#") -> Option { for ann in annotations { match (ann.range.0, ann.range.1) { (None, None) => continue, (Some(start), Some(end)) if start > end_index => continue, (Some(start), Some(end)) if start >= start_index => { let label = if let Some(ref label) = ann.label { format!(" {}", label) } else { String::from("") }; return Some(format!( "{}{}{}", " ".repeat(start - start_index), "^".repeat(end - start), label )); } _ => continue, } }"#; let report = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .line_start(51) .path("src/format.rs") .fold(false) .annotation( AnnotationKind::Context .span(5..19) .label("expected `Option` because of return type"), ) .annotation( AnnotationKind::Primary .span(26..724) .label("expected enum `std::option::Option`"), ), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/format.svg000064400000000000000000000160301046102023000232340ustar00 error[E0308]: mismatched types ╭▸ src/format.rs:52:5 │ 51 │ ) -> Option<String> { │ ────────────── expected `Option<String>` because of return type 52 │ ┏ for ann in annotations { 53 │ ┃ match (ann.range.0, ann.range.1) { 54 │ ┃ (None, None) => continue, 55 │ ┃ (Some(start), Some(end)) if start > end_index => continue, 56 │ ┃ (Some(start), Some(end)) if start >= start_index => { 57 │ ┃ let label = if let Some(ref label) = ann.label { 58 │ ┃ format!(" {}", label) 59 │ ┃ } else { 60 │ ┃ String::from("") 61 │ ┃ }; 62 │ ┃ 63 │ ┃ return Some(format!( 64 │ ┃ "{}{}{}", 65 │ ┃ " ".repeat(start - start_index), 66 │ ┃ "^".repeat(end - start), 67 │ ┃ label 68 │ ┃ )); 69 │ ┃ } 70 │ ┃ _ => continue, 71 │ ┃ } 72 │ ┃ } ╰╴┗━━━━┛ expected enum `std::option::Option` ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/highlight_message.rs000064400000000000000000000044721046102023000252530ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use anstyle::AnsiColor; use anstyle::Effects; use anstyle::Style; fn main() { let source = r#"// Make sure "highlighted" code is colored purple //@ compile-flags: --error-format=human --color=always //@ edition:2018 use core::pin::Pin; use core::future::Future; use core::any::Any; fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static )>>) {} fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin, String>> + Send + 'static )>> { Box::pin(async { Err("nope".into()) }) } fn main() { query(wrapped_fn); }"#; const MAGENTA: Style = AnsiColor::Magenta.on_default().effects(Effects::BOLD); let message = format!( "expected fn pointer `{MAGENTA}for<'a>{MAGENTA:#} fn(Box<{MAGENTA}(dyn Any + Send + 'a){MAGENTA:#}>) -> Pin<_>` found fn item `fn(Box<{MAGENTA}(dyn Any + Send + 'static){MAGENTA:#}>) -> Pin<_> {MAGENTA}{{wrapped_fn}}{MAGENTA:#}`", ); let report = &[ Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/highlighting.rs") .annotation( AnnotationKind::Primary .span(553..563) .label("one type is more general than the other"), ) .annotation( AnnotationKind::Context .span(547..552) .label("arguments to this function are incorrect"), ), ) .element(Level::NOTE.message(&message)), Level::NOTE .secondary_title("function defined here") .element( Snippet::source(source) .path("$DIR/highlighting.rs") .annotation(AnnotationKind::Context.span(200..333).label("")) .annotation(AnnotationKind::Primary.span(194..199)), ), ]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/highlight_message.svg000064400000000000000000000103541046102023000254220ustar00 error[E0308]: mismatched types ╭▸ $DIR/highlighting.rs:21:11 │ 21 │ query(wrapped_fn); │ ┬──── ━━━━━━━━━━ one type is more general than the other │ │ │ arguments to this function are incorrect │ ╰ note: expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>` found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}` note: function defined here ╭▸ $DIR/highlighting.rs:10:4 │ 10 │ fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<( │ ┌────━━━━━─┘ 11 │ │ dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static 12 │ │ )>>) {} ╰╴└───┘ ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/highlight_source.rs000064400000000000000000000020261046102023000251200ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#"//@ compile-flags: -Z teach #![allow(warnings)] const CON: Vec = vec![1, 2, 3]; //~ ERROR E0010 //~| ERROR cannot call non-const method fn main() {} "#; let report = &[Level::ERROR.primary_title("allocations are not allowed in constants") .id("E0010") .element( Snippet::source(source) .path("$DIR/E0010-teach.rs") .annotation( AnnotationKind::Primary .span(72..85) .label("allocation not allowed in constants") .highlight_source(true), ), ) .element( Level::NOTE.message("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/highlight_source.svg000064400000000000000000000037201046102023000252750ustar00 error[E0010]: allocations are not allowed in constants ╭▸ $DIR/E0010-teach.rs:5:23 │ 5 │ const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010 │ ━━━━━━━━━━━━━ allocation not allowed in constants │ ╰ note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/id_hyperlink.rs000064400000000000000000000020451046102023000242530ustar00use annotate_snippets::renderer::DecorStyle; use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Zterminal-urls=yes fn main() { let () = 4; //~ ERROR } "#; let report = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .id_url("https://doc.rust-lang.org/error_codes/E0308.html") .element( Snippet::source(source) .line_start(1) .path("$DIR/terminal_urls.rs") .annotation( AnnotationKind::Primary .span(59..61) .label("expected integer, found `()`"), ) .annotation( AnnotationKind::Context .span(64..65) .label("this expression has type `{integer}`"), ), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/id_hyperlink.svg000064400000000000000000000040231046102023000244240ustar00 error[E0308]: mismatched types ╭▸ $DIR/terminal_urls.rs:3:9 │ 3 │ let () = 4; //~ ERROR │ ┯━ ─ this expression has type `{integer}` │ │ ╰╴ expected integer, found `()` ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/multi_suggestion.rs000064400000000000000000000047141046102023000252000ustar00use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#" #![allow(dead_code)] struct U { wtf: Option>>, x: T, } fn main() { U { wtf: Some(Box(U { wtf: None, x: (), })), x: () }; let _ = std::collections::HashMap(); let _ = std::collections::HashMap {}; let _ = Box {}; } "#; let report = &[ Level::ERROR .primary_title( "cannot construct `Box<_, _>` with struct literal syntax due to private fields", ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .annotation(AnnotationKind::Primary.span(295..298)), ) .element(Level::NOTE.message("private fields `0` and `1` that were not provided")), Level::HELP .secondary_title( "you might have meant to use an associated function to build this type", ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(298..301, "::new(_)")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(298..301, "::new_uninit()")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(298..301, "::new_zeroed()")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(298..301, "::new_in(_, _)")), ) .element(Level::NOTE.no_name().message("and 12 other candidates")), Level::HELP .secondary_title("consider using the `Default` trait") .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(295..295, "<")) .patch(Patch::new( 298..301, " as std::default::Default>::default()", )), ), ]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/multi_suggestion.svg000064400000000000000000000125211046102023000253460ustar00 error: cannot construct `Box<_, _>` with struct literal syntax due to private fields ╭▸ $DIR/multi-suggestion.rs:17:13 │ 17 │ let _ = Box {}; │ ━━━ │ ╰ note: private fields `0` and `1` that were not provided help: you might have meant to use an associated function to build this type ╭╴ 17 - let _ = Box {}; 17 + let _ = Box::new(_); ├╴ 17 - let _ = Box {}; 17 + let _ = Box::new_uninit(); ├╴ 17 - let _ = Box {}; 17 + let _ = Box::new_zeroed(); ├╴ 17 - let _ = Box {}; 17 + let _ = Box::new_in(_, _); │ ╰ and 12 other candidates help: consider using the `Default` trait ╭╴ 17 - let _ = Box {}; 17 + let _ = <Box as std::default::Default>::default(); ╰╴ ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/multislice.rs000064400000000000000000000012371046102023000237460ustar00use annotate_snippets::{Annotation, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let report = &[Level::ERROR .primary_title("mismatched types") .element( Snippet::>::source("Foo") .line_start(51) .fold(false) .path("src/format.rs"), ) .element( Snippet::>::source("Faa") .line_start(129) .fold(false) .path("src/display.rs"), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/multislice.svg000064400000000000000000000034151046102023000241210ustar00 error: mismatched types ╭▸ src/format.rs │ 51 │ Foo │ ⸬ src/display.rs:129 │ 129 │ Faa ╰╴ ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/struct_name_as_context.rs000064400000000000000000000015721046102023000263510ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; fn main() { let source = r#"struct S { field1: usize, field2: usize, field3: usize, field4: usize, fn foo() {}, field6: usize, } "#; let report = &[Level::ERROR .primary_title("functions are not allowed in struct definitions") .element( Snippet::source(source) .path("$DIR/struct_name_as_context.rs") .annotation(AnnotationKind::Primary.span(91..102)) .annotation(AnnotationKind::Visible.span(0..8)), ) .element( Level::HELP .message("unlike in C++, Java, and C#, functions are declared in `impl` blocks"), )]; let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); anstream::println!("{}", renderer.render(report)); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/examples/struct_name_as_context.svg000064400000000000000000000037641046102023000265310ustar00 error: functions are not allowed in struct definitions ╭▸ $DIR/struct_name_as_context.rs:6:5 │ 1 │ struct S { ┆ 6 │ fn foo() {}, │ ━━━━━━━━━━━ │ ╰ help: unlike in C++, Java, and C#, functions are declared in `impl` blocks ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/level.rs000064400000000000000000000161721046102023000216600ustar00//! [`Level`] constants for easy importing use alloc::borrow::Cow; use anstyle::Style; use crate::renderer::stylesheet::Stylesheet; use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT}; use crate::{Message, OptionCow, Title}; /// Default `error:` [`Level`] pub const ERROR: Level<'_> = Level { name: None, level: LevelInner::Error, }; /// Default `warning:` [`Level`] pub const WARNING: Level<'_> = Level { name: None, level: LevelInner::Warning, }; /// Default `info:` [`Level`] pub const INFO: Level<'_> = Level { name: None, level: LevelInner::Info, }; /// Default `note:` [`Level`] pub const NOTE: Level<'_> = Level { name: None, level: LevelInner::Note, }; /// Default `help:` [`Level`] pub const HELP: Level<'_> = Level { name: None, level: LevelInner::Help, }; /// Severity level for [`Title`]s and [`Message`]s /// /// # Example /// /// ```rust /// # use annotate_snippets::*; /// let report = &[ /// Level::ERROR.primary_title("mismatched types").id("E0308") /// .element(Level::NOTE.message("expected reference")), /// Group::with_title( /// Level::HELP.secondary_title("function defined here") /// ), /// ]; /// ``` #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Level<'a> { pub(crate) name: Option>>, pub(crate) level: LevelInner, } /// # Constructors impl<'a> Level<'a> { pub const ERROR: Level<'a> = ERROR; pub const WARNING: Level<'a> = WARNING; pub const INFO: Level<'a> = INFO; pub const NOTE: Level<'a> = NOTE; pub const HELP: Level<'a> = HELP; } impl<'a> Level<'a> { /// For the primary, or root cause, [`Group`][crate::Group] (the first) in a [`Report`][crate::Report] /// /// See [`Group::with_title`][crate::Group::with_title] /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Styled text is /// not allowed to be passed to this function. /// ///
pub fn primary_title(self, text: impl Into>) -> Title<'a> { Title { level: self, id: None, text: text.into(), allows_styling: false, is_fixable: false, } } /// For any secondary, or context, [`Group`][crate::Group]s (subsequent) in a [`Report`][crate::Report] /// /// See [`Group::with_title`][crate::Group::with_title] /// ///
/// /// Text passed to this function is allowed to be styled, as such all /// text is considered "trusted input" and has no normalizations applied to /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be /// used to normalize untrusted text before it is passed to this function. /// ///
pub fn secondary_title(self, text: impl Into>) -> Title<'a> { Title { level: self, id: None, text: text.into(), allows_styling: true, is_fixable: false, } } /// A text [`Element`][crate::Element] in a [`Group`][crate::Group] /// ///
/// /// Text passed to this function is allowed to be styled, as such all /// text is considered "trusted input" and has no normalizations applied to /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be /// used to normalize untrusted text before it is passed to this function. /// ///
pub fn message(self, text: impl Into>) -> Message<'a> { Message { level: self, text: text.into(), } } pub(crate) fn as_str(&'a self) -> &'a str { match (&self.name, self.level) { (Some(Some(name)), _) => name.as_ref(), (Some(None), _) => "", (None, LevelInner::Error) => ERROR_TXT, (None, LevelInner::Warning) => WARNING_TXT, (None, LevelInner::Info) => INFO_TXT, (None, LevelInner::Note) => NOTE_TXT, (None, LevelInner::Help) => HELP_TXT, } } pub(crate) fn style(&self, stylesheet: &Stylesheet) -> Style { self.level.style(stylesheet) } } /// # Customize the `Level` impl<'a> Level<'a> { /// Replace the name describing this [`Level`] /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
/// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/custom_level.rs")] /// ``` #[doc = include_str!("../examples/custom_level.svg")] pub fn with_name(self, name: impl Into>) -> Level<'a> { Level { name: Some(name.into().0), level: self.level, } } /// Do not show the [`Level`]s name /// /// Useful for: /// - Another layer of the application will include the level (e.g. when rendering errors) /// - [`Message`]s that are part of a previous [`Group`][crate::Group] [`Element`][crate::Element]s /// /// # Example /// /// ```rust /// # use annotate_snippets::{Group, Snippet, AnnotationKind, Level}; ///let source = r#"fn main() { /// let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types /// let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types /// }"#; /// let report = &[ /// Level::ERROR.primary_title("mismatched types").id("E0308") /// .element( /// Snippet::source(source) /// .path("$DIR/mismatched-types.rs") /// .annotation( /// AnnotationKind::Primary /// .span(105..131) /// .label("expected `&str`, found `&[u8; 0]`"), /// ) /// .annotation( /// AnnotationKind::Context /// .span(98..102) /// .label("expected due to this"), /// ), /// ) /// .element( /// Level::NOTE /// .no_name() /// .message("expected reference `&str`\nfound reference `&'static [u8; 0]`"), /// ), /// ]; /// ``` pub fn no_name(self) -> Level<'a> { self.with_name(None::<&str>) } } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub(crate) enum LevelInner { Error, Warning, Info, Note, Help, } impl LevelInner { pub(crate) fn style(self, stylesheet: &Stylesheet) -> Style { match self { LevelInner::Error => stylesheet.error, LevelInner::Warning => stylesheet.warning, LevelInner::Info => stylesheet.info, LevelInner::Note => stylesheet.note, LevelInner::Help => stylesheet.help, } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/lib.rs000064400000000000000000000057151046102023000213200ustar00//! Format [diagnostic reports][Report], including highlighting snippets of text //! //! # Example //! //! ```rust //! # #[allow(clippy::needless_doctest_main)] #![doc = include_str!("../examples/expected_type.rs")] //! ``` //! #![doc = include_str!("../examples/expected_type.svg")] //! //! # Visual overview //! //! [`Report`] //! #![doc = include_str!("../examples/multi_suggestion.svg")] //! //! ### Primary group //! //! [`Title`] //! ```text //! error: cannot construct `Box<_, _>` with struct literal syntax due to private fields //! ``` //! //! //! [`Annotation`] on a [`Snippet`] //! ```text //! ╭▸ $DIR/multi-suggestion.rs:17:13 //! │ //! 17 │ let _ = Box {}; //! │ ━━━ //! │ //! ``` //! //! [`Message`] //! ```text //! ╰ note: private fields `0` and `1` that were not provided //! ``` //! //! //! //! ### Secondary group: suggested fix //! //! [`Title`] (proposed solution) //! ```text //! help: you might have meant to use an associated function to build this type //! ``` //! //! [`Patch`] Option 1 on a [`Snippet`] //! ```text //! ╭╴ //! 21 - let _ = Box {}; //! 21 + let _ = Box::new(_); //! ├╴ //! ``` //! //! [`Patch`] Option 2 on a [`Snippet`] //! ```text //! ├╴ //! 17 - let _ = Box {}; //! 17 + let _ = Box::new_uninit(); //! ├╴ //! ``` //! //! *etc for Options 3 and 4* //! //! [`Message`] //! ```text //! ╰ and 12 other candidates //! ``` //! //! ### Secondary group: alternative suggested fix //! //! [`Title`] (proposed solution) //! ```text //! help: consider using the `Default` trait //! ``` //! //! Only [`Patch`] on a [`Snippet`] //! ```text //! ╭╴ //! 17 - let _ = Box {}; //! 17 + let _ = ::default(); //! ╰╴ //! ``` //! //! # Cargo `features` //! //! - `simd` - Speeds up folding //! //! - `testing-colors` - Makes [Renderer::styled] colors OS independent, which //! allows for easier testing when testing colored output. It should be added as //! a feature in `[dev-dependencies]`, which can be done with the following command: //! ```text //! cargo add annotate-snippets --dev --feature testing-colors //! ``` #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] #![warn(clippy::std_instead_of_alloc)] #![warn(clippy::std_instead_of_core)] #![warn(missing_debug_implementations)] extern crate alloc; use alloc::string::String; pub mod level; pub mod renderer; mod snippet; /// Normalize the string to avoid any unicode control characters. /// /// This is important for untrusted input, as it can contain /// invalid unicode sequences. pub fn normalize_untrusted_str(s: &str) -> String { renderer::normalize_whitespace(s).into_owned() } #[doc(inline)] pub use level::Level; #[doc(inline)] pub use renderer::Renderer; pub use snippet::*; #[doc = include_str!("../README.md")] #[cfg(doctest)] pub struct ReadmeDoctests; ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/margin.rs000064400000000000000000000107311046102023000236270ustar00use core::cmp::{max, min}; const ELLIPSIS_PASSING: usize = 6; const LONG_WHITESPACE: usize = 20; const LONG_WHITESPACE_PADDING: usize = 4; #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct Margin { /// The available whitespace in the left that can be consumed when centering. whitespace_left: usize, /// The column of the beginning of left-most span. span_left: usize, /// The column of the end of right-most span. span_right: usize, /// The beginning of the line to be displayed. computed_left: usize, /// The end of the line to be displayed. computed_right: usize, /// The current width of the terminal. 140 by default and in tests. pub(crate) term_width: usize, /// The end column of a span label, including the span. Doesn't account for labels not in the /// same line as the span. label_right: usize, } impl Margin { pub(crate) fn new( whitespace_left: usize, span_left: usize, span_right: usize, label_right: usize, term_width: usize, max_line_len: usize, ) -> Self { // The 6 is padding to give a bit of room for `...` when displaying: // ``` // error: message // --> file.rs:16:58 // | // 16 | ... fn foo(self) -> Self::Bar { // | ^^^^^^^^^ // ``` let mut m = Margin { whitespace_left: whitespace_left.saturating_sub(ELLIPSIS_PASSING), span_left: span_left.saturating_sub(ELLIPSIS_PASSING), span_right: span_right + ELLIPSIS_PASSING, computed_left: 0, computed_right: 0, term_width, label_right: label_right + ELLIPSIS_PASSING, }; m.compute(max_line_len); m } pub(crate) fn was_cut_left(&self) -> bool { self.computed_left > 0 } fn compute(&mut self, max_line_len: usize) { // When there's a lot of whitespace (>20), we want to trim it as it is useless. self.computed_left = if self.whitespace_left > LONG_WHITESPACE { self.whitespace_left - (LONG_WHITESPACE - LONG_WHITESPACE_PADDING) // We want some padding. } else { 0 }; // We want to show as much as possible, max_line_len is the right-most boundary for the // relevant code. self.computed_right = max(max_line_len, self.computed_left); if self.computed_right - self.computed_left > self.term_width { // Trimming only whitespace isn't enough, let's get craftier. if self.label_right.saturating_sub(self.whitespace_left) <= self.term_width // Trimming whitespace when the right-most label is somewhrere // within it would result in the label pointing to the wrong // place && self.label_right >= self.whitespace_left { // Attempt to fit the code window only trimming whitespace. self.computed_left = self.whitespace_left; self.computed_right = self.computed_left + self.term_width; } else if self.label_right - self.span_left <= self.term_width { // Attempt to fit the code window considering only the spans and labels. let padding_left = (self.term_width - (self.label_right - self.span_left)) / 2; self.computed_left = self.span_left.saturating_sub(padding_left); self.computed_right = self.computed_left + self.term_width; } else if self.span_right - self.span_left <= self.term_width { // Attempt to fit the code window considering the spans and labels plus padding. let padding_left = (self.term_width - (self.span_right - self.span_left)) / 5 * 2; self.computed_left = self.span_left.saturating_sub(padding_left); self.computed_right = self.computed_left + self.term_width; } else { // Mostly give up but still don't show the full line. self.computed_left = self.span_left; self.computed_right = self.span_right; } } } pub(crate) fn left(&self, line_len: usize) -> usize { min(self.computed_left, line_len) } pub(crate) fn right(&self, line_len: usize) -> usize { if line_len.saturating_sub(self.computed_left) <= self.term_width { line_len } else { min(line_len, self.computed_right) } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/mod.rs000064400000000000000000000347331046102023000231410ustar00//! The [Renderer] and its settings //! //! # Example //! //! ``` //! # use annotate_snippets::*; //! # use annotate_snippets::renderer::*; //! # use annotate_snippets::Level; //! let report = // ... //! # &[Group::with_title( //! # Level::ERROR //! # .primary_title("unresolved import `baz::zed`") //! # .id("E0432") //! # )]; //! //! let renderer = Renderer::styled().decor_style(DecorStyle::Unicode); //! let output = renderer.render(report); //! anstream::println!("{output}"); //! ``` pub(crate) mod render; pub(crate) mod source_map; pub(crate) mod stylesheet; mod margin; mod styled_buffer; use alloc::string::String; use crate::Report; pub(crate) use render::ElementStyle; pub(crate) use render::UnderlineParts; pub(crate) use render::normalize_whitespace; pub(crate) use render::{LineAnnotation, LineAnnotationType, char_width, num_overlap}; pub(crate) use stylesheet::Stylesheet; pub use anstyle::*; /// See [`Renderer::term_width`] pub const DEFAULT_TERM_WIDTH: usize = 140; const USE_WINDOWS_COLORS: bool = cfg!(windows) && !cfg!(feature = "testing-colors"); const BRIGHT_BLUE: Style = if USE_WINDOWS_COLORS { AnsiColor::BrightCyan.on_default() } else { AnsiColor::BrightBlue.on_default() }; /// [`Renderer::error`] applied by [`Renderer::styled`] pub const DEFAULT_ERROR_STYLE: Style = AnsiColor::BrightRed.on_default().effects(Effects::BOLD); /// [`Renderer::warning`] applied by [`Renderer::styled`] pub const DEFAULT_WARNING_STYLE: Style = if USE_WINDOWS_COLORS { AnsiColor::BrightYellow.on_default() } else { AnsiColor::Yellow.on_default() } .effects(Effects::BOLD); /// [`Renderer::info`] applied by [`Renderer::styled`] pub const DEFAULT_INFO_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); /// [`Renderer::note`] applied by [`Renderer::styled`] pub const DEFAULT_NOTE_STYLE: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD); /// [`Renderer::help`] applied by [`Renderer::styled`] pub const DEFAULT_HELP_STYLE: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD); /// [`Renderer::line_num`] applied by [`Renderer::styled`] pub const DEFAULT_LINE_NUM_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); /// [`Renderer::emphasis`] applied by [`Renderer::styled`] pub const DEFAULT_EMPHASIS_STYLE: Style = if USE_WINDOWS_COLORS { AnsiColor::BrightWhite.on_default() } else { Style::new() } .effects(Effects::BOLD); /// [`Renderer::none`] applied by [`Renderer::styled`] pub const DEFAULT_NONE_STYLE: Style = Style::new(); /// [`Renderer::context`] applied by [`Renderer::styled`] pub const DEFAULT_CONTEXT_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); /// [`Renderer::addition`] applied by [`Renderer::styled`] pub const DEFAULT_ADDITION_STYLE: Style = AnsiColor::BrightGreen.on_default(); /// [`Renderer::removal`] applied by [`Renderer::styled`] pub const DEFAULT_REMOVAL_STYLE: Style = AnsiColor::BrightRed.on_default(); /// The [Renderer] for a [`Report`] /// /// The caller is expected to detect any relevant terminal features and configure the renderer, /// including /// - ANSI Escape code support (always outputted with [`Renderer::styled`]) /// - Terminal width ([`Renderer::term_width`]) /// - Unicode support ([`Renderer::decor_style`]) /// /// # Example /// /// ``` /// # use annotate_snippets::*; /// # use annotate_snippets::renderer::*; /// # use annotate_snippets::Level; /// let report = // ... /// # &[Group::with_title( /// # Level::ERROR /// # .primary_title("unresolved import `baz::zed`") /// # .id("E0432") /// # )]; /// /// let renderer = Renderer::styled(); /// let output = renderer.render(report); /// anstream::println!("{output}"); /// ``` #[derive(Clone, Debug)] pub struct Renderer { anonymized_line_numbers: bool, term_width: usize, decor_style: DecorStyle, stylesheet: Stylesheet, hyperlink: bool, short_message: bool, cut_indicator: Option<&'static str>, } impl Renderer { /// No terminal styling pub const fn plain() -> Self { Self { anonymized_line_numbers: false, term_width: DEFAULT_TERM_WIDTH, decor_style: DecorStyle::Ascii, stylesheet: Stylesheet::plain(), hyperlink: false, short_message: false, cut_indicator: None, } } /// Default terminal styling /// /// If ANSI escape codes are not supported, either /// - Call [`Renderer::plain`] instead /// - Strip them after the fact, like with [`anstream`](https://docs.rs/anstream/latest/anstream/) /// /// # Note /// /// When testing styled terminal output, see the [`testing-colors` feature](crate#features) pub const fn styled() -> Self { Self { stylesheet: Stylesheet { error: DEFAULT_ERROR_STYLE, warning: DEFAULT_WARNING_STYLE, info: DEFAULT_INFO_STYLE, note: DEFAULT_NOTE_STYLE, help: DEFAULT_HELP_STYLE, line_num: DEFAULT_LINE_NUM_STYLE, emphasis: DEFAULT_EMPHASIS_STYLE, none: DEFAULT_NONE_STYLE, context: DEFAULT_CONTEXT_STYLE, addition: DEFAULT_ADDITION_STYLE, removal: DEFAULT_REMOVAL_STYLE, }, hyperlink: true, ..Self::plain() } } /// Abbreviate the message pub const fn short_message(mut self, short_message: bool) -> Self { self.short_message = short_message; self } /// Set the width to render within /// /// Affects the rendering of [`Snippet`][crate::Snippet]s pub const fn term_width(mut self, term_width: usize) -> Self { self.term_width = term_width; self } /// Set the character set used for rendering decor pub const fn decor_style(mut self, decor_style: DecorStyle) -> Self { self.decor_style = decor_style; self } /// Anonymize line numbers /// /// When enabled, line numbers are replaced with `LL` which is useful for tests. /// /// # Example /// /// ```text /// --> $DIR/whitespace-trimming.rs:4:193 /// | /// LL | ... let _: () = 42; /// | ^^ expected (), found integer /// | /// ``` pub const fn anonymized_line_numbers(mut self, anonymized_line_numbers: bool) -> Self { self.anonymized_line_numbers = anonymized_line_numbers; self } } impl Renderer { /// Render a diagnostic [`Report`] pub fn render(&self, groups: Report<'_>) -> String { render::render(self, groups) } } /// Customize [`Renderer::styled`] impl Renderer { /// Override the output style for [error][crate::Level::ERROR] pub const fn error(mut self, style: Style) -> Self { self.stylesheet.error = style; self } /// Override the output style for [warnings][crate::Level::WARNING] pub const fn warning(mut self, style: Style) -> Self { self.stylesheet.warning = style; self } /// Override the output style for [info][crate::Level::INFO] pub const fn info(mut self, style: Style) -> Self { self.stylesheet.info = style; self } /// Override the output style for [notes][crate::Level::NOTE] pub const fn note(mut self, style: Style) -> Self { self.stylesheet.note = style; self } /// Override the output style for [help][crate::Level::HELP] pub const fn help(mut self, style: Style) -> Self { self.stylesheet.help = style; self } /// Override the output style for line numbers in the [`Snippet`][crate::Snippet] gutter pub const fn line_num(mut self, style: Style) -> Self { self.stylesheet.line_num = style; self } /// Override the output style for emphasis for the /// [`primary_title`][crate::Level::primary_title] pub const fn emphasis(mut self, style: Style) -> Self { self.stylesheet.emphasis = style; self } /// Override the output style for [`AnnotationKind::Context`][crate::AnnotationKind::Context] pub const fn context(mut self, style: Style) -> Self { self.stylesheet.context = style; self } /// Override the output style for [`Patch`][crate::Patch] additions pub const fn addition(mut self, style: Style) -> Self { self.stylesheet.addition = style; self } /// Override the output style for [`Patch`][crate::Patch] removals pub const fn removal(mut self, style: Style) -> Self { self.stylesheet.removal = style; self } /// Override the output style for all other text pub const fn none(mut self, style: Style) -> Self { self.stylesheet.none = style; self } pub const fn hyperlink(mut self, hyperlink: bool) -> Self { self.hyperlink = hyperlink; self } /// Set the string used for when a long line is cut. /// /// The default for [`DecorStyle::Ascii`] is `...` (three `U+002E` characters). pub const fn cut_indicator(mut self, cut: &'static str) -> Self { self.cut_indicator = Some(cut); self } } /// The character set for rendering for decor #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DecorStyle { Ascii, Unicode, } impl DecorStyle { fn col_separator(&self) -> char { match self { DecorStyle::Ascii => '|', DecorStyle::Unicode => '│', } } fn note_separator(&self, is_cont: bool) -> &str { match self { DecorStyle::Ascii => "= ", DecorStyle::Unicode if is_cont => "├ ", DecorStyle::Unicode => "╰ ", } } fn multi_suggestion_separator(&self) -> &'static str { match self { DecorStyle::Ascii => "|", DecorStyle::Unicode => "├╴", } } fn file_start(&self, is_first: bool, alone: bool) -> &'static str { match self { DecorStyle::Ascii => "--> ", DecorStyle::Unicode if is_first && alone => " ─▸ ", DecorStyle::Unicode if is_first => " ╭▸ ", DecorStyle::Unicode => " ├▸ ", } } fn secondary_file_start(&self) -> &'static str { match self { DecorStyle::Ascii => "::: ", DecorStyle::Unicode => " ⸬ ", } } fn diff(&self) -> char { match self { DecorStyle::Ascii => '~', DecorStyle::Unicode => '±', } } fn margin(&self) -> &'static str { match self { DecorStyle::Ascii => "...", DecorStyle::Unicode => "…", } } fn underline(&self, is_primary: bool) -> UnderlineParts { // X0 Y0 // label_start > ┯━━━━ < underline // │ < vertical_text_line // text // multiline_start_down ⤷ X0 Y0 // top_left > ┌───╿──┘ < top_right_flat // top_left > ┏│━━━┙ < top_right // multiline_vertical > ┃│ // ┃│ X1 Y1 // ┃│ X2 Y2 // ┃└────╿──┘ < multiline_end_same_line // bottom_left > ┗━━━━━┥ < bottom_right_with_text // multiline_horizontal ^ `X` is a good letter // multiline_whole_line > ┏ X0 Y0 // ┃ X1 Y1 // ┗━━━━┛ < multiline_end_same_line // multiline_whole_line > ┏ X0 Y0 // ┃ X1 Y1 // ┃ ╿ < multiline_end_up // ┗━━┛ < bottom_right match (self, is_primary) { (DecorStyle::Ascii, true) => UnderlineParts { style: ElementStyle::UnderlinePrimary, underline: '^', label_start: '^', vertical_text_line: '|', multiline_vertical: '|', multiline_horizontal: '_', multiline_whole_line: '/', multiline_start_down: '^', bottom_right: '|', top_left: ' ', top_right_flat: '^', bottom_left: '|', multiline_end_up: '^', multiline_end_same_line: '^', multiline_bottom_right_with_text: '|', }, (DecorStyle::Ascii, false) => UnderlineParts { style: ElementStyle::UnderlineSecondary, underline: '-', label_start: '-', vertical_text_line: '|', multiline_vertical: '|', multiline_horizontal: '_', multiline_whole_line: '/', multiline_start_down: '-', bottom_right: '|', top_left: ' ', top_right_flat: '-', bottom_left: '|', multiline_end_up: '-', multiline_end_same_line: '-', multiline_bottom_right_with_text: '|', }, (DecorStyle::Unicode, true) => UnderlineParts { style: ElementStyle::UnderlinePrimary, underline: '━', label_start: '┯', vertical_text_line: '│', multiline_vertical: '┃', multiline_horizontal: '━', multiline_whole_line: '┏', multiline_start_down: '╿', bottom_right: '┙', top_left: '┏', top_right_flat: '┛', bottom_left: '┗', multiline_end_up: '╿', multiline_end_same_line: '┛', multiline_bottom_right_with_text: '┥', }, (DecorStyle::Unicode, false) => UnderlineParts { style: ElementStyle::UnderlineSecondary, underline: '─', label_start: '┬', vertical_text_line: '│', multiline_vertical: '│', multiline_horizontal: '─', multiline_whole_line: '┌', multiline_start_down: '│', bottom_right: '┘', top_left: '┌', top_right_flat: '┘', bottom_left: '└', multiline_end_up: '│', multiline_end_same_line: '┘', multiline_bottom_right_with_text: '┤', }, } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/render.rs000064400000000000000000003124221046102023000236330ustar00// Most of this file is adapted from https://github.com/rust-lang/rust/blob/160905b6253f42967ed4aef4b98002944c7df24c/compiler/rustc_errors/src/emitter.rs use alloc::borrow::Cow; use alloc::collections::BTreeMap; use alloc::string::{String, ToString}; use alloc::{format, vec, vec::Vec}; use core::cmp::{Ordering, Reverse, max, min}; use core::fmt; use anstyle::Style; use super::DecorStyle; use super::Renderer; use super::margin::Margin; use super::stylesheet::Stylesheet; use crate::level::{Level, LevelInner}; use crate::renderer::source_map::{ AnnotatedLineInfo, LineInfo, Loc, SourceMap, SplicedLines, SubstitutionHighlight, TrimmedPatch, }; use crate::renderer::styled_buffer::StyledBuffer; use crate::snippet::Id; use crate::{ Annotation, AnnotationKind, Element, Group, Message, Origin, Padding, Patch, Report, Snippet, Title, }; const ANONYMIZED_LINE_NUM: &str = "LL"; pub(crate) fn render(renderer: &Renderer, groups: Report<'_>) -> String { if renderer.short_message { render_short_message(renderer, groups).unwrap() } else { let lineno_offset = groups.iter().map(|g| g.lineno_offset).max().unwrap_or(0); let (max_line_num, og_primary_path, groups) = pre_process(groups); let max_line_num_len = lineno_offset + if renderer.anonymized_line_numbers { ANONYMIZED_LINE_NUM.len() } else { num_decimal_digits(max_line_num) }; let mut out_string = String::new(); let group_len = groups.len(); for ( g, PreProcessedGroup { group, elements, primary_path, max_depth, }, ) in groups.into_iter().enumerate() { let mut buffer = StyledBuffer::new(); let level = group.primary_level.clone(); let mut message_iter = elements.into_iter().enumerate().peekable(); if let Some(title) = &group.title { let peek = message_iter.peek().map(|(_, s)| s); let title_style = if title.allows_styling { TitleStyle::Header } else { TitleStyle::MainHeader }; let buffer_msg_line_offset = buffer.num_lines(); render_title( renderer, &mut buffer, title, max_line_num_len, title_style, matches!(peek, Some(PreProcessedElement::Message(_))), buffer_msg_line_offset, ); let buffer_msg_line_offset = buffer.num_lines(); if matches!(peek, Some(PreProcessedElement::Message(_))) { draw_col_separator_no_space( renderer, &mut buffer, buffer_msg_line_offset, max_line_num_len + 1, ); } if peek.is_none() && title_style == TitleStyle::MainHeader && g == 0 && group_len > 1 { draw_col_separator_end( renderer, &mut buffer, buffer_msg_line_offset, max_line_num_len + 1, ); } } let mut seen_primary = false; let mut last_suggestion_path = None; while let Some((i, section)) = message_iter.next() { let peek = message_iter.peek().map(|(_, s)| s); let is_first = i == 0; match section { PreProcessedElement::Message(title) => { let title_style = TitleStyle::Secondary; let buffer_msg_line_offset = buffer.num_lines(); render_title( renderer, &mut buffer, title, max_line_num_len, title_style, peek.is_some(), buffer_msg_line_offset, ); } PreProcessedElement::Cause((cause, source_map, annotated_lines)) => { let is_primary = primary_path == cause.path.as_ref() && !seen_primary; seen_primary |= is_primary; render_snippet_annotations( renderer, &mut buffer, max_line_num_len, cause, is_primary, &source_map, &annotated_lines, max_depth, peek.is_some() || (g == 0 && group_len > 1), is_first, ); if g == 0 { let current_line = buffer.num_lines(); match peek { Some(PreProcessedElement::Message(_)) => { draw_col_separator_no_space( renderer, &mut buffer, current_line, max_line_num_len + 1, ); } None if group_len > 1 => draw_col_separator_end( renderer, &mut buffer, current_line, max_line_num_len + 1, ), _ => {} } } } PreProcessedElement::Suggestion(( suggestion, source_map, spliced_lines, display_suggestion, )) => { let matches_previous_suggestion = last_suggestion_path == Some((Some(suggestion.path.as_ref()), suggestion.cell_index)); emit_suggestion_default( renderer, &mut buffer, suggestion, spliced_lines, display_suggestion, max_line_num_len, &source_map, primary_path.or(og_primary_path), matches_previous_suggestion, is_first, //matches!(peek, Some(Element::Message(_) | Element::Padding(_))), peek.is_some(), ); if matches!(peek, Some(PreProcessedElement::Suggestion(_))) { last_suggestion_path = Some((Some(suggestion.path.as_ref()), suggestion.cell_index)); } else { last_suggestion_path = None; } } PreProcessedElement::Origin(origin) => { let buffer_msg_line_offset = buffer.num_lines(); let is_primary = primary_path == origin.path.as_ref() && !seen_primary; seen_primary |= is_primary; render_origin( renderer, &mut buffer, max_line_num_len, origin, is_primary, is_first, peek.is_none(), buffer_msg_line_offset, ); let current_line = buffer.num_lines(); if g == 0 && peek.is_none() && group_len > 1 { draw_col_separator_end( renderer, &mut buffer, current_line, max_line_num_len + 1, ); } } PreProcessedElement::Padding(_) => { let current_line = buffer.num_lines(); if peek.is_none() { draw_col_separator_end( renderer, &mut buffer, current_line, max_line_num_len + 1, ); } else { draw_col_separator_no_space( renderer, &mut buffer, current_line, max_line_num_len + 1, ); } } } } buffer .render(&level, &renderer.stylesheet, &mut out_string) .unwrap(); if g != group_len - 1 { out_string.push('\n'); } } out_string } } fn render_short_message(renderer: &Renderer, groups: &[Group<'_>]) -> Result { let mut buffer = StyledBuffer::new(); let mut labels = None; let group = groups.first().expect("Expected at least one group"); let Some(title) = &group.title else { panic!("Expected a Title"); }; if let Some(Element::Cause(cause)) = group .elements .iter() .find(|e| matches!(e, Element::Cause(_))) { let labels_inner = cause .markers .iter() .filter_map(|ann| match &ann.label { Some(msg) if ann.kind.is_primary() => { if !msg.trim().is_empty() { Some(msg.to_string()) } else { None } } _ => None, }) .collect::>() .join(", "); if !labels_inner.is_empty() { labels = Some(labels_inner); } if let Some(path) = &cause.path { let mut origin = Origin::path(path.as_ref()).cell_index(cause.cell_index); let source_map = SourceMap::new(&cause.source, cause.line_start); let (_depth, annotated_lines) = source_map.annotated_lines(cause.markers.clone(), cause.fold); if let Some(primary_line) = annotated_lines .iter() .find(|l| l.annotations.iter().any(LineAnnotation::is_primary)) .or(annotated_lines.iter().find(|l| !l.annotations.is_empty())) { origin.line = Some(primary_line.line_index); if let Some(first_annotation) = primary_line .annotations .iter() .min_by_key(|a| (Reverse(a.is_primary()), a.start.char)) { origin.char_column = Some(first_annotation.start.char + 1); } } render_origin(renderer, &mut buffer, 0, &origin, true, true, true, 0); buffer.append(0, ": ", ElementStyle::LineAndColumn); } } render_title( renderer, &mut buffer, title, 0, // No line numbers in short messages TitleStyle::MainHeader, false, 0, ); if let Some(labels) = labels { buffer.append(0, &format!(": {labels}"), ElementStyle::NoStyle); } let mut out_string = String::new(); buffer.render(&title.level, &renderer.stylesheet, &mut out_string)?; Ok(out_string) } #[allow(clippy::too_many_arguments)] fn render_title( renderer: &Renderer, buffer: &mut StyledBuffer, title: &dyn MessageOrTitle, max_line_num_len: usize, title_style: TitleStyle, is_cont: bool, buffer_msg_line_offset: usize, ) { let (label_style, title_element_style) = match title_style { TitleStyle::MainHeader => ( ElementStyle::Level(title.level().level), if renderer.short_message { ElementStyle::NoStyle } else { ElementStyle::MainHeaderMsg }, ), TitleStyle::Header => ( ElementStyle::Level(title.level().level), ElementStyle::HeaderMsg, ), TitleStyle::Secondary => { for _ in 0..max_line_num_len { buffer.append(buffer_msg_line_offset, " ", ElementStyle::NoStyle); } draw_note_separator( renderer, buffer, buffer_msg_line_offset, max_line_num_len + 1, is_cont, ); (ElementStyle::MainHeaderMsg, ElementStyle::NoStyle) } }; let mut label_width = 0; if title.level().name != Some(None) { buffer.append(buffer_msg_line_offset, title.level().as_str(), label_style); label_width += title.level().as_str().len(); if let Some(Id { id: Some(id), url }) = &title.id() { buffer.append(buffer_msg_line_offset, "[", label_style); if renderer.hyperlink && let Some(url) = url.as_ref() { buffer.append( buffer_msg_line_offset, &format!("\x1B]8;;{url}\x1B\\"), label_style, ); } buffer.append(buffer_msg_line_offset, id, label_style); if renderer.hyperlink && url.is_some() { buffer.append(buffer_msg_line_offset, "\x1B]8;;\x1B\\", label_style); } buffer.append(buffer_msg_line_offset, "]", label_style); label_width += 2 + id.len(); } if title.is_fixable() { buffer.append(buffer_msg_line_offset, "[", ElementStyle::NoStyle); buffer.append( buffer_msg_line_offset, "*", ElementStyle::Level(LevelInner::Help), ); buffer.append(buffer_msg_line_offset, "]", ElementStyle::NoStyle); label_width += 3; } buffer.append(buffer_msg_line_offset, ": ", title_element_style); label_width += 2; } else { if let Some(Id { id: Some(id), url }) = &title.id() { if renderer.hyperlink && let Some(url) = url.as_ref() { buffer.append( buffer_msg_line_offset, &format!("\x1B]8;;{url}\x1B\\"), label_style, ); } buffer.append(buffer_msg_line_offset, id, label_style); if renderer.hyperlink && url.is_some() { buffer.append(buffer_msg_line_offset, "\x1B]8;;\x1B\\", label_style); } label_width += id.len(); if title.is_fixable() { buffer.append(buffer_msg_line_offset, " [", ElementStyle::NoStyle); buffer.append( buffer_msg_line_offset, "*", ElementStyle::Level(LevelInner::Help), ); buffer.append(buffer_msg_line_offset, "]", ElementStyle::NoStyle); label_width += 4; } buffer.append(buffer_msg_line_offset, " ", title_element_style); label_width += 1; } } let padding = " ".repeat(if title_style == TitleStyle::Secondary { // The extra 3 ` ` is padding that's always needed to align to the // label i.e. `note: `: // // error: message // --> file.rs:13:20 // | // 13 | // | ^^^^ // | // = note: multiline // message // ++^^^------ // | | | // | | | // | | width of label // | magic `3` // `max_line_num_len` max_line_num_len + 3 + label_width } else { label_width }); let (title_str, style) = if title.allows_styling() { (Cow::Borrowed(title.text()), ElementStyle::NoStyle) } else { (normalize_whitespace(title.text()), title_element_style) }; for (i, text) in title_str.split('\n').enumerate() { #[allow(clippy::collapsible_if, reason = "reduce upstream divergence")] if i != 0 { if title_style == TitleStyle::Secondary && is_cont && matches!(renderer.decor_style, DecorStyle::Unicode) { buffer.append(buffer_msg_line_offset + i, &padding, ElementStyle::NoStyle); // There's another note after this one, associated to the subwindow above. // We write additional vertical lines to join them: // ╭▸ test.rs:3:3 // │ // 3 │ code // │ ━━━━ // │ // ├ note: foo // │ bar // ╰ note: foo // bar draw_col_separator_no_space( renderer, buffer, buffer_msg_line_offset + i, max_line_num_len + 1, ); } } buffer.append(buffer_msg_line_offset + i, text, style); } } #[allow(clippy::too_many_arguments)] fn render_origin( renderer: &Renderer, buffer: &mut StyledBuffer, max_line_num_len: usize, origin: &Origin<'_>, is_primary: bool, is_first: bool, alone: bool, buffer_msg_line_offset: usize, ) { if !renderer.short_message { for _ in 0..max_line_num_len { buffer.append(buffer_msg_line_offset, " ", ElementStyle::NoStyle); } } if is_primary && !renderer.short_message { buffer.append( buffer_msg_line_offset, renderer.decor_style.file_start(is_first, alone), ElementStyle::LineNumber, ); } else if !renderer.short_message { // if !origin.standalone { // // Add spacing line, as shown: // // --> $DIR/file:54:15 // // | // // LL | code // // | ^^^^ // // | (<- It prints *this* line) // // ::: $DIR/other_file.rs:15:5 // // | // // LL | code // // | ---- // draw_col_separator_no_space(renderer, // buffer, // buffer_msg_line_offset, // max_line_num_len + 1, // ); // // buffer_msg_line_offset += 1; // } // Then, the secondary file indicator buffer.append( buffer_msg_line_offset, renderer.decor_style.secondary_file_start(), ElementStyle::LineNumber, ); } let str = format_origin(origin, renderer.anonymized_line_numbers); buffer.append(buffer_msg_line_offset, &str, ElementStyle::LineAndColumn); } fn format_origin(origin: &Origin<'_>, anonymized_line_numbers: bool) -> String { use core::fmt::Write as _; let mut buffer = String::new(); if let Some(path) = &origin.path { write!(&mut buffer, "{path}").unwrap(); } if let Some(cell_index) = origin.cell_index { if !buffer.is_empty() { write!(&mut buffer, ":").unwrap(); } write!(&mut buffer, "cell {cell_index}").unwrap(); } if let Some(line) = origin.line { if anonymized_line_numbers { write!(&mut buffer, ":{ANONYMIZED_LINE_NUM}").unwrap(); } else { write!(&mut buffer, ":{line}").unwrap(); } if let Some(col) = origin.char_column { write!(&mut buffer, ":{col}").unwrap(); } } buffer } #[allow(clippy::too_many_arguments)] fn render_snippet_annotations( renderer: &Renderer, buffer: &mut StyledBuffer, max_line_num_len: usize, snippet: &Snippet<'_, Annotation<'_>>, is_primary: bool, sm: &SourceMap<'_>, annotated_lines: &[AnnotatedLineInfo<'_>], multiline_depth: usize, is_cont: bool, is_first: bool, ) { let show_snippet = !snippet.markers.iter().any(|s| s.is_file_level); if let Some(path) = &snippet.path { let mut origin = Origin::path(path.as_ref()).cell_index(snippet.cell_index); // print out the span location and spacer before we print the annotated source // to do this, we need to know if this span will be primary //let is_primary = primary_path == Some(&origin.path); if is_primary { if let Some(primary_line) = annotated_lines .iter() .find(|l| l.annotations.iter().any(LineAnnotation::is_primary)) .or(annotated_lines.iter().find(|l| !l.annotations.is_empty())) { origin.line = Some(primary_line.line_index); if let Some(first_annotation) = primary_line .annotations .iter() .min_by_key(|a| (Reverse(a.is_primary()), a.start.char)) { origin.char_column = Some(first_annotation.start.char + 1); } } } else { let buffer_msg_line_offset = buffer.num_lines(); // Add spacing line, as shown: // --> $DIR/file:54:15 // | // LL | code // | ^^^^ // | (<- It prints *this* line) // ::: $DIR/other_file.rs:15:5 // | // LL | code // | ---- draw_col_separator_no_space( renderer, buffer, buffer_msg_line_offset, max_line_num_len + 1, ); if let Some(first_line) = annotated_lines .iter() .find(|l| !l.annotations.is_empty()) .or(annotated_lines.first()) { origin.line = Some(first_line.line_index); if let Some(first_annotation) = first_line.annotations.first() { origin.char_column = Some(first_annotation.start.char + 1); } } } let buffer_msg_line_offset = buffer.num_lines(); render_origin( renderer, buffer, max_line_num_len, &origin, is_primary, is_first, !(show_snippet || is_cont), buffer_msg_line_offset, ); // Put in the spacer between the location and annotated source if show_snippet { draw_col_separator_no_space( renderer, buffer, buffer_msg_line_offset + 1, max_line_num_len + 1, ); } } else { let buffer_msg_line_offset = buffer.num_lines(); if is_primary { if renderer.decor_style == DecorStyle::Unicode { buffer.puts( buffer_msg_line_offset, max_line_num_len, renderer.decor_style.file_start(is_first, false), ElementStyle::LineNumber, ); } else { draw_col_separator_no_space( renderer, buffer, buffer_msg_line_offset, max_line_num_len + 1, ); } } else { // Add spacing line, as shown: // --> $DIR/file:54:15 // | // LL | code // | ^^^^ // | (<- It prints *this* line) // ::: $DIR/other_file.rs:15:5 // | // LL | code // | ---- draw_col_separator_no_space( renderer, buffer, buffer_msg_line_offset, max_line_num_len + 1, ); buffer.puts( buffer_msg_line_offset + 1, max_line_num_len, renderer.decor_style.secondary_file_start(), ElementStyle::LineNumber, ); } } if !show_snippet { return; } // Contains the vertical lines' positions for active multiline annotations let mut multilines = Vec::new(); // Get the left-side margin to remove it let mut whitespace_margin = usize::MAX; for line_info in annotated_lines { let leading_whitespace = line_info .line .chars() .take_while(|c| c.is_whitespace()) .map(|c| { match c { // Tabs are displayed as 4 spaces '\t' => 4, _ => 1, } }) .sum(); if line_info.line.chars().any(|c| !c.is_whitespace()) { whitespace_margin = min(whitespace_margin, leading_whitespace); } } if whitespace_margin == usize::MAX { whitespace_margin = 0; } // Left-most column any visible span points at. let mut span_left_margin = usize::MAX; for line_info in annotated_lines { for ann in &line_info.annotations { span_left_margin = min(span_left_margin, ann.start.display); span_left_margin = min(span_left_margin, ann.end.display); } } if span_left_margin == usize::MAX { span_left_margin = 0; } // Right-most column any visible span points at. let mut span_right_margin = 0; let mut label_right_margin = 0; let mut max_line_len = 0; for line_info in annotated_lines { max_line_len = max(max_line_len, str_width(line_info.line)); for ann in &line_info.annotations { span_right_margin = max(span_right_margin, ann.start.display); span_right_margin = max(span_right_margin, ann.end.display); // FIXME: account for labels not in the same line let label_right = ann.label.as_ref().map_or(0, |l| str_width(l) + 1); label_right_margin = max(label_right_margin, ann.end.display + label_right); } } let width_offset = 3 + max_line_num_len; let code_offset = if multiline_depth == 0 { width_offset } else { width_offset + multiline_depth + 1 }; let column_width = renderer.term_width.saturating_sub(code_offset); let margin = Margin::new( whitespace_margin, span_left_margin, span_right_margin, label_right_margin, column_width, max_line_len, ); // Next, output the annotate source for this file for annotated_line_idx in 0..annotated_lines.len() { let previous_buffer_line = buffer.num_lines(); let depths = render_source_line( renderer, &annotated_lines[annotated_line_idx], buffer, width_offset, code_offset, max_line_num_len, margin, !is_cont && annotated_line_idx + 1 == annotated_lines.len(), ); let mut to_add = BTreeMap::new(); for (depth, style) in depths { if let Some(index) = multilines.iter().position(|(d, _)| d == &depth) { multilines.swap_remove(index); } else { to_add.insert(depth, style); } } // Set the multiline annotation vertical lines to the left of // the code in this line. for (depth, style) in &multilines { for line in previous_buffer_line..buffer.num_lines() { draw_multiline_line(renderer, buffer, line, width_offset, *depth, *style, false); } } // check to see if we need to print out or elide lines that come between // this annotated line and the next one. if annotated_line_idx < (annotated_lines.len() - 1) { let line_idx_delta = annotated_lines[annotated_line_idx + 1].line_index - annotated_lines[annotated_line_idx].line_index; match line_idx_delta.cmp(&2) { Ordering::Greater => { let last_buffer_line_num = buffer.num_lines(); draw_line_separator(renderer, buffer, last_buffer_line_num, width_offset); // Set the multiline annotation vertical lines on `...` bridging line. for (depth, style) in &multilines { draw_multiline_line( renderer, buffer, last_buffer_line_num, width_offset, *depth, *style, true, ); } if let Some(line) = annotated_lines.get(annotated_line_idx) { for ann in &line.annotations { if let LineAnnotationType::MultilineStart(pos) = ann.annotation_type { // In the case where we have elided the entire start of the // multispan because those lines were empty, we still need // to draw the `|`s across the `...`. draw_multiline_line( renderer, buffer, last_buffer_line_num, width_offset, pos, if ann.is_primary() { ElementStyle::UnderlinePrimary } else { ElementStyle::UnderlineSecondary }, true, ); } } } } Ordering::Equal => { let unannotated_line = sm .get_line(annotated_lines[annotated_line_idx].line_index + 1) .unwrap_or(""); let last_buffer_line_num = buffer.num_lines(); draw_line( renderer, buffer, &normalize_whitespace(unannotated_line), annotated_lines[annotated_line_idx + 1].line_index - 1, last_buffer_line_num, width_offset, code_offset, max_line_num_len, margin, ); for (depth, style) in &multilines { draw_multiline_line( renderer, buffer, last_buffer_line_num, width_offset, *depth, *style, false, ); } if let Some(line) = annotated_lines.get(annotated_line_idx) { for ann in &line.annotations { if let LineAnnotationType::MultilineStart(pos) = ann.annotation_type { draw_multiline_line( renderer, buffer, last_buffer_line_num, width_offset, pos, if ann.is_primary() { ElementStyle::UnderlinePrimary } else { ElementStyle::UnderlineSecondary }, false, ); } } } } Ordering::Less => {} } } multilines.extend(to_add); } } #[allow(clippy::too_many_arguments)] fn render_source_line( renderer: &Renderer, line_info: &AnnotatedLineInfo<'_>, buffer: &mut StyledBuffer, width_offset: usize, code_offset: usize, max_line_num_len: usize, margin: Margin, close_window: bool, ) -> Vec<(usize, ElementStyle)> { // Draw: // // LL | ... code ... // | ^^-^ span label // | | // | secondary span label // // ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it // | | | | // | | | actual code found in your source code and the spans we use to mark it // | | when there's too much wasted space to the left, trim it // | vertical divider between the column number and the code // column number let source_string = normalize_whitespace(line_info.line); let line_offset = buffer.num_lines(); let left = draw_line( renderer, buffer, &source_string, line_info.line_index, line_offset, width_offset, code_offset, max_line_num_len, margin, ); // If there are no annotations, we are done if line_info.annotations.is_empty() { // `close_window` normally gets handled later, but we are early // returning, so it needs to be handled here if close_window { draw_col_separator_end(renderer, buffer, line_offset + 1, width_offset - 2); } return vec![]; } // Special case when there's only one annotation involved, it is the start of a multiline // span and there's no text at the beginning of the code line. Instead of doing the whole // graph: // // 2 | fn foo() { // | _^ // 3 | | // 4 | | } // | |_^ test // // we simplify the output to: // // 2 | / fn foo() { // 3 | | // 4 | | } // | |_^ test let mut buffer_ops = vec![]; let mut annotations = vec![]; let mut short_start = true; for ann in &line_info.annotations { if let LineAnnotationType::MultilineStart(depth) = ann.annotation_type { if source_string .chars() .take(ann.start.display) .all(char::is_whitespace) { let uline = renderer.decor_style.underline(ann.is_primary()); let chr = uline.multiline_whole_line; annotations.push((depth, uline.style)); buffer_ops.push((line_offset, width_offset + depth - 1, chr, uline.style)); } else { short_start = false; break; } } else if let LineAnnotationType::MultilineLine(_) = ann.annotation_type { } else { short_start = false; break; } } if short_start { for (y, x, c, s) in buffer_ops { buffer.putc(y, x, c, s); } return annotations; } // We want to display like this: // // vec.push(vec.pop().unwrap()); // --- ^^^ - previous borrow ends here // | | // | error occurs here // previous borrow of `vec` occurs here // // But there are some weird edge cases to be aware of: // // vec.push(vec.pop().unwrap()); // -------- - previous borrow ends here // || // |this makes no sense // previous borrow of `vec` occurs here // // For this reason, we group the lines into "highlight lines" // and "annotations lines", where the highlight lines have the `^`. // Sort the annotations by (start, end col) // The labels are reversed, sort and then reversed again. // Consider a list of annotations (A1, A2, C1, C2, B1, B2) where // the letter signifies the span. Here we are only sorting by the // span and hence, the order of the elements with the same span will // not change. On reversing the ordering (|a, b| but b.cmp(a)), you get // (C1, C2, B1, B2, A1, A2). All the elements with the same span are // still ordered first to last, but all the elements with different // spans are ordered by their spans in last to first order. Last to // first order is important, because the jiggly lines and | are on // the left, so the rightmost span needs to be rendered first, // otherwise the lines would end up needing to go over a message. let mut annotations = line_info.annotations.clone(); annotations.sort_by_key(|a| Reverse((a.start.display, a.start.char))); // First, figure out where each label will be positioned. // // In the case where you have the following annotations: // // vec.push(vec.pop().unwrap()); // -------- - previous borrow ends here [C] // || // |this makes no sense [B] // previous borrow of `vec` occurs here [A] // // `annotations_position` will hold [(2, A), (1, B), (0, C)]. // // We try, when possible, to stick the rightmost annotation at the end // of the highlight line: // // vec.push(vec.pop().unwrap()); // --- --- - previous borrow ends here // // But sometimes that's not possible because one of the other // annotations overlaps it. For example, from the test // `span_overlap_label`, we have the following annotations // (written on distinct lines for clarity): // // fn foo(x: u32) { // -------------- // - // // In this case, we can't stick the rightmost-most label on // the highlight line, or we would get: // // fn foo(x: u32) { // -------- x_span // | // fn_span // // which is totally weird. Instead we want: // // fn foo(x: u32) { // -------------- // | | // | x_span // fn_span // // which is...less weird, at least. In fact, in general, if // the rightmost span overlaps with any other span, we should // use the "hang below" version, so we can at least make it // clear where the span *starts*. There's an exception for this // logic, when the labels do not have a message: // // fn foo(x: u32) { // -------------- // | // x_span // // instead of: // // fn foo(x: u32) { // -------------- // | | // | x_span // // let mut overlap = vec![false; annotations.len()]; let mut annotations_position = vec![]; let mut line_len: usize = 0; let mut p = 0; for (i, annotation) in annotations.iter().enumerate() { for (j, next) in annotations.iter().enumerate() { if overlaps(next, annotation, 0) && j > 1 { overlap[i] = true; overlap[j] = true; } if overlaps(next, annotation, 0) // This label overlaps with another one and both && annotation.has_label() // take space (they have text and are not && j > i // multiline lines). && p == 0 // We're currently on the first line, move the label one line down { // If we're overlapping with an un-labelled annotation with the same span // we can just merge them in the output if next.start.display == annotation.start.display && next.start.char == annotation.start.char && next.end.display == annotation.end.display && next.end.char == annotation.end.char && !next.has_label() { continue; } // This annotation needs a new line in the output. p += 1; break; } } annotations_position.push((p, annotation)); for (j, next) in annotations.iter().enumerate() { if j > i { let l = next.label.as_ref().map_or(0, |label| label.len() + 2); if (overlaps(next, annotation, l) // Do not allow two labels to be in the same // line if they overlap including padding, to // avoid situations like: // // fn foo(x: u32) { // -------^------ // | | // fn_spanx_span // && annotation.has_label() // Both labels must have some text, otherwise && next.has_label()) // they are not overlapping. // Do not add a new line if this annotation // or the next are vertical line placeholders. || (annotation.takes_space() // If either this or the next annotation is && next.has_label()) // multiline start/end, move it to a new line || (annotation.has_label() // so as not to overlap the horizontal lines. && next.takes_space()) || (annotation.takes_space() && next.takes_space()) || (overlaps(next, annotation, l) && (next.end.display, next.end.char) <= (annotation.end.display, annotation.end.char) && next.has_label() && p == 0) // Avoid #42595. { // This annotation needs a new line in the output. p += 1; break; } } } line_len = max(line_len, p); } if line_len != 0 { line_len += 1; } // If there are no annotations or the only annotations on this line are // MultilineLine, then there's only code being shown, stop processing. if line_info.annotations.iter().all(LineAnnotation::is_line) { return vec![]; } if annotations_position .iter() .all(|(_, ann)| matches!(ann.annotation_type, LineAnnotationType::MultilineStart(_))) && let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max() { // Special case the following, so that we minimize overlapping multiline spans. // // 3 │ X0 Y0 Z0 // │ ┏━━━━━┛ │ │ < We are writing these lines // │ ┃┌───────┘ │ < by reverting the "depth" of // │ ┃│┌─────────┘ < their multiline spans. // 4 │ ┃││ X1 Y1 Z1 // 5 │ ┃││ X2 Y2 Z2 // │ ┃│└────╿──│──┘ `Z` label // │ ┃└─────│──┤ // │ ┗━━━━━━┥ `Y` is a good letter too // ╰╴ `X` is a good letter for (pos, _) in &mut annotations_position { *pos = max_pos - *pos; } // We know then that we don't need an additional line for the span label, saving us // one line of vertical space. line_len = line_len.saturating_sub(1); } // Write the column separator. // // After this we will have: // // 2 | fn foo() { // | // | // | // 3 | // 4 | } // | for pos in 0..=line_len { draw_col_separator_no_space(renderer, buffer, line_offset + pos + 1, width_offset - 2); } if close_window { draw_col_separator_end( renderer, buffer, line_offset + line_len + 1, width_offset - 2, ); } // Write the horizontal lines for multiline annotations // (only the first and last lines need this). // // After this we will have: // // 2 | fn foo() { // | __________ // | // | // 3 | // 4 | } // | _ for &(pos, annotation) in &annotations_position { let underline = renderer.decor_style.underline(annotation.is_primary()); let pos = pos + 1; match annotation.annotation_type { LineAnnotationType::MultilineStart(depth) | LineAnnotationType::MultilineEnd(depth) => { draw_range( buffer, underline.multiline_horizontal, line_offset + pos, width_offset + depth, (code_offset + annotation.start.display).saturating_sub(left), underline.style, ); } _ if annotation.highlight_source => { buffer.set_style_range( line_offset, (code_offset + annotation.start.char).saturating_sub(left), (code_offset + annotation.end.char).saturating_sub(left), underline.style, annotation.is_primary(), ); } _ => {} } } // Write the vertical lines for labels that are on a different line as the underline. // // After this we will have: // // 2 | fn foo() { // | __________ // | | | // | | // 3 | | // 4 | | } // | |_ for &(pos, annotation) in &annotations_position { let underline = renderer.decor_style.underline(annotation.is_primary()); let pos = pos + 1; if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { buffer.putc( p, (code_offset + annotation.start.display).saturating_sub(left), match annotation.annotation_type { LineAnnotationType::MultilineLine(_) => underline.multiline_vertical, _ => underline.vertical_text_line, }, underline.style, ); } if let LineAnnotationType::MultilineStart(_) = annotation.annotation_type { buffer.putc( line_offset + pos, (code_offset + annotation.start.display).saturating_sub(left), underline.bottom_right, underline.style, ); } if matches!( annotation.annotation_type, LineAnnotationType::MultilineEnd(_) ) && annotation.has_label() { buffer.putc( line_offset + pos, (code_offset + annotation.start.display).saturating_sub(left), underline.multiline_bottom_right_with_text, underline.style, ); } } match annotation.annotation_type { LineAnnotationType::MultilineStart(depth) => { buffer.putc( line_offset + pos, width_offset + depth - 1, underline.top_left, underline.style, ); for p in line_offset + pos + 1..line_offset + line_len + 2 { buffer.putc( p, width_offset + depth - 1, underline.multiline_vertical, underline.style, ); } } LineAnnotationType::MultilineEnd(depth) => { for p in line_offset..line_offset + pos { buffer.putc( p, width_offset + depth - 1, underline.multiline_vertical, underline.style, ); } buffer.putc( line_offset + pos, width_offset + depth - 1, underline.bottom_left, underline.style, ); } _ => (), } } // Write the labels on the annotations that actually have a label. // // After this we will have: // // 2 | fn foo() { // | __________ // | | // | something about `foo` // 3 | // 4 | } // | _ test for &(pos, annotation) in &annotations_position { let style = if annotation.is_primary() { ElementStyle::LabelPrimary } else { ElementStyle::LabelSecondary }; let (pos, col) = if pos == 0 { if annotation.end.display == 0 { (pos + 1, (annotation.end.display + 2).saturating_sub(left)) } else { (pos + 1, (annotation.end.display + 1).saturating_sub(left)) } } else { (pos + 2, annotation.start.display.saturating_sub(left)) }; if let Some(label) = &annotation.label { buffer.puts(line_offset + pos, code_offset + col, label, style); } } // Sort from biggest span to smallest span so that smaller spans are // represented in the output: // // x | fn foo() // | ^^^---^^ // | | | // | | something about `foo` // | something about `fn foo()` annotations_position.sort_by_key(|(_, ann)| { // Decreasing order. When annotations share the same length, prefer `Primary`. (Reverse(ann.len()), ann.is_primary()) }); // Write the underlines. // // After this we will have: // // 2 | fn foo() { // | ____-_____^ // | | // | something about `foo` // 3 | // 4 | } // | _^ test for &(pos, annotation) in &annotations_position { let uline = renderer.decor_style.underline(annotation.is_primary()); for p in annotation.start.display..annotation.end.display { // The default span label underline. buffer.putc( line_offset + 1, (code_offset + p).saturating_sub(left), uline.underline, uline.style, ); } if pos == 0 && matches!( annotation.annotation_type, LineAnnotationType::MultilineStart(_) | LineAnnotationType::MultilineEnd(_) ) { // The beginning of a multiline span with its leftward moving line on the same line. buffer.putc( line_offset + 1, (code_offset + annotation.start.display).saturating_sub(left), match annotation.annotation_type { LineAnnotationType::MultilineStart(_) => uline.top_right_flat, LineAnnotationType::MultilineEnd(_) => uline.multiline_end_same_line, _ => panic!("unexpected annotation type: {annotation:?}"), }, uline.style, ); } else if pos != 0 && matches!( annotation.annotation_type, LineAnnotationType::MultilineStart(_) | LineAnnotationType::MultilineEnd(_) ) { // The beginning of a multiline span with its leftward moving line on another line, // so we start going down first. buffer.putc( line_offset + 1, (code_offset + annotation.start.display).saturating_sub(left), match annotation.annotation_type { LineAnnotationType::MultilineStart(_) => uline.multiline_start_down, LineAnnotationType::MultilineEnd(_) => uline.multiline_end_up, _ => panic!("unexpected annotation type: {annotation:?}"), }, uline.style, ); } else if pos != 0 && annotation.has_label() { // The beginning of a span label with an actual label, we'll point down. buffer.putc( line_offset + 1, (code_offset + annotation.start.display).saturating_sub(left), uline.label_start, uline.style, ); } } // We look for individual *long* spans, and we trim the *middle*, so that we render // LL | ...= [0, 0, 0, ..., 0, 0]; // | ^^^^^^^^^^...^^^^^^^ expected `&[u8]`, found `[{integer}; 1680]` for (i, (_pos, annotation)) in annotations_position.iter().enumerate() { // Skip cases where multiple spans overlap eachother. if overlap[i] { continue; }; let LineAnnotationType::Singleline = annotation.annotation_type else { continue; }; let width = annotation.end.display - annotation.start.display; static MIN_PAD: usize = 5; let cut_indicator = renderer .cut_indicator .unwrap_or(renderer.decor_style.margin()); let margin_width = str_width(cut_indicator); if width > margin.term_width * 2 && width > (MIN_PAD * 2 + margin_width) { // If the terminal is *too* small, we keep at least a tiny bit of the span for // display. let pad = max(margin.term_width / 3, MIN_PAD); // Code line buffer.replace( line_offset, code_offset + (annotation.start.display + pad).saturating_sub(left), code_offset + (annotation.end.display - pad).saturating_sub(left), cut_indicator, ); // Underline line buffer.replace( line_offset + 1, code_offset + (annotation.start.display + pad).saturating_sub(left), code_offset + (annotation.end.display - pad).saturating_sub(left), cut_indicator, ); } } annotations_position .iter() .filter_map(|&(_, annotation)| match annotation.annotation_type { LineAnnotationType::MultilineStart(p) | LineAnnotationType::MultilineEnd(p) => { let style = if annotation.is_primary() { ElementStyle::LabelPrimary } else { ElementStyle::LabelSecondary }; Some((p, style)) } _ => None, }) .collect::>() } #[allow(clippy::too_many_arguments)] fn emit_suggestion_default( renderer: &Renderer, buffer: &mut StyledBuffer, suggestion: &Snippet<'_, Patch<'_>>, spliced_lines: SplicedLines<'_>, show_code_change: DisplaySuggestion, max_line_num_len: usize, sm: &SourceMap<'_>, primary_path: Option<&Cow<'_, str>>, matches_previous_suggestion: bool, _is_first: bool, is_cont: bool, ) { let buffer_offset = buffer.num_lines(); let mut row_num = buffer_offset + usize::from(!matches_previous_suggestion); let (complete, parts, highlights, replaced_highlights) = spliced_lines; let is_multiline = complete.lines().count() > 1; let secondary_path = suggestion.path.as_ref() != primary_path; if ((secondary_path && suggestion.path.as_ref().is_some()) || suggestion.cell_index.is_some()) && !matches_previous_suggestion { let (loc, _) = sm.span_to_locations(parts[0].span.clone()); // --> file.rs:line:col // | for _ in 0..max_line_num_len { buffer.append(row_num - 1, " ", ElementStyle::NoStyle); } let arrow = renderer.decor_style.secondary_file_start(); buffer.append(row_num - 1, arrow, ElementStyle::LineNumber); let origin = Origin { path: suggestion .path .as_ref() .filter(|_| secondary_path) .map(|p| Cow::Borrowed(p.as_ref())), cell_index: suggestion.cell_index, line: Some(loc.line), char_column: Some(loc.char + 1), }; let message = format_origin(&origin, renderer.anonymized_line_numbers); buffer.append(row_num - 1, &message, ElementStyle::LineAndColumn); draw_col_separator_no_space(renderer, buffer, row_num, max_line_num_len + 1); row_num += 1; } else if matches_previous_suggestion { buffer.puts( row_num - 1, max_line_num_len + 1, renderer.decor_style.multi_suggestion_separator(), ElementStyle::LineNumber, ); } else { draw_col_separator_start(renderer, buffer, row_num - 1, max_line_num_len + 1); } if let DisplaySuggestion::Diff = show_code_change { row_num += 1; } let lo = parts.iter().map(|p| p.span.start).min().unwrap(); let hi = parts.iter().map(|p| p.span.end).max().unwrap(); let file_lines = sm.span_to_lines(lo..hi); let (line_start, line_end) = if suggestion.fold { // We use the original span to get original line_start sm.span_to_locations(parts[0].original_span.clone()) } else { sm.span_to_locations(0..sm.source.len()) }; let mut lines = complete.lines(); if lines.clone().next().is_none() { // Account for a suggestion to completely remove a line(s) with whitespace (#94192). for line in line_start.line..=line_end.line { buffer.puts( row_num - 1 + line - line_start.line, 0, &maybe_anonymized(renderer, line, max_line_num_len), ElementStyle::LineNumber, ); buffer.puts( row_num - 1 + line - line_start.line, max_line_num_len + 1, "- ", ElementStyle::Removal, ); buffer.puts( row_num - 1 + line - line_start.line, max_line_num_len + 3, &normalize_whitespace(sm.get_line(line).unwrap()), ElementStyle::Removal, ); } row_num += line_end.line - line_start.line; } let mut unhighlighted_lines = Vec::new(); for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() { // Remember lines that are not highlighted to hide them if needed if highlight_parts.is_empty() && suggestion.fold { unhighlighted_lines.push((line_pos, line)); continue; } match unhighlighted_lines.len() { 0 => (), // Since we show first line, "..." line and last line, // There is no reason to hide if there are 3 or less lines // (because then we just replace a line with ... which is // not helpful) n if n <= 3 => unhighlighted_lines.drain(..).for_each(|(p, l)| { draw_code_line( renderer, buffer, &mut row_num, &[], &[], p + line_start.line, l, show_code_change, max_line_num_len, &file_lines, is_multiline, ); }), // Print first unhighlighted line, "..." and last unhighlighted line, like so: // // LL | this line was highlighted // LL | this line is just for context // ... // LL | this line is just for context // LL | this line was highlighted _ => { let last_line = unhighlighted_lines.pop(); let first_line = unhighlighted_lines.drain(..).next(); if let Some((p, l)) = first_line { draw_code_line( renderer, buffer, &mut row_num, &[], &[], p + line_start.line, l, show_code_change, max_line_num_len, &file_lines, is_multiline, ); } let cut_indicator = renderer .cut_indicator .unwrap_or(renderer.decor_style.margin()); let padding = str_width(cut_indicator); buffer.puts( row_num, max_line_num_len.saturating_sub(padding), cut_indicator, ElementStyle::LineNumber, ); row_num += 1; if let Some((p, l)) = last_line { draw_code_line( renderer, buffer, &mut row_num, &[], &[], p + line_start.line, l, show_code_change, max_line_num_len, &file_lines, is_multiline, ); } } } draw_code_line( renderer, buffer, &mut row_num, &highlight_parts, &replaced_highlights, line_pos + line_start.line, line, show_code_change, max_line_num_len, &file_lines, is_multiline, ); } // This offset and the ones below need to be signed to account for replacement code // that is shorter than the original code. let mut offsets: Vec<(usize, isize)> = Vec::new(); // Only show an underline in the suggestions if the suggestion is not the // entirety of the code being shown and the displayed code is not multiline. if let DisplaySuggestion::Diff | DisplaySuggestion::Underline | DisplaySuggestion::Add = show_code_change { for part in parts { let (span_start, span_end) = sm.span_to_locations(part.span.clone()); let span_start_pos = span_start.display; let span_end_pos = span_end.display; // If this addition is _only_ whitespace, then don't trim it, // or else we're just not rendering anything. let is_whitespace_addition = part.replacement.trim().is_empty(); // Do not underline the leading... let start = if is_whitespace_addition { 0 } else { part.replacement .len() .saturating_sub(part.replacement.trim_start().len()) }; // ...or trailing spaces. Account for substitutions containing unicode // characters. let sub_len: usize = str_width(if is_whitespace_addition { &part.replacement } else { part.replacement.trim() }); let offset: isize = offsets .iter() .filter_map(|(start, v)| { if span_start_pos < *start { None } else { Some(v) } }) .sum(); let underline_start = (span_start_pos + start) as isize + offset; let underline_end = (span_start_pos + start + sub_len) as isize + offset; assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { if matches!(show_code_change, DisplaySuggestion::Underline) { // If this is a replacement, underline with `~`, if this is an addition // underline with `+`. buffer.putc( row_num, (padding as isize + p) as usize, if part.is_addition(sm) { '+' } else { renderer.decor_style.diff() }, ElementStyle::Addition, ); } } // length of the code after substitution let full_sub_len = str_width(&part.replacement) as isize; // length of the code to be substituted let snippet_len = span_end_pos as isize - span_start_pos as isize; // For multiple substitutions, use the position *after* the previous // substitutions have happened, only when further substitutions are // located strictly after. offsets.push((span_end_pos, full_sub_len - snippet_len)); } row_num += 1; } // if we elided some lines, add an ellipsis if lines.next().is_some() { let cut_indicator = renderer .cut_indicator .unwrap_or(renderer.decor_style.margin()); let padding = str_width(cut_indicator); buffer.puts( row_num, max_line_num_len.saturating_sub(padding), cut_indicator, ElementStyle::LineNumber, ); } else { let row = match show_code_change { DisplaySuggestion::Diff | DisplaySuggestion::Add | DisplaySuggestion::Underline => { row_num - 1 } DisplaySuggestion::None => row_num, }; if is_cont { draw_col_separator_no_space(renderer, buffer, row, max_line_num_len + 1); } else { draw_col_separator_end(renderer, buffer, row, max_line_num_len + 1); } } } #[allow(clippy::too_many_arguments)] fn draw_code_line( renderer: &Renderer, buffer: &mut StyledBuffer, row_num: &mut usize, highlight_parts: &[SubstitutionHighlight], replaced_parts: &[Vec], line_num: usize, line_to_add: &str, show_code_change: DisplaySuggestion, max_line_num_len: usize, file_lines: &[&LineInfo<'_>], is_multiline: bool, ) { if let DisplaySuggestion::Diff = show_code_change { // We need to print more than one line if the span we need to remove is multiline. // For more info: https://github.com/rust-lang/rust/issues/92741 let lines_to_remove = file_lines.iter().take(file_lines.len() - 1); for (index, (line_to_remove, parts)) in lines_to_remove.zip(replaced_parts).enumerate() { buffer.puts( *row_num - 1, 0, &maybe_anonymized(renderer, line_num + index, max_line_num_len), ElementStyle::LineNumber, ); buffer.puts( *row_num - 1, max_line_num_len + 1, "- ", ElementStyle::Removal, ); let line = normalize_whitespace(line_to_remove.line); buffer.puts( *row_num - 1, max_line_num_len + 3, &line, ElementStyle::NoStyle, ); style_substitution_highlights( parts, ElementStyle::Removal, *row_num - 1, line_to_remove.line, max_line_num_len, buffer, ); *row_num += 1; } // If the last line is exactly equal to the line we need to add, we can skip both of // them. This allows us to avoid output like the following: // 2 - & // 2 + if true { true } else { false } // 3 - if true { true } else { false } // If those lines aren't equal, we print their diff let last_line = &file_lines.last().unwrap(); if last_line.line == line_to_add { *row_num -= 2; // The last original line collapses into the previous drawn row, so // fold its replaced-code highlights onto that row too. style_substitution_highlights( replaced_parts.last().unwrap(), ElementStyle::Removal, *row_num, last_line.line, max_line_num_len, buffer, ); } else { buffer.puts( *row_num - 1, 0, &maybe_anonymized(renderer, line_num + file_lines.len() - 1, max_line_num_len), ElementStyle::LineNumber, ); buffer.puts( *row_num - 1, max_line_num_len + 1, "- ", ElementStyle::Removal, ); buffer.puts( *row_num - 1, max_line_num_len + 3, &normalize_whitespace(last_line.line), ElementStyle::NoStyle, ); style_substitution_highlights( replaced_parts.last().unwrap(), ElementStyle::Removal, *row_num - 1, last_line.line, max_line_num_len, buffer, ); if line_to_add.trim().is_empty() { *row_num -= 1; } else { // Check if after the removal, the line is left with only whitespace. If so, we // will not show an "addition" line, as removing the whole line is what the user // would really want. // For example, for the following: // | // 2 - .await // 2 + (note the left over whitespace) // | // We really want // | // 2 - .await // | // *row_num -= 1; buffer.puts( *row_num, 0, &maybe_anonymized(renderer, line_num, max_line_num_len), ElementStyle::LineNumber, ); buffer.puts(*row_num, max_line_num_len + 1, "+ ", ElementStyle::Addition); buffer.append( *row_num, &normalize_whitespace(line_to_add), ElementStyle::NoStyle, ); } } } else if is_multiline { buffer.puts( *row_num, 0, &maybe_anonymized(renderer, line_num, max_line_num_len), ElementStyle::LineNumber, ); match &highlight_parts { [SubstitutionHighlight { start: 0, end }] if *end == line_to_add.len() => { buffer.puts(*row_num, max_line_num_len + 1, "+ ", ElementStyle::Addition); } [] | [SubstitutionHighlight { start: 0, end: 0 }] => { // FIXME: needed? Doesn't get exercised in any test. draw_col_separator_no_space(renderer, buffer, *row_num, max_line_num_len + 1); } _ => { let diff = renderer.decor_style.diff(); buffer.puts( *row_num, max_line_num_len + 1, &format!("{diff} "), ElementStyle::Addition, ); } } // LL | line_to_add // ++^^^ // | | // | magic `3` // `max_line_num_len` buffer.puts( *row_num, max_line_num_len + 3, &normalize_whitespace(line_to_add), ElementStyle::NoStyle, ); } else if let DisplaySuggestion::Add = show_code_change { buffer.puts( *row_num, 0, &maybe_anonymized(renderer, line_num, max_line_num_len), ElementStyle::LineNumber, ); buffer.puts(*row_num, max_line_num_len + 1, "+ ", ElementStyle::Addition); buffer.append( *row_num, &normalize_whitespace(line_to_add), ElementStyle::NoStyle, ); } else { buffer.puts( *row_num, 0, &maybe_anonymized(renderer, line_num, max_line_num_len), ElementStyle::LineNumber, ); draw_col_separator(renderer, buffer, *row_num, max_line_num_len + 1); buffer.append( *row_num, &normalize_whitespace(line_to_add), ElementStyle::NoStyle, ); } style_substitution_highlights( highlight_parts, ElementStyle::Addition, *row_num, line_to_add, max_line_num_len, buffer, ); *row_num += 1; } fn style_substitution_highlights( highlight_parts: &[SubstitutionHighlight], style: ElementStyle, row_num: usize, unnormalized_line: &str, max_line_num_len: usize, buffer: &mut StyledBuffer, ) { for &SubstitutionHighlight { start, end } in highlight_parts { // This is a no-op for empty ranges if start != end { // We calculate the extra width from tabs for both the start and end // of the span, as tabs could be present in the middle of the span let extra_width_start: usize = extra_width_from_tabs(unnormalized_line, start); let extra_width_end: usize = extra_width_from_tabs(unnormalized_line, end); buffer.set_style_range( row_num, max_line_num_len + 3 + start + extra_width_start, max_line_num_len + 3 + end + extra_width_end, style, true, ); } } } #[allow(clippy::too_many_arguments)] fn draw_line( renderer: &Renderer, buffer: &mut StyledBuffer, source_string: &str, line_index: usize, line_offset: usize, width_offset: usize, code_offset: usize, max_line_num_len: usize, margin: Margin, ) -> usize { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(!source_string.contains('\t')); let line_len = str_width(source_string); // Create the source line we will highlight. let mut left = margin.left(line_len); let right = margin.right(line_len); let mut taken = 0; let mut skipped = 0; let code: String = source_string .chars() .skip_while(|ch| { let w = char_width(*ch); // If `skipped` is less than `left`, always skip the next `ch`, // even if `ch` is a multi-width char that would make `skipped` // exceed `left`. This ensures that we do not exceed term width on // source lines. if skipped < left { skipped += w; true } else { false } }) .take_while(|ch| { // Make sure that the trimming on the right will fall within the terminal width. taken += char_width(*ch); taken <= (right - left) }) .collect(); // If we skipped more than `left`, adjust `left` to account for it. if skipped > left { left += skipped - left; } let cut_indicator = renderer .cut_indicator .unwrap_or(renderer.decor_style.margin()); let padding = str_width(cut_indicator); let (width_taken, bytes_taken) = if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. let mut bytes_taken = 0; let mut width_taken = 0; for ch in code.chars() { width_taken += char_width(ch); bytes_taken += ch.len_utf8(); if width_taken >= padding { break; } } buffer.puts( line_offset, code_offset, cut_indicator, ElementStyle::LineNumber, ); (width_taken, bytes_taken) } else { (0, 0) }; buffer.puts( line_offset, code_offset + width_taken, &code[bytes_taken..], ElementStyle::Quotation, ); if line_len > right { // We have stripped some code/whitespace from the beginning, make it clear. let mut char_taken = 0; let mut width_taken_inner = 0; for ch in code.chars().rev() { width_taken_inner += char_width(ch); char_taken += 1; if width_taken_inner >= padding { break; } } buffer.puts( line_offset, code_offset + width_taken + code[bytes_taken..].chars().count() - char_taken, cut_indicator, ElementStyle::LineNumber, ); } buffer.puts( line_offset, 0, &maybe_anonymized(renderer, line_index, max_line_num_len), ElementStyle::LineNumber, ); draw_col_separator_no_space(renderer, buffer, line_offset, width_offset - 2); left } fn draw_range( buffer: &mut StyledBuffer, symbol: char, line: usize, col_from: usize, col_to: usize, style: ElementStyle, ) { for col in col_from..col_to { buffer.putc(line, col, symbol, style); } } fn draw_multiline_line( renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, offset: usize, depth: usize, style: ElementStyle, elided: bool, ) { let chr = match (style, renderer.decor_style) { (ElementStyle::UnderlinePrimary | ElementStyle::LabelPrimary, DecorStyle::Ascii) => '|', (_, DecorStyle::Ascii) => '|', (ElementStyle::UnderlinePrimary | ElementStyle::LabelPrimary, DecorStyle::Unicode) => { if elided { '┇' } else { '┃' } } (_, DecorStyle::Unicode) => { if elided { '┆' } else { '│' } } }; buffer.putc(line, offset + depth - 1, chr, style); } fn draw_col_separator(renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize) { let chr = renderer.decor_style.col_separator(); buffer.puts(line, col, &format!("{chr} "), ElementStyle::LineNumber); } fn draw_col_separator_no_space( renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize, ) { let chr = renderer.decor_style.col_separator(); draw_col_separator_no_space_with_style(buffer, chr, line, col, ElementStyle::LineNumber); } fn draw_col_separator_start( renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize, ) { match renderer.decor_style { DecorStyle::Ascii => { draw_col_separator_no_space_with_style( buffer, '|', line, col, ElementStyle::LineNumber, ); } DecorStyle::Unicode => { draw_col_separator_no_space_with_style( buffer, '╭', line, col, ElementStyle::LineNumber, ); draw_col_separator_no_space_with_style( buffer, '╴', line, col + 1, ElementStyle::LineNumber, ); } } } fn draw_col_separator_end(renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize) { match renderer.decor_style { DecorStyle::Ascii => { draw_col_separator_no_space_with_style( buffer, '|', line, col, ElementStyle::LineNumber, ); } DecorStyle::Unicode => { draw_col_separator_no_space_with_style( buffer, '╰', line, col, ElementStyle::LineNumber, ); draw_col_separator_no_space_with_style( buffer, '╴', line, col + 1, ElementStyle::LineNumber, ); } } } fn draw_col_separator_no_space_with_style( buffer: &mut StyledBuffer, chr: char, line: usize, col: usize, style: ElementStyle, ) { buffer.putc(line, col, chr, style); } fn maybe_anonymized(renderer: &Renderer, line_num: usize, max_line_num_len: usize) -> String { format!( "{:>max_line_num_len$}", if renderer.anonymized_line_numbers { Cow::Borrowed(ANONYMIZED_LINE_NUM) } else { Cow::Owned(line_num.to_string()) } ) } fn draw_note_separator( renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize, is_cont: bool, ) { let chr = renderer.decor_style.note_separator(is_cont); buffer.puts(line, col, chr, ElementStyle::LineNumber); } fn draw_line_separator(renderer: &Renderer, buffer: &mut StyledBuffer, line: usize, col: usize) { let (column, dots) = match renderer.decor_style { DecorStyle::Ascii => (0, "..."), DecorStyle::Unicode => (col - 2, "┆"), }; buffer.puts(line, column, dots, ElementStyle::LineNumber); } trait MessageOrTitle { fn level(&self) -> &Level<'_>; fn id(&self) -> Option<&Id<'_>>; fn text(&self) -> &str; fn allows_styling(&self) -> bool; fn is_fixable(&self) -> bool; } impl MessageOrTitle for Title<'_> { fn level(&self) -> &Level<'_> { &self.level } fn id(&self) -> Option<&Id<'_>> { self.id.as_ref() } fn text(&self) -> &str { self.text.as_ref() } fn allows_styling(&self) -> bool { self.allows_styling } fn is_fixable(&self) -> bool { self.is_fixable } } impl MessageOrTitle for Message<'_> { fn level(&self) -> &Level<'_> { &self.level } fn id(&self) -> Option<&Id<'_>> { None } fn text(&self) -> &str { self.text.as_ref() } fn allows_styling(&self) -> bool { true } fn is_fixable(&self) -> bool { false } } /// Count extra display columns from tabs in the first `n` chars of `s`. /// Each tab is displayed as 4 spaces, so the extra width per tab is 3. fn extra_width_from_tabs(s: &str, n: usize) -> usize { s.chars().take(n).filter(|&ch| ch == '\t').count() * 3 } // instead of taking the String length or dividing by 10 while > 0, we multiply a limit by 10 until // we're higher. If the loop isn't exited by the `return`, the last multiplication will wrap, which // is OK, because while we cannot fit a higher power of 10 in a usize, the loop will end anyway. // This is also why we need the max number of decimal digits within a `usize`. fn num_decimal_digits(num: Option) -> usize { #[cfg(target_pointer_width = "64")] const MAX_DIGITS: usize = 20; #[cfg(target_pointer_width = "32")] const MAX_DIGITS: usize = 10; #[cfg(target_pointer_width = "16")] const MAX_DIGITS: usize = 5; let Some(num) = num else { return 0; }; let mut lim = 10; for num_digits in 1..MAX_DIGITS { if num < lim { return num_digits; } lim = lim.wrapping_mul(10); } MAX_DIGITS } fn str_width(s: &str) -> usize { s.chars().map(char_width).sum() } pub(crate) fn char_width(ch: char) -> usize { // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now, // just accept that sometimes the code line will be longer than desired. match ch { '\t' => 4, // Keep the following list in sync with `rustc_errors::emitter::OUTPUT_REPLACEMENTS`. These // are control points that we replace before printing with a visible codepoint for the sake // of being able to point at them with underlines. '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}' | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}' | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}' | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}' | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}' | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1, _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1), } } pub(crate) fn num_overlap( a_start: usize, a_end: usize, b_start: usize, b_end: usize, inclusive: bool, ) -> bool { let extra = usize::from(inclusive); (b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start) } fn overlaps(a1: &LineAnnotation<'_>, a2: &LineAnnotation<'_>, padding: usize) -> bool { num_overlap( a1.start.display, a1.end.display + padding, a2.start.display, a2.end.display, false, ) } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] pub(crate) enum LineAnnotationType { /// Annotation under a single line of code Singleline, // The Multiline type above is replaced with the following three in order // to reuse the current label drawing code. // // Each of these corresponds to one part of the following diagram: // // x | foo(1 + bar(x, // | _________^ < MultilineStart // x | | y), < MultilineLine // | |______________^ label < MultilineEnd // x | z); /// Annotation marking the first character of a fully shown multiline span MultilineStart(usize), /// Annotation marking the last character of a fully shown multiline span MultilineEnd(usize), /// Line at the left enclosing the lines of a fully shown multiline span // Just a placeholder for the drawing algorithm, to know that it shouldn't skip the first 4 // and last 2 lines of code. The actual line is drawn in `emit_message_default` and not in // `draw_multiline_line`. MultilineLine(usize), } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] pub(crate) struct LineAnnotation<'a> { /// Start column. /// Note that it is important that this field goes /// first, so that when we sort, we sort orderings by start /// column. pub start: Loc, /// End column within the line (exclusive) pub end: Loc, /// level pub kind: AnnotationKind, /// Optional label to display adjacent to the annotation. pub label: Option>, /// Is this a single line, multiline or multiline span minimized down to a /// smaller span. pub annotation_type: LineAnnotationType, /// Whether the source code should be highlighted pub highlight_source: bool, } impl LineAnnotation<'_> { pub(crate) fn is_primary(&self) -> bool { self.kind == AnnotationKind::Primary } /// Whether this annotation is a vertical line placeholder. pub(crate) fn is_line(&self) -> bool { matches!(self.annotation_type, LineAnnotationType::MultilineLine(_)) } /// Length of this annotation as displayed in the stderr output pub(crate) fn len(&self) -> usize { // Account for usize underflows self.end.display.abs_diff(self.start.display) } pub(crate) fn has_label(&self) -> bool { if let Some(label) = &self.label { // Consider labels with no text as effectively not being there // to avoid weird output with unnecessary vertical lines, like: // // X | fn foo(x: u32) { // | -------^------ // | | | // | | // | // // Note that this would be the complete output users would see. !label.is_empty() } else { false } } pub(crate) fn takes_space(&self) -> bool { // Multiline annotations always have to keep vertical space. matches!( self.annotation_type, LineAnnotationType::MultilineStart(_) | LineAnnotationType::MultilineEnd(_) ) } } #[derive(Clone, Copy, Debug)] pub(crate) enum DisplaySuggestion { Underline, Diff, None, Add, } impl DisplaySuggestion { fn new(complete: &str, patches: &[TrimmedPatch<'_>], sm: &SourceMap<'_>) -> Self { let has_deletion = patches .iter() .any(|p| p.is_deletion(sm) || p.is_destructive_replacement(sm)); let is_multiline = complete.lines().count() > 1; if has_deletion && !is_multiline { DisplaySuggestion::Diff } else if patches.len() == 1 && patches.first().is_some_and(|p| { p.replacement.ends_with('\n') && p.replacement.trim() == complete.trim() }) { // We are adding a line(s) of code before code that was already there. DisplaySuggestion::Add } else if (patches.len() != 1 || patches[0].replacement.trim() != complete.trim()) && !is_multiline { DisplaySuggestion::Underline } else { DisplaySuggestion::None } } } // We replace some characters so the CLI output is always consistent and underlines aligned. // Keep the following list in sync with `rustc_span::char_width`. const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ // In terminals without Unicode support the following will be garbled, but in *all* terminals // the underlying codepoint will be as well. We could gate this replacement behind a "unicode // support" gate. ('\0', "␀"), ('\u{0001}', "␁"), ('\u{0002}', "␂"), ('\u{0003}', "␃"), ('\u{0004}', "␄"), ('\u{0005}', "␅"), ('\u{0006}', "␆"), ('\u{0007}', "␇"), ('\u{0008}', "␈"), ('\t', " "), // We do our own tab replacement ('\u{000b}', "␋"), ('\u{000c}', "␌"), ('\u{000d}', "␍"), ('\u{000e}', "␎"), ('\u{000f}', "␏"), ('\u{0010}', "␐"), ('\u{0011}', "␑"), ('\u{0012}', "␒"), ('\u{0013}', "␓"), ('\u{0014}', "␔"), ('\u{0015}', "␕"), ('\u{0016}', "␖"), ('\u{0017}', "␗"), ('\u{0018}', "␘"), ('\u{0019}', "␙"), ('\u{001a}', "␚"), ('\u{001b}', "␛"), ('\u{001c}', "␜"), ('\u{001d}', "␝"), ('\u{001e}', "␞"), ('\u{001f}', "␟"), ('\u{007f}', "␡"), ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters. ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk ('\u{202c}', "�"), // not corresponding to the visible source code, so we replace them always. ('\u{202d}', "�"), ('\u{202e}', "�"), ('\u{2066}', "�"), ('\u{2067}', "�"), ('\u{2068}', "�"), ('\u{2069}', "�"), ]; pub(crate) fn normalize_whitespace(s: &str) -> Cow<'_, str> { if !s .chars() .any(|user| OUTPUT_REPLACEMENTS.iter().any(|(bad, _)| user == *bad)) { return Cow::Borrowed(s); } // Scan the input string for a character in the ordered table above. // If it's present, replace it with its alternative string (it can be more than 1 char!). // Otherwise, retain the input char. let normalized = s.chars().fold(String::with_capacity(s.len()), |mut s, c| { match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) { Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1), _ => s.push(c), } s }); Cow::Owned(normalized) } #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)] pub(crate) enum ElementStyle { MainHeaderMsg, HeaderMsg, LineAndColumn, LineNumber, Quotation, UnderlinePrimary, UnderlineSecondary, LabelPrimary, LabelSecondary, NoStyle, Level(LevelInner), Addition, Removal, } impl ElementStyle { pub(crate) fn color_spec(&self, level: &Level<'_>, stylesheet: &Stylesheet) -> Style { match self { ElementStyle::Addition => stylesheet.addition, ElementStyle::Removal => stylesheet.removal, ElementStyle::LineAndColumn => stylesheet.none, ElementStyle::LineNumber => stylesheet.line_num, ElementStyle::Quotation => stylesheet.none, ElementStyle::MainHeaderMsg => stylesheet.emphasis, ElementStyle::UnderlinePrimary | ElementStyle::LabelPrimary => level.style(stylesheet), ElementStyle::UnderlineSecondary | ElementStyle::LabelSecondary => stylesheet.context, ElementStyle::HeaderMsg | ElementStyle::NoStyle => stylesheet.none, ElementStyle::Level(lvl) => lvl.style(stylesheet), } } } #[derive(Debug, Clone, Copy)] pub(crate) struct UnderlineParts { pub(crate) style: ElementStyle, pub(crate) underline: char, pub(crate) label_start: char, pub(crate) vertical_text_line: char, pub(crate) multiline_vertical: char, pub(crate) multiline_horizontal: char, pub(crate) multiline_whole_line: char, pub(crate) multiline_start_down: char, pub(crate) bottom_right: char, pub(crate) top_left: char, pub(crate) top_right_flat: char, pub(crate) bottom_left: char, pub(crate) multiline_end_up: char, pub(crate) multiline_end_same_line: char, pub(crate) multiline_bottom_right_with_text: char, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum TitleStyle { MainHeader, Header, Secondary, } struct PreProcessedGroup<'a> { group: &'a Group<'a>, elements: Vec>, primary_path: Option<&'a Cow<'a, str>>, max_depth: usize, } enum PreProcessedElement<'a> { Message(&'a Message<'a>), Cause( ( &'a Snippet<'a, Annotation<'a>>, SourceMap<'a>, Vec>, ), ), Suggestion( ( &'a Snippet<'a, Patch<'a>>, SourceMap<'a>, SplicedLines<'a>, DisplaySuggestion, ), ), Origin(&'a Origin<'a>), Padding(Padding), } fn pre_process<'a>( groups: &'a [Group<'a>], ) -> ( Option, Option<&'a Cow<'a, str>>, Vec>, ) { let mut max_line_num = None; let mut og_primary_path = None; let mut out = Vec::with_capacity(groups.len()); for group in groups { let mut elements = Vec::with_capacity(group.elements.len()); let mut primary_path = None; let mut max_depth = 0; for element in &group.elements { match element { Element::Message(message) => { elements.push(PreProcessedElement::Message(message)); } Element::Cause(cause) => { let sm = SourceMap::new(&cause.source, cause.line_start); let (depth, annotated_lines) = sm.annotated_lines(cause.markers.clone(), cause.fold); let show_snippet = !cause.markers.iter().any(|s| s.is_file_level); if show_snippet { if cause.fold { let end = cause .markers .iter() .map(|a| a.span.end) .max() .unwrap_or(cause.source.len()) .min(cause.source.len()); max_line_num = Some(max( cause.line_start + newline_count(&cause.source[..end]), max_line_num.unwrap_or(0), )); } else { max_line_num = Some(max( cause.line_start + newline_count(&cause.source), max_line_num.unwrap_or(0), )); } max_depth = max(depth, max_depth); } if primary_path.is_none() { primary_path = Some(cause.path.as_ref()); } elements.push(PreProcessedElement::Cause((cause, sm, annotated_lines))); } Element::Suggestion(suggestion) => { let sm = SourceMap::new(&suggestion.source, suggestion.line_start); if let Some((complete, patches, highlights, replaced_highlights)) = sm.splice_lines(suggestion.markers.clone(), suggestion.fold) { let display_suggestion = DisplaySuggestion::new(&complete, &patches, &sm); if suggestion.fold { if let Some(first) = patches.first() { let (l_start, _) = sm.span_to_locations(first.original_span.clone()); let nc = newline_count(&complete); let sugg_max_line_num = match display_suggestion { DisplaySuggestion::Underline => l_start.line, DisplaySuggestion::Diff => { let file_lines = sm.span_to_lines(first.span.clone()); file_lines .last() .map_or(l_start.line + nc, |line| line.line_index) } DisplaySuggestion::None => l_start.line + nc, DisplaySuggestion::Add => l_start.line + nc, }; max_line_num = Some(max(sugg_max_line_num, max_line_num.unwrap_or(0))); } } else { max_line_num = Some(max( suggestion.line_start + newline_count(&complete), max_line_num.unwrap_or(0), )); } elements.push(PreProcessedElement::Suggestion(( suggestion, sm, (complete, patches, highlights, replaced_highlights), display_suggestion, ))); } } Element::Origin(origin) => { if primary_path.is_none() { primary_path = Some(origin.path.as_ref()); } elements.push(PreProcessedElement::Origin(origin)); } Element::Padding(padding) => { elements.push(PreProcessedElement::Padding(padding.clone())); } } } let group = PreProcessedGroup { group, elements, primary_path: primary_path.unwrap_or_default(), max_depth, }; if og_primary_path.is_none() && group.primary_path.is_some() { og_primary_path = group.primary_path; } out.push(group); } (max_line_num, og_primary_path, out) } fn newline_count(body: &str) -> usize { #[cfg(feature = "simd")] { // Trailing newlines do not count towards the number of lines // (this is based into `str::lines`) let trailing_newline = body.ends_with('\n'); memchr::memchr_iter(b'\n', body.as_bytes()).count() - usize::from(trailing_newline) } #[cfg(not(feature = "simd"))] { body.lines().count().saturating_sub(1) } } #[cfg(test)] mod test { use super::{OUTPUT_REPLACEMENTS, newline_count}; use snapbox::IntoData; fn format_replacements(replacements: Vec<(char, &str)>) -> String { replacements .into_iter() .map(|r| format!(" {r:?}")) .collect::>() .join("\n") } #[test] /// The [`OUTPUT_REPLACEMENTS`] array must be sorted (for binary search to /// work) and must contain no duplicate entries fn ensure_output_replacements_is_sorted() { let mut expected = OUTPUT_REPLACEMENTS.to_owned(); expected.sort_by_key(|r| r.0); expected.dedup_by_key(|r| r.0); let expected = format_replacements(expected); let actual = format_replacements(OUTPUT_REPLACEMENTS.to_owned()); snapbox::assert_data_eq!(actual, expected.into_data().raw()); } #[test] fn ensure_newline_count_correct() { let source = r#" cargo-features = ["path-bases"] [package] name = "foo" version = "0.5.0" authors = ["wycats@example.com"] [dependencies] bar = { base = '^^not-valid^^', path = 'bar' } "#; assert_eq!(newline_count(source), 10); assert_eq!(newline_count(""), 0); assert_eq!(newline_count("one"), 0); assert_eq!(newline_count("one\n"), 0); assert_eq!(newline_count("one\ntwo"), 1); assert_eq!(newline_count("one\ntwo\n"), 1); assert_eq!(newline_count("one\n\n"), 1); assert_eq!(newline_count("one\r\ntwo\r\n"), 1); } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/source_map.rs000064400000000000000000000743141046102023000245160ustar00use alloc::borrow::Cow; use alloc::string::String; use alloc::{vec, vec::Vec}; use core::cmp::{max, min}; use core::ops::Range; use crate::renderer::{LineAnnotation, LineAnnotationType, char_width, num_overlap}; use crate::{Annotation, AnnotationKind, Patch}; #[derive(Debug)] pub(crate) struct SourceMap<'a> { lines: Vec>, pub(crate) source: &'a str, } impl<'a> SourceMap<'a> { pub(crate) fn new(source: &'a str, line_start: usize) -> Self { // Empty sources do have a "line", but it is empty, so we need to add // a line with an empty string to the source map. if source.is_empty() { return Self { lines: vec![LineInfo { line: "", line_index: line_start, start_byte: 0, end_byte: 0, end_line_size: 0, }], source, }; } let mut current_index = 0; let mut mapping = vec![]; for (idx, (line, end_line)) in CursorLines::new(source).enumerate() { let line_length = line.len(); let line_range = current_index..current_index + line_length; let end_line_size = end_line.len(); mapping.push(LineInfo { line, line_index: line_start + idx, start_byte: line_range.start, end_byte: line_range.end + end_line_size, end_line_size, }); current_index += line_length + end_line_size; } Self { lines: mapping, source, } } pub(crate) fn get_line(&self, idx: usize) -> Option<&'a str> { self.lines .iter() .find(|l| l.line_index == idx) .map(|info| info.line) } pub(crate) fn span_to_locations(&self, span: Range) -> (Loc, Loc) { let start_info = self .lines .iter() .find(|info| span.start >= info.start_byte && span.start < info.end_byte) .unwrap_or(self.lines.last().unwrap()); let (mut start_char_pos, start_display_pos) = start_info.line [0..(span.start - start_info.start_byte).min(start_info.line.len())] .chars() .fold((0, 0), |(char_pos, byte_pos), c| { let display = char_width(c); (char_pos + 1, byte_pos + display) }); // correct the char pos if we are highlighting the end of a line if (span.start - start_info.start_byte).saturating_sub(start_info.line.len()) > 0 { start_char_pos += 1; } let start = Loc { line: start_info.line_index, char: start_char_pos, display: start_display_pos, byte: span.start, }; if span.start == span.end { return (start, start); } let (end_idx, end_info, eof) = self .lines .iter() .enumerate() .find(|(_, info)| span.end >= info.start_byte && span.end < info.end_byte) .map(|(idx, info)| (idx, info, false)) .unwrap_or((self.lines.len() - 1, self.lines.last().unwrap(), true)); let (end_char_pos, end_display_pos) = end_info.line [0..(span.end - end_info.start_byte).min(end_info.line.len())] .chars() .fold((0, 0), |(char_pos, byte_pos), c| { let display = char_width(c); (char_pos + 1, byte_pos + display) }); let mut end = Loc { line: end_info.line_index, char: end_char_pos, display: end_display_pos, byte: span.end, }; if start.line < end.line && end.char == 0 && !eof { let prev_line_info = &self.lines[end_idx - 1]; let (end_char_pos, end_display_pos) = prev_line_info.line [0..(span.end - prev_line_info.start_byte).min(prev_line_info.line.len())] .chars() .fold((0, 0), |(char_pos, byte_pos), c| { let display = char_width(c); (char_pos + 1, byte_pos + display) }); if prev_line_info.end_byte == start.byte { end = Loc { line: prev_line_info.line_index, char: end_char_pos + 1, display: end_display_pos + 1, byte: span.end, }; } else { end = Loc { line: prev_line_info.line_index, char: end_char_pos, display: end_display_pos, byte: span.end, }; } } if start.line != end.line && end.byte > end_info.end_byte - end_info.end_line_size { end.char += 1; end.display += 1; } (start, end) } pub(crate) fn span_to_snippet(&self, span: Range) -> Option<&str> { self.source.get(span) } pub(crate) fn span_to_lines(&self, span: Range) -> Vec<&LineInfo<'a>> { let mut lines = vec![]; let start = span.start; let end = span.end; for line_info in &self.lines { if start >= line_info.end_byte { continue; } if end < line_info.start_byte { break; } lines.push(line_info); } if lines.is_empty() && !self.lines.is_empty() { lines.push(self.lines.last().unwrap()); } lines } pub(crate) fn annotated_lines( &self, annotations: Vec>, fold: bool, ) -> (usize, Vec>) { let source_len = self.source.len(); if let Some(bigger) = annotations.iter().find_map(|x| { // Allow highlighting one past the last character in the source. if source_len + 1 < x.span.end { Some(&x.span) } else { None } }) { panic!("Annotation range `{bigger:?}` is beyond the end of buffer `{source_len}`") } let mut annotated_line_infos = self .lines .iter() .map(|info| AnnotatedLineInfo { line: info.line, line_index: info.line_index, annotations: vec![], keep: false, }) .collect::>(); let mut multiline_annotations = vec![]; for Annotation { span, label, kind, highlight_source, is_file_level: _, } in annotations { let (lo, mut hi) = self.span_to_locations(span.clone()); if kind == AnnotationKind::Visible { for line_idx in lo.line..=hi.line { self.keep_line(&mut annotated_line_infos, line_idx); } continue; } // Watch out for "empty spans". If we get a span like 6..6, we // want to just display a `^` at 6, so convert that to // 6..7. This is degenerate input, but it's best to degrade // gracefully -- and the parser likes to supply a span like // that for EOF, in particular. if lo.display == hi.display && lo.line == hi.line { hi.display += 1; } if lo.line == hi.line { let line_ann = LineAnnotation { start: lo, end: hi, kind, label, annotation_type: LineAnnotationType::Singleline, highlight_source, }; self.add_annotation_to_file(&mut annotated_line_infos, lo.line, line_ann); } else { multiline_annotations.push(MultilineAnnotation { depth: 1, start: lo, end: hi, kind, label, overlaps_exactly: false, highlight_source, }); } } let mut primary_spans = vec![]; // Find overlapping multiline annotations, put them at different depths multiline_annotations.sort_by_key(|ml| (ml.start.line, usize::MAX - ml.end.line)); for (outer_i, ann) in multiline_annotations.clone().into_iter().enumerate() { if ann.kind.is_primary() { primary_spans.push((ann.start, ann.end)); } for (inner_i, a) in &mut multiline_annotations.iter_mut().enumerate() { // Move all other multiline annotations overlapping with this one // one level to the right. if !ann.same_span(a) && num_overlap(ann.start.line, ann.end.line, a.start.line, a.end.line, true) { a.increase_depth(); } else if ann.same_span(a) && outer_i != inner_i { a.overlaps_exactly = true; } else { if primary_spans .iter() .any(|(s, e)| a.start == *s && a.end == *e) { a.kind = AnnotationKind::Primary; } break; } } } let mut max_depth = 0; // max overlapping multiline spans for ann in &multiline_annotations { max_depth = max(max_depth, ann.depth); } // Change order of multispan depth to minimize the number of overlaps in the ASCII art. for a in &mut multiline_annotations { a.depth = max_depth - a.depth + 1; } for ann in multiline_annotations { let mut end_ann = ann.as_end(); if ann.overlaps_exactly { end_ann.annotation_type = LineAnnotationType::Singleline; } else { // avoid output like // // | foo( // | _____^ // | |_____| // | || bar, // | || ); // | || ^ // | ||______| // | |______foo // | baz // // and instead get // // | foo( // | _____^ // | | bar, // | | ); // | | ^ // | | | // | |______foo // | baz self.add_annotation_to_file( &mut annotated_line_infos, ann.start.line, ann.as_start(), ); // 4 is the minimum vertical length of a multiline span when presented: two lines // of code and two lines of underline. This is not true for the special case where // the beginning doesn't have an underline, but the current logic seems to be // working correctly. let middle = min(ann.start.line + 4, ann.end.line); // We'll show up to 4 lines past the beginning of the multispan start. // We will *not* include the tail of lines that are only whitespace, a comment or // a bare delimiter. let filter = |s: &str| { let s = s.trim(); // Consider comments as empty, but don't consider docstrings to be empty. !(s.starts_with("//") && !(s.starts_with("///") || s.starts_with("//!"))) // Consider lines with nothing but whitespace, a single delimiter as empty. && !["", "{", "}", "(", ")", "[", "]"].contains(&s) }; let until = (ann.start.line..middle) .rev() .filter_map(|line| self.get_line(line).map(|s| (line + 1, s))) .find(|(_, s)| filter(s)) .map_or(ann.start.line, |(line, _)| line); for line in ann.start.line + 1..until { // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). self.add_annotation_to_file(&mut annotated_line_infos, line, ann.as_line()); } let line_end = ann.end.line - 1; let end_is_empty = self.get_line(line_end).is_some_and(|s| !filter(s)); if middle < line_end && !end_is_empty { self.add_annotation_to_file(&mut annotated_line_infos, line_end, ann.as_line()); } } self.add_annotation_to_file(&mut annotated_line_infos, end_ann.end.line, end_ann); } if fold { annotated_line_infos.retain(|l| !l.annotations.is_empty() || l.keep); } (max_depth, annotated_line_infos) } fn add_annotation_to_file( &self, annotated_line_infos: &mut Vec>, line_index: usize, line_ann: LineAnnotation<'a>, ) { if let Some(line_info) = annotated_line_infos .iter_mut() .find(|line_info| line_info.line_index == line_index) { line_info.annotations.push(line_ann); } else { let info = self .lines .iter() .find(|l| l.line_index == line_index) .unwrap(); annotated_line_infos.push(AnnotatedLineInfo { line: info.line, line_index, annotations: vec![line_ann], keep: false, }); annotated_line_infos.sort_by_key(|l| l.line_index); } } fn keep_line(&self, annotated_line_infos: &mut Vec>, line_index: usize) { if let Some(line_info) = annotated_line_infos .iter_mut() .find(|line_info| line_info.line_index == line_index) { line_info.keep = true; } else { let info = self .lines .iter() .find(|l| l.line_index == line_index) .unwrap(); annotated_line_infos.push(AnnotatedLineInfo { line: info.line, line_index, annotations: vec![], keep: true, }); annotated_line_infos.sort_by_key(|l| l.line_index); } } pub(crate) fn splice_lines<'b>( &'a self, mut patches: Vec>, fold: bool, ) -> Option> { fn push_trailing(buf: &mut String, line_opt: Option<&str>, lo: &Loc, hi_opt: Option<&Loc>) { // Convert CharPos to Usize, as CharPose is character offset // Extract low index and high index let (lo, hi_opt) = (lo.char, hi_opt.map(|hi| hi.char)); if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { // Get high index while account for rare unicode and emoji with char_indices let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); match hi_opt { // If high index exist, take string from low to high index Some(hi) if hi > lo => buf.push_str(&line[lo..hi]), Some(_) => (), // If high index absence, take string from low index till end string.len None => buf.push_str(&line[lo..]), } } // If high index is None if hi_opt.is_none() { buf.push('\n'); } } } let source_len = self.source.len(); if let Some(bigger) = patches.iter().find_map(|x| { // Allow patching one past the last character in the source. if source_len + 1 < x.span.end { Some(&x.span) } else { None } }) { panic!("Patch span `{bigger:?}` is beyond the end of buffer `{source_len}`") } // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. patches.sort_by_key(|p| p.span.start); // Find the bounding span. let (lo, hi) = if fold { let lo = patches .iter() .map(|p| p.span.clone()) .min_by_key(|s| s.start)?; let hi = patches .iter() .map(|p| p.span.clone()) .max_by_key(|s| s.end)?; (lo, hi) } else { let lo = 0..source_len; let hi = 0..source_len; (lo, hi) }; let lines = self.span_to_lines(lo.start..hi.end); let (bounding_lo, _) = self.span_to_locations(lo); let (_, bounding_hi) = self.span_to_locations(hi); let mut highlights = vec![]; // To build up the result, we do this for each span: // - push the line segment trailing the previous span // (at the beginning a "phantom" span pointing at the start of the line) // - push lines between the previous and current span (if any) // - if the previous and current span are not on the same line // push the line segment leading up to the current span // - splice in the span substitution // // Finally push the trailing line segment of the last span let mut prev_hi = bounding_lo; prev_hi.char = 0; let mut prev_line = lines.first().map(|line| line.line); let mut buf = String::new(); let trimmed_patches = patches .into_iter() // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the // suggestion and snippet to look as if we just suggested to add // `"b"`, which is typically much easier for the user to understand. .map(|part| part.trim_trivial_replacements(self.source)) .collect::>(); let mut line_highlight = vec![]; // We need to keep track of the difference between the existing code and the added // or deleted code in order to point at the correct column *after* substitution. let mut acc = 0; for part in &trimmed_patches { let (cur_lo, cur_hi) = self.span_to_locations(part.span.clone()); if prev_hi.line == cur_lo.line { push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); } else { acc = 0; highlights.push(core::mem::take(&mut line_highlight)); push_trailing(&mut buf, prev_line, &prev_hi, None); // push lines between the previous and current span (if any) for idx in prev_hi.line + 1..(cur_lo.line) { if let Some(line) = self.get_line(idx) { buf.push_str(line.as_ref()); buf.push('\n'); highlights.push(core::mem::take(&mut line_highlight)); } } if let Some(cur_line) = self.get_line(cur_lo.line) { let end = match cur_line.char_indices().nth(cur_lo.char) { Some((i, _)) => i, None => cur_line.len(), }; buf.push_str(&cur_line[..end]); } } // Add a whole line highlight per line in the snippet. let len: isize = part .replacement .split('\n') .next() .unwrap_or(&part.replacement) .chars() .map(|c| match c { '\t' => 4, _ => 1, }) .sum(); line_highlight.push(SubstitutionHighlight { start: (cur_lo.char as isize + acc) as usize, end: (cur_lo.char as isize + acc + len) as usize, }); buf.push_str(&part.replacement); // Account for the difference between the width of the current code and the // snippet being suggested, so that the *later* suggestions are correctly // aligned on the screen. Note that cur_hi and cur_lo can be on different // lines, so cur_hi.col can be smaller than cur_lo.col acc += len - (cur_hi.char as isize - cur_lo.char as isize); prev_hi = cur_hi; prev_line = self.get_line(prev_hi.line); for line in part.replacement.split('\n').skip(1) { acc = 0; highlights.push(core::mem::take(&mut line_highlight)); let end: usize = line .chars() .map(|c| match c { '\t' => 4, _ => 1, }) .sum(); line_highlight.push(SubstitutionHighlight { start: 0, end }); } } highlights.push(core::mem::take(&mut line_highlight)); if fold { // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { push_trailing(&mut buf, prev_line, &prev_hi, None); } } else { // Add the trailing part of the source after the last patch if let Some(snippet) = self.span_to_snippet(prev_hi.byte..source_len) { buf.push_str(snippet); for _ in snippet.matches('\n') { highlights.push(core::mem::take(&mut line_highlight)); } } } // remove trailing newlines while buf.ends_with('\n') { buf.pop(); } let line_count = bounding_hi.line.saturating_sub(bounding_lo.line) + 1; let mut replaced_highlights: Vec> = vec![Vec::new(); line_count]; for part in &trimmed_patches { let (cur_lo, cur_hi) = self.span_to_locations(part.span.clone()); for line in cur_lo.line..=cur_hi.line { let start = if line == cur_lo.line { cur_lo.char } else { 0 }; let end = if line == cur_hi.line { cur_hi.char } else { self.get_line(line).unwrap_or_default().chars().count() }; replaced_highlights[line - bounding_lo.line] .push(SubstitutionHighlight { start, end }); } } if highlights.iter().all(|parts| parts.is_empty()) { None } else { Some((buf, trimmed_patches, highlights, replaced_highlights)) } } } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] pub(crate) struct MultilineAnnotation<'a> { pub depth: usize, pub start: Loc, pub end: Loc, pub kind: AnnotationKind, pub label: Option>, pub overlaps_exactly: bool, pub highlight_source: bool, } impl<'a> MultilineAnnotation<'a> { pub(crate) fn increase_depth(&mut self) { self.depth += 1; } /// Compare two `MultilineAnnotation`s considering only the `Span` they cover. pub(crate) fn same_span(&self, other: &MultilineAnnotation<'_>) -> bool { self.start == other.start && self.end == other.end } pub(crate) fn as_start(&self) -> LineAnnotation<'a> { LineAnnotation { start: self.start, end: Loc { line: self.start.line, char: self.start.char + 1, display: self.start.display + 1, byte: self.start.byte + 1, }, kind: self.kind, label: None, annotation_type: LineAnnotationType::MultilineStart(self.depth), highlight_source: self.highlight_source, } } pub(crate) fn as_end(&self) -> LineAnnotation<'a> { LineAnnotation { start: Loc { line: self.end.line, char: self.end.char.saturating_sub(1), display: self.end.display.saturating_sub(1), byte: self.end.byte.saturating_sub(1), }, end: self.end, kind: self.kind, label: self.label.clone(), annotation_type: LineAnnotationType::MultilineEnd(self.depth), highlight_source: self.highlight_source, } } pub(crate) fn as_line(&self) -> LineAnnotation<'a> { LineAnnotation { start: Loc::default(), end: Loc::default(), kind: self.kind, label: None, annotation_type: LineAnnotationType::MultilineLine(self.depth), highlight_source: self.highlight_source, } } } #[derive(Debug)] pub(crate) struct LineInfo<'a> { pub(crate) line: &'a str, pub(crate) line_index: usize, pub(crate) start_byte: usize, pub(crate) end_byte: usize, end_line_size: usize, } #[derive(Debug)] pub(crate) struct AnnotatedLineInfo<'a> { pub(crate) line: &'a str, pub(crate) line_index: usize, pub(crate) annotations: Vec>, pub(crate) keep: bool, } /// A source code location used for error reporting. #[derive(Clone, Copy, Debug, Default, PartialOrd, Ord, PartialEq, Eq)] pub(crate) struct Loc { /// The (1-based) line number. pub(crate) line: usize, /// The (0-based) column offset. pub(crate) char: usize, /// The (0-based) column offset when displayed. pub(crate) display: usize, /// The (0-based) byte offset. pub(crate) byte: usize, } struct CursorLines<'a>(&'a str); impl CursorLines<'_> { fn new(src: &str) -> CursorLines<'_> { CursorLines(src) } } #[derive(Copy, Clone, Debug, PartialEq)] enum EndLine { Eof, Lf, Crlf, } impl EndLine { /// The number of characters this line ending occupies in bytes. pub(crate) fn len(self) -> usize { match self { EndLine::Eof => 0, EndLine::Lf => 1, EndLine::Crlf => 2, } } } impl<'a> Iterator for CursorLines<'a> { type Item = (&'a str, EndLine); fn next(&mut self) -> Option { if self.0.is_empty() { None } else { self.0 .find('\n') .map(|x| { let ret = if 0 < x { if self.0.as_bytes()[x - 1] == b'\r' { (&self.0[..x - 1], EndLine::Crlf) } else { (&self.0[..x], EndLine::Lf) } } else { ("", EndLine::Lf) }; self.0 = &self.0[x + 1..]; ret }) .or_else(|| { let ret = Some((self.0, EndLine::Eof)); self.0 = ""; ret }) } } } pub(crate) type SplicedLines<'a> = ( String, Vec>, // Char spans to highlight per line of the post-substitution output. Vec>, // Char spans of the replaced (original) code, per original line in the // bounding range covered by the splice. Vec>, ); /// Used to translate between `Span`s and byte positions within a single output line in highlighted /// code of structured suggestions. #[derive(Debug, Clone, Copy)] pub(crate) struct SubstitutionHighlight { pub(crate) start: usize, pub(crate) end: usize, } #[derive(Clone, Debug)] pub(crate) struct TrimmedPatch<'a> { pub(crate) original_span: Range, pub(crate) span: Range, pub(crate) replacement: Cow<'a, str>, } impl<'a> TrimmedPatch<'a> { pub(crate) fn is_addition(&self, sm: &SourceMap<'_>) -> bool { !self.replacement.is_empty() && !self.replaces_meaningful_content(sm) } pub(crate) fn is_deletion(&self, sm: &SourceMap<'_>) -> bool { self.replacement.trim().is_empty() && self.replaces_meaningful_content(sm) } pub(crate) fn is_replacement(&self, sm: &SourceMap<'_>) -> bool { !self.replacement.is_empty() && self.replaces_meaningful_content(sm) } /// Whether this is a replacement that overwrites source with a snippet /// in a way that isn't a superset of the original string. For example, /// replacing "abc" with "abcde" is not destructive, but replacing it /// it with "abx" is, since the "c" character is lost. pub(crate) fn is_destructive_replacement(&self, sm: &SourceMap<'_>) -> bool { self.is_replacement(sm) && sm .span_to_snippet(self.span.clone()) .is_none_or(|s| as_substr(s.trim(), self.replacement.trim()).is_none()) } fn replaces_meaningful_content(&self, sm: &SourceMap<'_>) -> bool { sm.span_to_snippet(self.span.clone()) .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty()) } } /// Given an original string like `AACC`, and a suggestion like `AABBCC`, try to detect /// the case where a substring of the suggestion is "sandwiched" in the original, like /// `BB` is. Return the length of the prefix, the "trimmed" suggestion, and the length /// of the suffix. pub(crate) fn as_substr<'a>( original: &'a str, suggestion: &'a str, ) -> Option<(usize, &'a str, usize)> { if let Some(stripped) = suggestion.strip_prefix(original) { Some((original.len(), stripped, 0)) } else if let Some(stripped) = suggestion.strip_suffix(original) { Some((0, stripped, original.len())) } else { let common_prefix = original .chars() .zip(suggestion.chars()) .take_while(|(c1, c2)| c1 == c2) .map(|(c, _)| c.len_utf8()) .sum(); let original = &original[common_prefix..]; let suggestion = &suggestion[common_prefix..]; if let Some(stripped) = suggestion.strip_suffix(original) { let common_suffix = original.len(); Some((common_prefix, stripped, common_suffix)) } else { None } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/styled_buffer.rs000064400000000000000000000127371046102023000252170ustar00//! Adapted from [styled_buffer] //! //! [styled_buffer]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_errors/src/styled_buffer.rs use alloc::string::String; use alloc::{vec, vec::Vec}; use core::fmt::{self, Write}; use crate::Level; use crate::renderer::ElementStyle; use crate::renderer::stylesheet::Stylesheet; #[derive(Debug)] pub(crate) struct StyledBuffer { lines: Vec>, } #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct StyledChar { ch: char, style: ElementStyle, } impl StyledChar { pub(crate) const SPACE: Self = StyledChar::new(' ', ElementStyle::NoStyle); pub(crate) const fn new(ch: char, style: ElementStyle) -> StyledChar { StyledChar { ch, style } } } impl StyledBuffer { pub(crate) fn new() -> StyledBuffer { StyledBuffer { lines: vec![] } } fn ensure_lines(&mut self, line: usize) { if line >= self.lines.len() { self.lines.resize(line + 1, Vec::new()); } } pub(crate) fn render( &self, level: &Level<'_>, stylesheet: &Stylesheet, str: &mut String, ) -> Result<(), fmt::Error> { let capacity = self.lines.iter().map(|line| line.len()).sum(); str.reserve(capacity); for (i, line) in self.lines.iter().enumerate() { let mut current_style = stylesheet.none; for StyledChar { ch, style } in line { let ch_style = style.color_spec(level, stylesheet); if ch_style != current_style { if !line.is_empty() { write!(str, "{current_style:#}")?; } current_style = ch_style; write!(str, "{current_style}")?; } str.push(*ch); } write!(str, "{current_style:#}")?; if i != self.lines.len() - 1 { str.push('\n'); } } Ok(()) } /// Sets `chr` with `style` for given `line`, `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. pub(crate) fn putc(&mut self, line: usize, col: usize, chr: char, style: ElementStyle) { self.ensure_lines(line); if col >= self.lines[line].len() { self.lines[line].resize(col + 1, StyledChar::SPACE); } self.lines[line][col] = StyledChar::new(chr, style); } /// Sets `string` with `style` for given `line`, starting from `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. pub(crate) fn puts(&mut self, line: usize, col: usize, string: &str, style: ElementStyle) { if string.is_empty() { // don't add trailing whitespace (from column offset) for blank strings return; } self.ensure_lines(line); let line = &mut self.lines[line]; let new_len = col + string.chars().count(); if new_len > line.len() { line.resize(new_len, StyledChar::SPACE); } for (offset, chr) in string.chars().enumerate() { let col = col + offset; line[col] = StyledChar::new(chr, style); } } /// For given `line` inserts `string` with `style` after old content of that line, /// adding lines if needed pub(crate) fn append(&mut self, line: usize, string: &str, style: ElementStyle) { if line >= self.lines.len() { self.puts(line, 0, string, style); } else { let col = self.lines[line].len(); self.puts(line, col, string, style); } } pub(crate) fn replace(&mut self, line: usize, start: usize, end: usize, string: &str) { if start == end { return; } // If the replacement range would be out of bounds, do nothing, as we // can't replace things that don't exist. if start > self.lines[line].len() || end > self.lines[line].len() { return; }; self.lines[line].splice( start..end, string .chars() .map(|c| StyledChar::new(c, ElementStyle::LineNumber)), ); } pub(crate) fn num_lines(&self) -> usize { self.lines.len() } /// Set `style` for `line`, `col_start..col_end` range if: /// 1. That line and column range exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub(crate) fn set_style_range( &mut self, line: usize, col_start: usize, col_end: usize, style: ElementStyle, overwrite: bool, ) { for col in col_start..col_end { self.set_style(line, col, style, overwrite); } } /// Set `style` for `line`, `col` if: /// 1. That line and column exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub(crate) fn set_style( &mut self, line: usize, col: usize, style: ElementStyle, overwrite: bool, ) { if let Some(ref mut line) = self.lines.get_mut(line) && let Some(StyledChar { style: s, .. }) = line.get_mut(col) && (overwrite || matches!(s, ElementStyle::NoStyle | ElementStyle::Quotation)) { *s = style; } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/renderer/stylesheet.rs000064400000000000000000000017121046102023000245420ustar00use anstyle::Style; #[derive(Clone, Copy, Debug)] pub(crate) struct Stylesheet { pub(crate) error: Style, pub(crate) warning: Style, pub(crate) info: Style, pub(crate) note: Style, pub(crate) help: Style, pub(crate) line_num: Style, pub(crate) emphasis: Style, pub(crate) none: Style, pub(crate) context: Style, pub(crate) addition: Style, pub(crate) removal: Style, } impl Default for Stylesheet { fn default() -> Self { Self::plain() } } impl Stylesheet { pub(crate) const fn plain() -> Self { Self { error: Style::new(), warning: Style::new(), info: Style::new(), note: Style::new(), help: Style::new(), line_num: Style::new(), emphasis: Style::new(), none: Style::new(), context: Style::new(), addition: Style::new(), removal: Style::new(), } } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/src/snippet.rs000064400000000000000000000444401046102023000222320ustar00//! Structures used as an input for the library. use alloc::borrow::{Cow, ToOwned}; use alloc::string::String; use alloc::{vec, vec::Vec}; use core::ops::Range; use crate::Level; use crate::renderer::source_map::{TrimmedPatch, as_substr}; pub(crate) const ERROR_TXT: &str = "error"; pub(crate) const HELP_TXT: &str = "help"; pub(crate) const INFO_TXT: &str = "info"; pub(crate) const NOTE_TXT: &str = "note"; pub(crate) const WARNING_TXT: &str = "warning"; /// A [diagnostic message][Title] and any associated [context][Element] to help users /// understand it /// /// The first [`Group`] is the ["primary" group][Level::primary_title], ie it contains the diagnostic /// message. /// /// All subsequent [`Group`]s are for distinct pieces of [context][Level::secondary_title]. /// The primary group will be visually distinguished to help tell them apart. pub type Report<'a> = &'a [Group<'a>]; #[derive(Clone, Debug, Default)] pub(crate) struct Id<'a> { pub(crate) id: Option>, pub(crate) url: Option>, } /// A [`Title`] with supporting [context][Element] within a [`Report`] /// /// [Decor][crate::renderer::DecorStyle] is used to visually connect [`Element`]s of a `Group`. /// /// Generally, you will create separate group's for: /// - New [`Snippet`]s, especially if they need their own [`AnnotationKind::Primary`] /// - Each logically distinct set of [suggestions][Patch`] /// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/highlight_message.rs")] /// ``` #[doc = include_str!("../examples/highlight_message.svg")] #[derive(Clone, Debug)] pub struct Group<'a> { pub(crate) primary_level: Level<'a>, pub(crate) title: Option>, pub(crate) elements: Vec>, pub(crate) lineno_offset: usize, } impl<'a> Group<'a> { /// Create group with a [`Title`], deriving [`AnnotationKind::Primary`] from its [`Level`] pub fn with_title(title: Title<'a>) -> Self { let level = title.level.clone(); let mut x = Self::with_level(level); x.title = Some(title); x } /// Create a title-less group with a primary [`Level`] for [`AnnotationKind::Primary`] /// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/elide_header.rs")] /// ``` #[doc = include_str!("../examples/elide_header.svg")] pub fn with_level(level: Level<'a>) -> Self { Self { primary_level: level, title: None, elements: vec![], lineno_offset: 0, } } /// Append an [`Element`] that adds context to the [`Title`] pub fn element(mut self, section: impl Into>) -> Self { self.elements.push(section.into()); self } /// Append [`Element`]s that adds context to the [`Title`] pub fn elements(mut self, sections: impl IntoIterator>>) -> Self { self.elements.extend(sections.into_iter().map(Into::into)); self } pub fn is_empty(&self) -> bool { self.elements.is_empty() && self.title.is_none() } /// Add an offset used for aligning the header sigil (`-->`) with the line number separators. /// /// For normal diagnostics this is computed automatically based on the lines to be rendered. /// This is intended only for use in the formatter, where we don't render a snippet directly but /// still want the header to align with the diff. pub fn lineno_offset(mut self, offset: usize) -> Self { self.lineno_offset = offset; self } } /// A section of content within a [`Group`] #[derive(Clone, Debug)] #[non_exhaustive] pub enum Element<'a> { Message(Message<'a>), Cause(Snippet<'a, Annotation<'a>>), Suggestion(Snippet<'a, Patch<'a>>), Origin(Origin<'a>), Padding(Padding), } impl<'a> From> for Element<'a> { fn from(value: Message<'a>) -> Self { Element::Message(value) } } impl<'a> From>> for Element<'a> { fn from(value: Snippet<'a, Annotation<'a>>) -> Self { Element::Cause(value) } } impl<'a> From>> for Element<'a> { fn from(value: Snippet<'a, Patch<'a>>) -> Self { Element::Suggestion(value) } } impl<'a> From> for Element<'a> { fn from(value: Origin<'a>) -> Self { Element::Origin(value) } } impl From for Element<'_> { fn from(value: Padding) -> Self { Self::Padding(value) } } /// A whitespace [`Element`] in a [`Group`] #[derive(Clone, Debug)] pub struct Padding; /// A title that introduces a [`Group`], describing the main point /// /// To create a `Title`, see [`Level::primary_title`] or [`Level::secondary_title`]. /// /// # Example /// /// ```rust /// # use annotate_snippets::*; /// let report = &[ /// Group::with_title( /// Level::ERROR.primary_title("mismatched types").id("E0308") /// ), /// Group::with_title( /// Level::HELP.secondary_title("function defined here") /// ), /// ]; /// ``` #[derive(Clone, Debug)] pub struct Title<'a> { pub(crate) level: Level<'a>, pub(crate) id: Option>, pub(crate) text: Cow<'a, str>, pub(crate) allows_styling: bool, pub(crate) is_fixable: bool, } impl<'a> Title<'a> { /// The category for this [`Report`] /// /// Useful for looking searching for more information to resolve the diagnostic. /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Styled text is /// not allowed to be passed to this function. /// ///
pub fn id(mut self, id: impl Into>) -> Self { self.id.get_or_insert(Id::default()).id = Some(id.into()); self } /// Provide a URL for [`Title::id`] for more information on this diagnostic /// ///
/// /// This is only relevant if `id` is present /// ///
pub fn id_url(mut self, url: impl Into>) -> Self { self.id.get_or_insert(Id::default()).url = Some(url.into()); self } /// Append an [`Element`] that adds context to the [`Title`] pub fn element(self, section: impl Into>) -> Group<'a> { Group::with_title(self).element(section) } /// Append [`Element`]s that adds context to the [`Title`] pub fn elements(self, sections: impl IntoIterator>>) -> Group<'a> { Group::with_title(self).elements(sections) } /// Whether or not the diagnostic for this message is fixable. /// /// This is rendered as a `[*]` indicator after the `id` in an annotation header, if the /// annotation also has `Level::None`. pub fn is_fixable(mut self, yes: bool) -> Self { self.is_fixable = yes; self } } /// A text [`Element`] in a [`Group`] /// /// See [`Level::message`] to create this. #[derive(Clone, Debug)] pub struct Message<'a> { pub(crate) level: Level<'a>, pub(crate) text: Cow<'a, str>, } /// A source view [`Element`] in a [`Group`] /// /// If you do not have [source][Snippet::source] available, see instead [`Origin`] /// /// `Snippet`s come in the following styles (`T`): /// - With [`Annotation`]s, see [`Snippet::annotation`] /// - With [`Patch`]s, see [`Snippet::patch`] #[derive(Clone, Debug)] pub struct Snippet<'a, T> { pub(crate) path: Option>, /// The optional cell index in a Jupyter notebook, used for reporting source locations along /// with the ranges on `annotations`. pub(crate) cell_index: Option, pub(crate) line_start: usize, pub(crate) source: Cow<'a, str>, pub(crate) markers: Vec, pub(crate) fold: bool, } impl<'a, T: Clone> Snippet<'a, T> { /// The source code to be rendered /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
pub fn source(source: impl Into>) -> Self { Self { path: None, line_start: 1, cell_index: None, source: source.into(), markers: vec![], fold: true, } } /// When manually [`fold`][Self::fold]ing, /// the [`source`][Self::source]s line offset from the original start pub fn line_start(mut self, line_start: usize) -> Self { self.line_start = line_start; self } /// The location of the [`source`][Self::source] (e.g. a path) /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
pub fn path(mut self, path: impl Into>) -> Self { self.path = path.into().0; self } /// Attach a Jupyter notebook cell index. pub fn cell_index(mut self, index: Option) -> Self { self.cell_index = index; self } /// Control whether lines without [`Annotation`]s are shown /// /// The default is `fold(true)`, collapsing uninteresting lines. /// /// See [`AnnotationKind::Visible`] to force specific spans to be shown. pub fn fold(mut self, fold: bool) -> Self { self.fold = fold; self } } impl<'a> Snippet<'a, Annotation<'a>> { /// Highlight and describe a span of text within the [`source`][Self::source] pub fn annotation(mut self, annotation: Annotation<'a>) -> Snippet<'a, Annotation<'a>> { self.markers.push(annotation); self } /// Highlight and describe spans of text within the [`source`][Self::source] pub fn annotations(mut self, annotation: impl IntoIterator>) -> Self { self.markers.extend(annotation); self } } impl<'a> Snippet<'a, Patch<'a>> { /// Suggest to the user an edit to the [`source`][Self::source] pub fn patch(mut self, patch: Patch<'a>) -> Snippet<'a, Patch<'a>> { self.markers.push(patch); self } /// Suggest to the user edits to the [`source`][Self::source] pub fn patches(mut self, patches: impl IntoIterator>) -> Self { self.markers.extend(patches); self } } /// Highlight and describe a span of text within a [`Snippet`] /// /// See [`AnnotationKind`] to create an annotation. /// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/expected_type.rs")] /// ``` /// #[doc = include_str!("../examples/expected_type.svg")] #[derive(Clone, Debug)] pub struct Annotation<'a> { pub(crate) span: Range, pub(crate) label: Option>, pub(crate) kind: AnnotationKind, pub(crate) highlight_source: bool, pub(crate) is_file_level: bool, } impl<'a> Annotation<'a> { /// Describe the reason the span is highlighted /// /// This will be styled according to the [`AnnotationKind`] /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
pub fn label(mut self, label: impl Into>) -> Self { self.label = label.into().0; self } /// Style the source according to the [`AnnotationKind`] /// /// This gives extra emphasis to this annotation pub fn highlight_source(mut self, highlight_source: bool) -> Self { self.highlight_source = highlight_source; self } pub fn hide_snippet(mut self, yes: bool) -> Self { self.is_file_level = yes; self } } /// The type of [`Annotation`] being applied to a [`Snippet`] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] pub enum AnnotationKind { /// For showing the source that the [Group's Title][Group::with_title] references /// /// For [`Title`]-less groups, see [`Group::with_level`] Primary, /// Additional context to better understand the [`Primary`][Self::Primary] /// [`Annotation`] /// /// See also [`Renderer::context`]. /// /// [`Renderer::context`]: crate::renderer::Renderer Context, /// Prevents the annotated text from getting [folded][Snippet::fold] /// /// By default, [`Snippet`]s will [fold][`Snippet::fold`] (remove) lines /// that do not contain any annotations. [`Visible`][Self::Visible] makes /// it possible to selectively prevent this behavior for specific text, /// allowing context to be preserved without adding any annotation /// characters. /// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/struct_name_as_context.rs")] /// ``` /// #[doc = include_str!("../examples/struct_name_as_context.svg")] /// Visible, } impl AnnotationKind { /// Annotate a byte span within [`Snippet`] pub fn span<'a>(self, span: Range) -> Annotation<'a> { Annotation { span, label: None, kind: self, highlight_source: false, is_file_level: false, } } pub(crate) fn is_primary(&self) -> bool { matches!(self, AnnotationKind::Primary) } } /// Suggested edit to the [`Snippet`] /// /// See [`Snippet::patch`] /// /// # Example /// /// ```rust /// # #[allow(clippy::needless_doctest_main)] #[doc = include_str!("../examples/multi_suggestion.rs")] /// ``` /// #[doc = include_str!("../examples/multi_suggestion.svg")] #[derive(Clone, Debug)] pub struct Patch<'a> { pub(crate) span: Range, pub(crate) replacement: Cow<'a, str>, } impl<'a> Patch<'a> { /// Splice `replacement` into the [`Snippet`] at the specified byte span /// ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
pub fn new(span: Range, replacement: impl Into>) -> Self { Self { span, replacement: replacement.into(), } } /// Try to turn a replacement into an addition when the span that is being /// overwritten matches either the prefix or suffix of the replacement. pub(crate) fn trim_trivial_replacements(self, source: &str) -> TrimmedPatch<'a> { let mut trimmed = TrimmedPatch { original_span: self.span.clone(), span: self.span, replacement: self.replacement, }; if trimmed.replacement.is_empty() { return trimmed; } let Some(snippet) = source.get(trimmed.original_span.clone()) else { return trimmed; }; if let Some((prefix, substr, suffix)) = as_substr(snippet, &trimmed.replacement) { trimmed.span = trimmed.original_span.start + prefix ..trimmed.original_span.end.saturating_sub(suffix); trimmed.replacement = Cow::Owned(substr.to_owned()); } trimmed } } /// A source location [`Element`] in a [`Group`] /// /// If you have source available, see instead [`Snippet`] /// /// # Example /// /// ```rust /// # use annotate_snippets::{Group, Snippet, AnnotationKind, Level, Origin}; /// let report = &[ /// Level::ERROR.primary_title("mismatched types").id("E0308") /// .element( /// Origin::path("$DIR/mismatched-types.rs") /// ) /// ]; /// ``` #[derive(Clone, Debug)] pub struct Origin<'a> { pub(crate) path: Option>, /// The optional cell index in a Jupyter notebook, used for reporting source locations along /// with the ranges on `annotations`. pub(crate) cell_index: Option, pub(crate) line: Option, pub(crate) char_column: Option, } impl<'a> Origin<'a> { ///
/// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. /// ///
pub fn path(path: impl Into>) -> Self { Self { path: Some(path.into()), cell_index: None, line: None, char_column: None, } } /// Attach a Jupyter notebook cell index. pub fn cell_index(mut self, index: Option) -> Self { self.cell_index = index; self } /// Set the default line number to display pub fn line(mut self, line: usize) -> Self { self.line = Some(line); self } /// Set the default column to display /// ///
/// /// `char_column` is only be respected if [`Origin::line`] is also set. /// ///
pub fn char_column(mut self, char_column: usize) -> Self { self.char_column = Some(char_column); self } } impl<'a> From> for Origin<'a> { fn from(origin: Cow<'a, str>) -> Self { Self::path(origin) } } #[derive(Debug)] pub struct OptionCow<'a>(pub(crate) Option>); impl<'a, T: Into>> From> for OptionCow<'a> { fn from(value: Option) -> Self { Self(value.map(Into::into)) } } impl<'a> From<&'a Cow<'a, str>> for OptionCow<'a> { fn from(value: &'a Cow<'a, str>) -> Self { Self(Some(Cow::Borrowed(value))) } } impl<'a> From> for OptionCow<'a> { fn from(value: Cow<'a, str>) -> Self { Self(Some(value)) } } impl<'a> From<&'a str> for OptionCow<'a> { fn from(value: &'a str) -> Self { Self(Some(Cow::Borrowed(value))) } } impl<'a> From for OptionCow<'a> { fn from(value: String) -> Self { Self(Some(Cow::Owned(value))) } } impl<'a> From<&'a String> for OptionCow<'a> { fn from(value: &'a String) -> Self { Self(Some(Cow::Borrowed(value.as_str()))) } } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_eof.ascii.term.svg000064400000000000000000000024201046102023000260460ustar00 error: expected `.`, `=` --> Cargo.toml:1:5 | 1 | asdf | ^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_eof.rs000064400000000000000000000013701046102023000236410ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let input = &[Level::ERROR.primary_title("expected `.`, `=`").element( Snippet::source("asdf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(4..4).label("")), )]; let expected_ascii = file!["ann_eof.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ann_eof.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_eof.unicode.term.svg000064400000000000000000000024331046102023000264100ustar00 error: expected `.`, `=` ╭▸ Cargo.toml:1:5 │ 1 │ asdf ╰╴ ━ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_insertion.ascii.term.svg000064400000000000000000000025271046102023000273170ustar00 error: expected `.`, `=` --> Cargo.toml:1:3 | 1 | asf | ^ 'd' belongs here ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_insertion.rs000064400000000000000000000014231046102023000251010ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let input = &[Level::ERROR.primary_title("expected `.`, `=`").element( Snippet::source("asf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(2..2).label("'d' belongs here")), )]; let expected_ascii = file!["ann_insertion.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ann_insertion.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_insertion.unicode.term.svg000064400000000000000000000025421046102023000276520ustar00 error: expected `.`, `=` ╭▸ Cargo.toml:1:3 │ 1 │ asf ╰╴ ━ 'd' belongs here ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline.ascii.term.svg000064400000000000000000000043111046102023000273000ustar00 error[E0027]: pattern does not mention fields `lineno`, `content` --> src/display_list.rs:139:32 | 139 | if let DisplayLine::Source { | ________________________________^ 140 | | ref mut inline_marks, 141 | | } = body[body_idx] | |_________________________^ missing fields `lineno`, `content` ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline.rs000064400000000000000000000022621046102023000250730ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" if let DisplayLine::Source { ref mut inline_marks, } = body[body_idx] "#; let input = &[Level::ERROR .primary_title("pattern does not mention fields `lineno`, `content`") .id("E0027") .element( Snippet::source(source) .path("src/display_list.rs") .line_start(139) .fold(false) .annotation( AnnotationKind::Primary .span(31..128) .label("missing fields `lineno`, `content`"), ), )]; let expected_ascii = file!["ann_multiline.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ann_multiline.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline.unicode.term.svg000064400000000000000000000045071046102023000276450ustar00 error[E0027]: pattern does not mention fields `lineno`, `content` ╭▸ src/display_list.rs:139:32 │ 139 │ if let DisplayLine::Source { │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 140 │ ┃ ref mut inline_marks, 141 │ ┃ } = body[body_idx] ╰╴┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ missing fields `lineno`, `content` ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline2.ascii.term.svg000064400000000000000000000036171046102023000273720ustar00 error[E####]: spacing error found --> foo.txt:26:12 | 26 | This is an example | ^^^^^^^ this should not be on separate lines 27 | of an edge case of an annotation overflowing 28 | to exactly one character on next line. | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline2.rs000064400000000000000000000021351046102023000251540ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"This is an example of an edge case of an annotation overflowing to exactly one character on next line. "#; let input = &[Level::ERROR .primary_title("spacing error found") .id("E####") .element( Snippet::source(source) .path("foo.txt") .line_start(26) .fold(false) .annotation( AnnotationKind::Primary .span(11..19) .label("this should not be on separate lines"), ), )]; let expected_ascii = file!["ann_multiline2.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ann_multiline2.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_multiline2.unicode.term.svg000064400000000000000000000036551046102023000277320ustar00 error[E####]: spacing error found ╭▸ foo.txt:26:12 │ 26 │ This is an example │ ━━━━━━━ this should not be on separate lines 27 │ of an edge case of an annotation overflowing 28 │ to exactly one character on next line. ╰╴ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_removed_nl.ascii.term.svg000064400000000000000000000024201046102023000274270ustar00 error: expected `.`, `=` --> Cargo.toml:1:5 | 1 | asdf | ^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_removed_nl.rs000064400000000000000000000014061046102023000252220ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let input = &[Level::ERROR.primary_title("expected `.`, `=`").element( Snippet::source("asdf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(4..5).label("")), )]; let expected_ascii = file!["ann_removed_nl.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ann_removed_nl.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ann_removed_nl.unicode.term.svg000064400000000000000000000024331046102023000277710ustar00 error: expected `.`, `=` ╭▸ Cargo.toml:1:5 │ 1 │ asdf ╰╴ ━ ensure_emoji_highlight_width.ascii.term.svg000064400000000000000000000027771046102023000323130ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error: invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) --> <file>:7:1 | 7 | "haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/ensure_emoji_highlight_width.rs000064400000000000000000000020511046102023000301430ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#""haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } "#; let input = &[Level::ERROR.primary_title("invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)") .element( Snippet::source(source) .path("") .line_start(7) .annotation(AnnotationKind::Primary.span(0..35).label("")) )]; let expected_ascii = file!["ensure_emoji_highlight_width.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["ensure_emoji_highlight_width.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ensure_emoji_highlight_width.unicode.term.svg000064400000000000000000000030731046102023000326370ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error: invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) ╭▸ <file>:7:1 │ 7 │ "haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } ╰╴━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ first_snippet_is_primary.ascii.term.svg000064400000000000000000000060141046102023000315140ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types --> $DIR/file.txt:3:1 | 3 | this is from a txt file | ----------------------- the macro expands to this string | ::: $DIR/mismatched-types.rs:2:12 | 2 | let b: &[u8] = include_str!("file.txt"); | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[u8]`, found `&str` | | | expected due to this | = note: expected reference `&[u8]` found reference `&'static str` ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/first_snippet_is_primary.rs000064400000000000000000000034131046102023000273630ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let file_txt_source = r#"this is from a txt file"#; let rust_source = r#"fn main() { let b: &[u8] = include_str!("file.txt"); let s: &str = include_bytes!("file.txt"); }"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(file_txt_source) .line_start(3) .path("$DIR/file.txt") .annotation( AnnotationKind::Context .span(0..23) .label("the macro expands to this string"), ), ) .element( Snippet::source(rust_source) .path("$DIR/mismatched-types.rs") .annotation( AnnotationKind::Context .span(23..28) .label("expected due to this"), ) .annotation( AnnotationKind::Primary .span(31..55) .label("expected `&[u8]`, found `&str`"), ), ) .element( Level::NOTE.message("expected reference `&[u8]`\n found reference `&'static str`"), )]; let expected_ascii = file!["first_snippet_is_primary.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["first_snippet_is_primary.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } first_snippet_is_primary.unicode.term.svg000064400000000000000000000062171046102023000320570ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types ╭▸ $DIR/file.txt:3:1 │ 3 │ this is from a txt file │ ─────────────────────── the macro expands to this string │ ⸬ $DIR/mismatched-types.rs:2:12 │ 2 │ let b: &[u8] = include_str!("file.txt"); │ ┬──── ━━━━━━━━━━━━━━━━━━━━━━━━ expected `&[u8]`, found `&str` │ │ │ expected due to this │ ╰ note: expected reference `&[u8]` found reference `&'static str` ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_ann_multiline.ascii.term.svg000064400000000000000000000062311046102023000303070ustar00 error[E0308]: mismatched types --> src/format.rs:52:1 | 51 | ) -> Option<String> { | -------------- expected `std::option::Option<std::string::String>` because of return type 52 | / for ann in annotations { 53 | | match (ann.range.0, ann.range.1) { 54 | | (None, None) => continue, 55 | | (Some(start), Some(end)) if start > end_index || end < start_index => continue, ... | 72 | | } | |_____^ expected enum `std::option::Option`, found () ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_ann_multiline.rs000064400000000000000000000036511046102023000261020ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#") -> Option { for ann in annotations { match (ann.range.0, ann.range.1) { (None, None) => continue, (Some(start), Some(end)) if start > end_index || end < start_index => continue, (Some(start), Some(end)) if start >= start_index && end <= end_index => { let label = if let Some(ref label) = ann.label { format!(" {}", label) } else { String::from("") }; return Some(format!( "{}{}{}", " ".repeat(start - start_index), "^".repeat(end - start), label )); } _ => continue, } } "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("src/format.rs") .line_start(51) .annotation(AnnotationKind::Context.span(5..19).label( "expected `std::option::Option` because of return type", )) .annotation( AnnotationKind::Primary .span(22..766) .label("expected enum `std::option::Option`, found ()"), ), )]; let expected_ascii = file!["fold_ann_multiline.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["fold_ann_multiline.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_ann_multiline.unicode.term.svg000064400000000000000000000063461046102023000306540ustar00 error[E0308]: mismatched types ╭▸ src/format.rs:52:1 │ 51 │ ) -> Option<String> { │ ────────────── expected `std::option::Option<std::string::String>` because of return type 52 │ ┏ for ann in annotations { 53 │ ┃ match (ann.range.0, ann.range.1) { 54 │ ┃ (None, None) => continue, 55 │ ┃ (Some(start), Some(end)) if start > end_index || end < start_index => continue, ┆ ┇ 72 │ ┃ } ╰╴┗━━━━━┛ expected enum `std::option::Option`, found () ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_bad_origin_line.ascii.term.svg000064400000000000000000000025361046102023000305610ustar00 error: --> path/to/error.rs:3:1 | 3 | invalid syntax | -------------- error here ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_bad_origin_line.rs000064400000000000000000000014741046102023000263510ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" invalid syntax "#; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("path/to/error.rs") .line_start(1) .annotation(AnnotationKind::Context.span(2..16).label("error here")), )]; let expected_ascii = file!["fold_bad_origin_line.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["fold_bad_origin_line.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_bad_origin_line.unicode.term.svg000064400000000000000000000025111046102023000311100ustar00 error: ╭▸ path/to/error.rs:3:1 │ 3 │ invalid syntax ╰╴────────────── error here ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_leading.ascii.term.svg000064400000000000000000000025121046102023000270520ustar00 error[E0308]: invalid type: integer `20`, expected a bool --> Cargo.toml:11:13 | 11 | workspace = 20 | ^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_leading.rs000064400000000000000000000017731046102023000246520ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"[workspace] [package] name = "hello" version = "1.0.0" license = "MIT" rust-version = "1.70" edition = "2021" [lints] workspace = 20 "#; let input = &[Level::ERROR .primary_title("invalid type: integer `20`, expected a bool") .id("E0308") .element( Snippet::source(source) .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(132..134).label("")), )]; let expected_ascii = file!["fold_leading.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["fold_leading.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_leading.unicode.term.svg000064400000000000000000000025271046102023000274160ustar00 error[E0308]: invalid type: integer `20`, expected a bool ╭▸ Cargo.toml:11:13 │ 11 │ workspace = 20 ╰╴ ━━ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_trailing.ascii.term.svg000064400000000000000000000025031046102023000272600ustar00 error[E0308]: invalid type: integer `20`, expected a lints table --> Cargo.toml:1:9 | 1 | lints = 20 | ^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_trailing.rs000064400000000000000000000017651046102023000250610ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"lints = 20 [workspace] [package] name = "hello" version = "1.0.0" license = "MIT" rust-version = "1.70" edition = "2021" "#; let input = &[Level::ERROR .primary_title("invalid type: integer `20`, expected a lints table") .id("E0308") .element( Snippet::source(source) .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(8..10).label("")), )]; let expected_ascii = file!["fold_trailing.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["fold_trailing.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/fold_trailing.unicode.term.svg000064400000000000000000000025201046102023000276150ustar00 error[E0308]: invalid type: integer `20`, expected a lints table ╭▸ Cargo.toml:1:9 │ 1 │ lints = 20 ╰╴ ━━ highlight_diff_line_with_wide_characters.ascii.term.svg000064400000000000000000000062321046102023000345770ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0422]: cannot find struct, variant or union type `哈哈哈哈` in this scope --> $DIR/highlight_diff_line_with_wide_characters.rs:3:18 | 1 | struct 啊啊啊啊 {} | ------------------ similarly named struct `啊啊啊啊` defined here 2 | 3 | const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment | ^^^^^^^^ here | help: a struct with a similar name exists: `啊啊啊啊` | 3 - const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment 3 + const 哦哦: 啊啊啊啊 = 啊啊啊啊 {}; // some comment | highlight_diff_line_with_wide_characters.rs000064400000000000000000000031671046102023000323730ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/coloruse annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"struct 啊啊啊啊 {} const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment"#; let path = "$DIR/highlight_diff_line_with_wide_characters.rs"; let report = &[ Level::ERROR .primary_title("cannot find struct, variant or union type `哈哈哈哈` in this scope") .id("E0422") .element( Snippet::source(source) .path(path) .annotation(AnnotationKind::Primary.span(53..65).label("here")) .annotation( AnnotationKind::Context .span(0..22) .label("similarly named struct `啊啊啊啊` defined here"), ), ), Level::HELP .secondary_title("a struct with a similar name exists: `啊啊啊啊`") .element( Snippet::source(source) .path(path) .patch(Patch::new(53..65, "啊啊啊啊")), ), ]; let expected_ascii = file!["highlight_diff_line_with_wide_characters.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["highlight_diff_line_with_wide_characters.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } highlight_diff_line_with_wide_characters.unicode.term.svg000064400000000000000000000063521046102023000351400ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0422]: cannot find struct, variant or union type `哈哈哈哈` in this scope ╭▸ $DIR/highlight_diff_line_with_wide_characters.rs:3:18 │ 1 │ struct 啊啊啊啊 {} │ ────────────────── similarly named struct `啊啊啊啊` defined here 2 │ 3 │ const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment │ ━━━━━━━━ here ╰╴ help: a struct with a similar name exists: `啊啊啊啊` ╭╴ 3 - const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment 3 + const 哦哦: 啊啊啊啊 = 啊啊啊啊 {}; // some comment ╰╴ highlight_duplicated_diff_lines.ascii.term.svg000064400000000000000000000065731046102023000327260ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0061]: this function takes 6 arguments but 7 arguments were supplied --> $DIR/wrong-highlight-span-extra-arguments-147070.rs:17:15 | 17 | let foo = Thingy::new( | ^^^^^^^^^^^ ... 24 | String::from(""), | ---------------- unexpected argument #7 of type `String` | note: associated function defined here --> $DIR/wrong-highlight-span-extra-arguments-147070.rs:4:19 | 4 | pub(crate) fn new( | ^^^ help: remove the extra argument | 23 - String::from(""), | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_duplicated_diff_lines.rs000064400000000000000000000044741046102023000305730ustar00use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { // https://github.com/rust-lang/rust/blob/4b94758d2ba7d0ef71ccf5fde29ce4bc5d6fe2a4/tests/ui/argument-suggestions/wrong-highlight-span-extra-arguments-147070.rs let source = r#"struct Thingy; impl Thingy { pub(crate) fn new( _a: String, _b: String, _c: String, _d: String, _e: String, _f: String, ) -> Self { unimplemented!() } } fn main() { let foo = Thingy::new( String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), ); }"#; let path = "$DIR/wrong-highlight-span-extra-arguments-147070.rs"; let report = &[ Level::ERROR .primary_title("this function takes 6 arguments but 7 arguments were supplied") .id("E0061") .element( Snippet::source(source) .path(path) .annotation( AnnotationKind::Context .span(426..442) .label("unexpected argument #7 of type `String`"), ) .annotation(AnnotationKind::Primary.span(249..260)), ), Level::NOTE .secondary_title("associated function defined here") .element( Snippet::source(source) .path(path) .annotation(AnnotationKind::Primary.span(48..51)), ), Level::HELP .secondary_title("remove the extra argument") .element( Snippet::source(source) .path(path) .patch(Patch::new(413..439, "")), ), ]; let expected_ascii = file!["highlight_duplicated_diff_lines.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["highlight_duplicated_diff_lines.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } highlight_duplicated_diff_lines.unicode.term.svg000064400000000000000000000067541046102023000332650ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0061]: this function takes 6 arguments but 7 arguments were supplied ╭▸ $DIR/wrong-highlight-span-extra-arguments-147070.rs:17:15 │ 17 │ let foo = Thingy::new( │ ━━━━━━━━━━━ ┆ 24 │ String::from(""), │ ──────────────── unexpected argument #7 of type `String` ╰╴ note: associated function defined here ╭▸ $DIR/wrong-highlight-span-extra-arguments-147070.rs:4:19 │ 4 │ pub(crate) fn new( ╰╴ ━━━ help: remove the extra argument ╭╴ 23 - String::from(""), ╰╴ highlight_first_line_tab_371.ascii.term.svg000064400000000000000000000035421046102023000317750ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error: <sample error message> ::: <sample path>:6:18 | 6 - ts.into_iter().map(|t| { 7 - (is_true, t) 8 - }).flatten() 6 + ts.into_iter().flatten() | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_first_line_tab_371.rs000064400000000000000000000012271046102023000276420ustar00use annotate_snippets::{Level, Patch, Renderer, Snippet}; use snapbox::{assert_data_eq, file}; #[test] fn test() { let report = &[Level::ERROR .primary_title("") .element( Snippet::source( "\t\t\tts.into_iter().map(|t| {\n\t\t\t\t(is_true, t)\n\t\t\t}).flatten()\n", ) .line_start(6) .path("") .patch(Patch::new(17..50, "")), )]; let expected_ascii = file!["highlight_first_line_tab_371.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_source.ascii.term.svg000064400000000000000000000034121046102023000277720ustar00 error: all annotation kinds have a highlighted source --> Cargo.toml:9:1 | 2 | [workspace.lints.rust] ... 9 | unused_qualifications = "warn" | ^^^^^^^^^^^^^^^^^^^^^ ------ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_source.rs000064400000000000000000000026621046102023000255700ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" [workspace.lints.rust] rust_2018_idioms = { level = "warn", priority = -1 } unnameable_types = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" "#; let input = &[Level::ERROR .primary_title("all annotation kinds have a highlighted source") .element( Snippet::source(source) .path("Cargo.toml") .annotation( AnnotationKind::Primary .span(214..235) .highlight_source(true), ) .annotation( AnnotationKind::Context .span(238..244) .highlight_source(true), ) .annotation(AnnotationKind::Visible.span(2..22).highlight_source(true)), )]; let expected_ascii = file!["highlight_source.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["highlight_source.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_source.unicode.term.svg000064400000000000000000000035151046102023000303340ustar00 error: all annotation kinds have a highlighted source ╭▸ Cargo.toml:9:1 │ 2 │ [workspace.lints.rust] ┆ 9 │ unused_qualifications = "warn" ╰╴━━━━━━━━━━━━━━━━━━━━━ ────── highlight_source_multi_width_chars.ascii.term.svg000064400000000000000000000021301046102023000335000ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color | 1 | [lorem ipsum](表意文字) | ^^^^^^^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_source_multi_width_chars.rs000064400000000000000000000014611046102023000313550ustar00use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"[lorem ipsum](表意文字)"#; let report = &[Group::with_level(Level::WARNING).element( Snippet::source(source) .annotation(AnnotationKind::Primary.span(14..26).highlight_source(true)), )]; let expected_ascii = file!["highlight_source_multi_width_chars.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["highlight_source_multi_width_chars.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } highlight_source_multi_width_chars.unicode.term.svg000064400000000000000000000021641046102023000340450ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color ╭▸ 1 │ [lorem ipsum](表意文字) ╰╴ ━━━━━━━━ highlight_source_zero_width_chars.ascii.term.svg000064400000000000000000000022661046102023000333370ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color | 1 | [résumé] [naïve] | ^^^^^^ ^^^^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/highlight_source_zero_width_chars.rs000064400000000000000000000015761046102023000312110ustar00use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"[résumé] [naïve]"#; let report = &[Group::with_level(Level::WARNING).element( Snippet::source(source) .annotation(AnnotationKind::Primary.span(1..11).highlight_source(true)) .annotation(AnnotationKind::Primary.span(14..21).highlight_source(true)), )]; let expected_ascii = file!["highlight_source_zero_width_chars.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["highlight_source_zero_width_chars.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } highlight_source_zero_width_chars.unicode.term.svg000064400000000000000000000023301046102023000336650ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color ╭▸ 1 │ [résumé] [naïve] ╰╴ ━━━━━━ ━━━━━ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/issue_9.ascii.term.svg000064400000000000000000000050541046102023000260270ustar00 error: expected one of `.`, `;`, `?`, or an operator, found `for` --> /code/rust/src/test/ui/annotate-snippet/suggestion.rs:9:1 | 4 | let x = vec![1]; | - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait ... 7 | let y = x; | - value moved here 8 | 9 | x; | ^ value used here after move ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/issue_9.rs000064400000000000000000000023121046102023000236110ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"let x = vec![1]; let y = x; x; "#; let input = &[Level::ERROR.primary_title("expected one of `.`, `;`, `?`, or an operator, found `for`") .element( Snippet::source(source) .path("/code/rust/src/test/ui/annotate-snippet/suggestion.rs") .line_start(4) .annotation(AnnotationKind::Context.span(4..5).label("move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait")) .annotation(AnnotationKind::Context.span(27..28).label("value moved here")) .annotation(AnnotationKind::Primary.span(31..32).label("value used here after move")) ) ]; let expected_ascii = file!["issue_9.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["issue_9.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/issue_9.unicode.term.svg000064400000000000000000000051071046102023000263640ustar00 error: expected one of `.`, `;`, `?`, or an operator, found `for` ╭▸ /code/rust/src/test/ui/annotate-snippet/suggestion.rs:9:1 │ 4 │ let x = vec![1]; │ ─ move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait ┆ 7 │ let y = x; │ ─ value moved here 8 │ 9 │ x; ╰╴━ value used here after move ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/main.rs000064400000000000000000000015501046102023000231600ustar00mod ann_eof; mod ann_insertion; mod ann_multiline; mod ann_multiline2; mod ann_removed_nl; mod ensure_emoji_highlight_width; mod first_snippet_is_primary; mod fold_ann_multiline; mod fold_bad_origin_line; mod fold_leading; mod fold_trailing; mod highlight_diff_line_with_wide_characters; mod highlight_duplicated_diff_lines; mod highlight_first_line_tab_371; mod highlight_source; mod highlight_source_multi_width_chars; mod highlight_source_zero_width_chars; mod issue_9; mod multiline_removal_indent; mod multiline_removal_last_line_tabs; mod multiline_removal_suggestion; mod multiple_annotations; mod multiple_highlight_duplicated; mod multiple_multiline_removal; mod primary_title_second_group; mod regression_leading_tab_label_alignment; mod regression_leading_tab_long_line; mod simple; mod strip_line; mod strip_line_char; mod strip_line_non_ws; mod styled_title; multiline_removal_indent.ascii.term.svg000064400000000000000000000024311046102023000314540ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color | 2 - local function f() 3 - print() 4 - end | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiline_removal_indent.rs000064400000000000000000000013431046102023000273240ustar00use annotate_snippets::{Group, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn test() { let report = &[Group::with_level(Level::ERROR).element( Snippet::source("do\n local function f()\n print()\n end\nend\n") .patch(Patch::new(5..41, "")), )]; let expected_ascii = file!["multiline_removal_indent.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["multiline_removal_indent.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } multiline_removal_indent.unicode.term.svg000064400000000000000000000024431046102023000320150ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color ╭╴ 2 - local function f() 3 - print() 4 - end ╰╴ multiline_removal_last_line_tabs.ascii.term.svg000064400000000000000000000027721046102023000331660ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color | 1 - a.foo(|t| { 2 - b 3 - }).bar() 1 + a.bar() | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiline_removal_last_line_tabs.rs000064400000000000000000000013311046102023000310230ustar00use annotate_snippets::{Group, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn test() { let report = &[Group::with_level(Level::ERROR).element( Snippet::source("a.foo(|t| {\n\t\t\tb\n\t\t\t}).bar()\n").patch(Patch::new(1..22, "")), )]; let expected_ascii = file!["multiline_removal_last_line_tabs.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["multiline_removal_last_line_tabs.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } multiline_removal_last_line_tabs.unicode.term.svg000064400000000000000000000030041046102023000335110ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color ╭╴ 1 - a.foo(|t| { 2 - b 3 - }).bar() 1 + a.bar() ╰╴ multiline_removal_suggestion.ascii.term.svg000064400000000000000000000103551046102023000323660ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0277]: `(bool, HashSet<u8>)` is not an iterator --> $DIR/multiline-removal-suggestion.rs:21:8 | 21 | }).flatten() | ^^^^^^^ `(bool, HashSet<u8>)` is not an iterator | = help: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)` = note: required for `(bool, HashSet<u8>)` to implement `IntoIterator` note: required by a bound in `flatten` --> /rustc/FAKE_PREFIX/library/core/src/iter/traits/iterator.rs:1556:4 help: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds | 15 - ts.into_iter() 16 - .map(|t| { 17 - ( 18 - is_true, 19 - t, 20 - ) 21 - }).flatten() 15 + ts.into_iter().flatten() | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiline_removal_suggestion.rs000064400000000000000000000070051046102023000302330ustar00use annotate_snippets::{ AnnotationKind, Level, Origin, Patch, Renderer, Snippet, renderer::DecorStyle, }; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"// Make sure suggestion for removal of a span that covers multiple lines is properly highlighted. //@ compile-flags: --error-format=human --color=always //@ edition:2018 //@ only-linux // ignore-tidy-tab // We use `\t` instead of spaces for indentation to ensure that the highlighting logic properly // accounts for replaced characters (like we do for `\t` with ` `). The naïve way of highlighting // could be counting chars of the original code, instead of operating on the code as it is being // displayed. use std::collections::{HashMap, HashSet}; fn foo() -> Vec<(bool, HashSet)> { let mut hm = HashMap::>>::new(); hm.into_iter() .map(|(is_true, ts)| { ts.into_iter() .map(|t| { ( is_true, t, ) }).flatten() }) .flatten() .collect() } fn bar() -> Vec<(bool, HashSet)> { let mut hm = HashMap::>>::new(); hm.into_iter() .map(|(is_true, ts)| { ts.into_iter() .map(|t| (is_true, t)) .flatten() }) .flatten() .collect() } fn baz() -> Vec<(bool, HashSet)> { let mut hm = HashMap::>>::new(); hm.into_iter() .map(|(is_true, ts)| { ts.into_iter().map(|t| { (is_true, t) }).flatten() }) .flatten() .collect() } fn bay() -> Vec<(bool, HashSet)> { let mut hm = HashMap::>>::new(); hm.into_iter() .map(|(is_true, ts)| { ts.into_iter() .map(|t| (is_true, t)).flatten() }) .flatten() .collect() } fn main() {} "#; let input = &[ Level::ERROR .primary_title("`(bool, HashSet)` is not an iterator") .id("E0277") .element( Snippet::source(source) .path("$DIR/multiline-removal-suggestion.rs") .annotation( AnnotationKind::Primary .span(769..776) .label("`(bool, HashSet)` is not an iterator"), ), ) .element( Level::HELP .message("the trait `Iterator` is not implemented for `(bool, HashSet)`"), ) .element( Level::NOTE.message("required for `(bool, HashSet)` to implement `IntoIterator`"), ), Level::NOTE.secondary_title("required by a bound in `flatten`") .element( Origin::path("/rustc/FAKE_PREFIX/library/core/src/iter/traits/iterator.rs") .line(1556) .char_column(4), ), Level::HELP.secondary_title("consider removing this method call, as the receiver has type `std::vec::IntoIter>` and `std::vec::IntoIter>: Iterator` trivially holds").element( Snippet::source(source) .path("$DIR/multiline-removal-suggestion.rs") .patch(Patch::new(708..768, "")), ), ]; let expected_ascii = file!["multiline_removal_suggestion.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["multiline_removal_suggestion.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } multiline_removal_suggestion.unicode.term.svg000064400000000000000000000104231046102023000327200ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0277]: `(bool, HashSet<u8>)` is not an iterator ╭▸ $DIR/multiline-removal-suggestion.rs:21:8 │ 21 │ }).flatten() │ ━━━━━━━ `(bool, HashSet<u8>)` is not an iterator │ ├ help: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)` ╰ note: required for `(bool, HashSet<u8>)` to implement `IntoIterator` note: required by a bound in `flatten` ─▸ /rustc/FAKE_PREFIX/library/core/src/iter/traits/iterator.rs:1556:4 help: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds ╭╴ 15 - ts.into_iter() 16 - .map(|t| { 17 - ( 18 - is_true, 19 - t, 20 - ) 21 - }).flatten() 15 + ts.into_iter().flatten() ╰╴ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiple_annotations.ascii.term.svg000064400000000000000000000066111046102023000307170ustar00 error: | 96 | fn add_title_line(result: &mut Vec<String>, main_annotation: Option<&Annotation>) { 97 | if let Some(annotation) = main_annotation { | ^^^^^^^^^^ Variable defined here 98 | result.push(format_title_line( 99 | &annotation.annotation_type, | ^^^^^^^^^^ Referenced here 100 | None, 101 | &annotation.label, | ^^^^^^^^^^ Referenced again here 102 | )); 103 | } 104 | } | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiple_annotations.rs000064400000000000000000000027311046102023000265060ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"fn add_title_line(result: &mut Vec, main_annotation: Option<&Annotation>) { if let Some(annotation) = main_annotation { result.push(format_title_line( &annotation.annotation_type, None, &annotation.label, )); } } "#; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .line_start(96) .fold(false) .annotation( AnnotationKind::Primary .span(100..110) .label("Variable defined here"), ) .annotation( AnnotationKind::Primary .span(184..194) .label("Referenced here"), ) .annotation( AnnotationKind::Primary .span(243..253) .label("Referenced again here"), ), )]; let expected_ascii = file!["multiple_annotations.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["multiple_annotations.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiple_annotations.unicode.term.svg000064400000000000000000000067501046102023000312610ustar00 error: ╭▸ 96 │ fn add_title_line(result: &mut Vec<String>, main_annotation: Option<&Annotation>) { 97 │ if let Some(annotation) = main_annotation { │ ━━━━━━━━━━ Variable defined here 98 │ result.push(format_title_line( 99 │ &annotation.annotation_type, │ ━━━━━━━━━━ Referenced here 100 │ None, 101 │ &annotation.label, │ ━━━━━━━━━━ Referenced again here 102 │ )); 103 │ } 104 │ } ╰╴ multiple_highlight_duplicated.ascii.term.svg000064400000000000000000000107331046102023000324500ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0061]: this function takes 6 arguments but 7 arguments were supplied --> $DIR/wrong-highlight-span-extra-arguments-147070.rs:17:15 | 17 | let foo = Thingy::new( | ^^^^^^^^^^^ ... 24 | String::from(""), | ---------------- unexpected argument #7 of type `String` | note: associated function defined here --> $DIR/wrong-highlight-span-extra-arguments-147070.rs:4:19 | 4 | pub(crate) fn new( | ^^^ help: remove the extra argument | 23 - String::from(""), | 18 - String::from(""), | 18 - String::from(""), | 23 - String::from(""), | 23 - String::from(""), | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiple_highlight_duplicated.rs000064400000000000000000000054331046102023000303200ustar00use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#"struct Thingy; impl Thingy { pub(crate) fn new( _a: String, _b: String, _c: String, _d: String, _e: String, _f: String, ) -> Self { unimplemented!() } } fn main() { let foo = Thingy::new( String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), String::from(""), ); }"#; let path = "$DIR/wrong-highlight-span-extra-arguments-147070.rs"; let report = &[ Level::ERROR .primary_title("this function takes 6 arguments but 7 arguments were supplied") .id("E0061") .element( Snippet::source(source) .path(path) .annotation( AnnotationKind::Context .span(426..442) .label("unexpected argument #7 of type `String`"), ) .annotation(AnnotationKind::Primary.span(249..260)), ), Level::NOTE .secondary_title("associated function defined here") .element( Snippet::source(source) .path(path) .annotation(AnnotationKind::Primary.span(48..51)), ), Level::HELP .secondary_title("remove the extra argument") .element( Snippet::source(source) .path(path) .patch(Patch::new(416..442, "")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(263..289, "")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(286..312, "")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(400..417, "")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(416..442, "")), ), ]; let expected_ascii = file!["multiple_highlight_duplicated.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["multiple_highlight_duplicated.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } multiple_highlight_duplicated.unicode.term.svg000064400000000000000000000111401046102023000327770ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0061]: this function takes 6 arguments but 7 arguments were supplied ╭▸ $DIR/wrong-highlight-span-extra-arguments-147070.rs:17:15 │ 17 │ let foo = Thingy::new( │ ━━━━━━━━━━━ ┆ 24 │ String::from(""), │ ──────────────── unexpected argument #7 of type `String` ╰╴ note: associated function defined here ╭▸ $DIR/wrong-highlight-span-extra-arguments-147070.rs:4:19 │ 4 │ pub(crate) fn new( ╰╴ ━━━ help: remove the extra argument ╭╴ 23 - String::from(""), ├╴ 18 - String::from(""), ├╴ 18 - String::from(""), ├╴ 23 - String::from(""), ├╴ 23 - String::from(""), ╰╴ multiple_multiline_removal.ascii.term.svg000064400000000000000000000203611046102023000320300ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0423]: cannot initialize a tuple struct which contains private fields --> $DIR/suggest-box-new.rs:8:19 | 8 | wtf: Some(Box(U { | ^^^ | note: constructor is not visible here due to private fields --> $SRC_DIR/alloc/src/boxed.rs:234:2 | = note: private field | = note: private field help: you might have meant to use an associated function to build this type | 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new(_)), | 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_uninit()), | 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_zeroed()), | 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_in(_, _)), | = and 12 other candidates help: consider using the `Default` trait | 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(<Box as std::default::Default>::default()), | ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/multiple_multiline_removal.rs000064400000000000000000000061711046102023000277020ustar00use annotate_snippets::{ AnnotationKind, Level, Origin, Padding, Patch, Renderer, Snippet, renderer::DecorStyle, }; use snapbox::{assert_data_eq, file}; #[test] fn case() { // https://github.com/rust-lang/rust/blob/4b94758d2ba7d0ef71ccf5fde29ce4bc5d6fe2a4/tests/ui/suggestions/multi-suggestion.rs let source = r#"#![allow(dead_code)] struct U { wtf: Option>>, x: T, } fn main() { U { wtf: Some(Box(U { wtf: None, x: (), })), x: () }; let _ = std::collections::HashMap(); let _ = std::collections::HashMap {}; let _ = Box {}; } "#; let path = "$DIR/suggest-box-new.rs"; let secondary_path = "$SRC_DIR/alloc/src/boxed.rs"; let report = &[ Level::ERROR .primary_title("cannot initialize a tuple struct which contains private fields") .id("E0423") .element( Snippet::source(source) .path(path) .annotation(AnnotationKind::Primary.span(114..117)), ), Level::NOTE .secondary_title("constructor is not visible here due to private fields") .element(Origin::path(secondary_path).line(234).char_column(2)) .element(Padding) .element(Level::NOTE.message("private field")) .element(Padding) .element(Level::NOTE.message("private field")), Level::HELP .secondary_title( "you might have meant to use an associated function to build this type", ) .element( Snippet::source(source) .path(path) .patch(Patch::new(117..174, "::new(_)")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(117..174, "::new_uninit()")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(117..174, "::new_zeroed()")), ) .element( Snippet::source(source) .path(path) .patch(Patch::new(117..174, "::new_in(_, _)")), ) .element(Level::NOTE.no_name().message("and 12 other candidates")), Level::HELP .secondary_title("consider using the `Default` trait") .element( Snippet::source(source) .path(path) .patch(Patch::new(114..114, "<")) .patch(Patch::new( 117..174, " as std::default::Default>::default()", )), ), ]; let expected_ascii = file!["multiple_multiline_removal.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["multiple_multiline_removal.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } multiple_multiline_removal.unicode.term.svg000064400000000000000000000204561046102023000323730ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0423]: cannot initialize a tuple struct which contains private fields ╭▸ $DIR/suggest-box-new.rs:8:19 │ 8 │ wtf: Some(Box(U { │ ━━━ ╰╴ note: constructor is not visible here due to private fields ╭▸ $SRC_DIR/alloc/src/boxed.rs:234:2 │ ├ note: private field │ ╰ note: private field help: you might have meant to use an associated function to build this type ╭╴ 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new(_)), ├╴ 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_uninit()), ├╴ 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_zeroed()), ├╴ 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(Box::new_in(_, _)), │ ╰ and 12 other candidates help: consider using the `Default` trait ╭╴ 8 - wtf: Some(Box(U { 9 - wtf: None, 10 - x: (), 11 - })), 8 + wtf: Some(<Box as std::default::Default>::default()), ╰╴ primary_title_second_group.ascii.term.svg000064400000000000000000000035411046102023000320220ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types --> src/multislice.rs:13:22 | 13 | slices: vec!["A", | ^^^ expected struct `annotate_snippets::snippet::Slice`, found reference | note: expected type: `snippet::Annotation` found type: `__&__snippet::Annotation` ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/primary_title_second_group.rs000064400000000000000000000023051046102023000276660ustar00use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let report = &[ Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(" slices: vec![\"A\",") .line_start(13) .path("src/multislice.rs") .annotation(AnnotationKind::Primary.span(21..24).label( "expected struct `annotate_snippets::snippet::Slice`, found reference", )), ), Group::with_title(Level::NOTE.primary_title( "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", )), ]; let expected_ascii = file!["primary_title_second_group.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = file!["primary_title_second_group.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } primary_title_second_group.unicode.term.svg000064400000000000000000000035631046102023000323640ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types ╭▸ src/multislice.rs:13:22 │ 13 │ slices: vec!["A", │ ━━━ expected struct `annotate_snippets::snippet::Slice`, found reference ╰╴ note: expected type: `snippet::Annotation` found type: `__&__snippet::Annotation` regression_leading_tab_label_alignment.ascii.term.svg000064400000000000000000000025161046102023000342560ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: call-non-callable --> $DIR/main.py:5:9 | 5 | return (1 == '2')() # Tab indented | ^^^^^^^^^^^^ regression_leading_tab_label_alignment.rs000064400000000000000000000016721046102023000320500ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/coloruse annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = "def f():\n\treturn (1 == '2')() # Tab indented\n"; let input = &[Level::ERROR .primary_title("call-non-callable") .id("E0308") .element( Snippet::source(source) .path("$DIR/main.py") .line_start(4) .annotation(AnnotationKind::Primary.span(17..29)), )]; let expected_ascii = file!["regression_leading_tab_label_alignment.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["regression_leading_tab_label_alignment.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } regression_leading_tab_label_alignment.unicode.term.svg000064400000000000000000000025571046102023000346210ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: call-non-callable ╭▸ $DIR/main.py:5:9 │ 5 │ return (1 == '2')() # Tab indented ╰╴ ━━━━━━━━━━━━ regression_leading_tab_long_line.ascii.term.svg000064400000000000000000000027411046102023000331070ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types --> $DIR/non-whitespace-trimming.rs:4:6 | 4 | s_data['d_dails'] = bb['contacted'][hostip]['ansible_facts']['ansible_devices']['vda']['vendor... | ^^^^^^ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/regression_leading_tab_long_line.rs000064400000000000000000000020631046102023000307530ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = " s_data['d_dails'] = bb['contacted'][hostip]['ansible_facts']['ansible_devices']['vda']['vendor'] + \" \" + bb['contacted'][hostip]['an"; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/non-whitespace-trimming.rs") .line_start(4) .annotation(AnnotationKind::Primary.span(5..11)), )]; let expected_ascii = file!["regression_leading_tab_long_line.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["regression_leading_tab_long_line.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } regression_leading_tab_long_line.unicode.term.svg000064400000000000000000000027701046102023000334470ustar00ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color error[E0308]: mismatched types ╭▸ $DIR/non-whitespace-trimming.rs:4:6 │ 4 │ s_data['d_dails'] = bb['contacted'][hostip]['ansible_facts']['ansible_devices']['vda']['vendor']… ╰╴ ━━━━━━ ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/simple.ascii.term.svg000064400000000000000000000040241046102023000257340ustar00 error: expected one of `.`, `;`, `?`, or an operator, found `for` --> src/format_color.rs:171:9 | 169 | }) | - expected one of `.`, `;`, `?`, or an operator here 170 | 171 | for line in &self.body { | ^^^ unexpected token ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/simple.rs000064400000000000000000000023301046102023000235220ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" }) for line in &self.body { "#; let input = &[Level::ERROR .primary_title("expected one of `.`, `;`, `?`, or an operator, found `for`") .element( Snippet::source(source) .path("src/format_color.rs") .line_start(169) .annotation( AnnotationKind::Primary .span(20..23) .label("unexpected token"), ) .annotation( AnnotationKind::Context .span(10..11) .label("expected one of `.`, `;`, `?`, or an operator here"), ), )]; let expected_ascii = file!["simple.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["simple.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/simple.unicode.term.svg000064400000000000000000000040531046102023000262740ustar00 error: expected one of `.`, `;`, `?`, or an operator, found `for` ╭▸ src/format_color.rs:171:9 │ 169 │ }) │ ─ expected one of `.`, `;`, `?`, or an operator here 170 │ 171 │ for line in &self.body { ╰╴ ━━━ unexpected token ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line.ascii.term.svg000064400000000000000000000027671046102023000266270ustar00 error[E0308]: mismatched types --> $DIR/whitespace-trimming.rs:4:193 | 4 | ... let _: () = 42; | ^^ expected (), found integer ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line.rs000064400000000000000000000022341046102023000244040ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" let _: () = 42;"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/whitespace-trimming.rs") .line_start(4) .annotation( AnnotationKind::Primary .span(192..194) .label("expected (), found integer"), ), )]; let expected_ascii = file!["strip_line.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["strip_line.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line.unicode.term.svg000064400000000000000000000030061046102023000271500ustar00 error[E0308]: mismatched types ╭▸ $DIR/whitespace-trimming.rs:4:193 │ 4 │ … let _: () = 42; ╰╴ ━━ expected (), found integer ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_char.ascii.term.svg000064400000000000000000000027701046102023000276160ustar00 error[E0308]: mismatched types --> $DIR/whitespace-trimming.rs:4:193 | 4 | ... let _: () = 42ñ | ^^ expected (), found integer ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_char.rs000064400000000000000000000022471046102023000254050ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" let _: () = 42ñ"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/whitespace-trimming.rs") .line_start(4) .annotation( AnnotationKind::Primary .span(192..194) .label("expected (), found integer"), ), )]; let expected_ascii = file!["strip_line_char.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["strip_line_char.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_char.unicode.term.svg000064400000000000000000000030071046102023000301460ustar00 error[E0308]: mismatched types ╭▸ $DIR/whitespace-trimming.rs:4:193 │ 4 │ … let _: () = 42ñ ╰╴ ━━ expected (), found integer ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_non_ws.ascii.term.svg000064400000000000000000000042211046102023000301750ustar00 error[E0308]: mismatched types --> $DIR/non-whitespace-trimming.rs:4:233 | 4 | ...) = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () ... | ^^ ^^ expected `()`, found integer | | | expected due to this ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_non_ws.rs000064400000000000000000000030311046102023000257630ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use snapbox::{assert_data_eq, file}; #[test] fn case() { let source = r#" let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/non-whitespace-trimming.rs") .line_start(4) .annotation( AnnotationKind::Primary .span(237..239) .label("expected `()`, found integer"), ) .annotation( AnnotationKind::Primary .span(232..234) .label("expected due to this"), ), )]; let expected_ascii = file!["strip_line_non_ws.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["strip_line_non_ws.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/strip_line_non_ws.unicode.term.svg000064400000000000000000000042541046102023000305410ustar00 error[E0308]: mismatched types ╭▸ $DIR/non-whitespace-trimming.rs:4:233 │ 4 │ … () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = … │ ┯━ ━━ expected `()`, found integer │ │ ╰╴ expected due to this ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/styled_title.ascii.term.svg000064400000000000000000000071521046102023000271550ustar00 error[E0277]: the trait bound `CustomErrorHandler: ErrorHandler` is not satisfied --> src/main.rs:5:17 | 5 | cnb_runtime(CustomErrorHandler {}); | ----------- ^^^^^^^^^^^^^^^^^^^^^ the trait `ErrorHandler` is not implemented for `CustomErrorHandler` | | | required by a bound introduced by this call | help: there are multiple different versions of crate `c` in the dependency graph --> src/main.rs:1:5 | 1 | use b::CustomErrorHandler; | ^ one version of crate `c` is used here, as a dependency of crate `b` 2 | use c::cnb_runtime; | ^ one version of crate `c` is used here, as a direct dependency of the current crate ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/styled_title.rs000064400000000000000000000040661046102023000247460ustar00use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle}; use anstyle::{AnsiColor, Effects, Style}; use snapbox::{assert_data_eq, file}; const MAGENTA: Style = AnsiColor::Magenta.on_default().effects(Effects::BOLD); const BOLD: Style = Style::new().effects(Effects::BOLD); #[test] fn case() { let source = r#"use b::CustomErrorHandler; use c::cnb_runtime; cnb_runtime(CustomErrorHandler {}); "#; let title_1 = "the trait bound `CustomErrorHandler: ErrorHandler` is not satisfied"; let title_2 = format!( "{BOLD}there are {BOLD:#}{MAGENTA}multiple different versions{MAGENTA:#}{BOLD} of crate `{BOLD:#}{MAGENTA}c{MAGENTA:#}{BOLD}` in the dependency graph{BOLD:#}" ); let label_1 = "the trait `ErrorHandler` is not implemented for `CustomErrorHandler`"; let label_2 = "required by a bound introduced by this call"; let label_3 = "one version of crate `c` is used here, as a dependency of crate `b`"; let label_4 = "one version of crate `c` is used here, as a direct dependency of the current crate"; let input = &[ Level::ERROR.primary_title(title_1).id("E0277").element( Snippet::source(source) .path("src/main.rs") .annotation(AnnotationKind::Primary.span(65..86).label(label_1)) .annotation(AnnotationKind::Context.span(53..64).label(label_2)), ), Level::HELP.secondary_title(title_2).element( Snippet::source(source) .path("src/main.rs") .annotation(AnnotationKind::Primary.span(4..5).label(label_3)) .annotation(AnnotationKind::Primary.span(31..32).label(label_4)), ), ]; let expected_ascii = file!["styled_title.ascii.term.svg": TermSvg]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = file!["styled_title.unicode.term.svg": TermSvg]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/color/styled_title.unicode.term.svg000064400000000000000000000073151046102023000275140ustar00 error[E0277]: the trait bound `CustomErrorHandler: ErrorHandler` is not satisfied ╭▸ src/main.rs:5:17 │ 5 │ cnb_runtime(CustomErrorHandler {}); │ ┬────────── ━━━━━━━━━━━━━━━━━━━━━ the trait `ErrorHandler` is not implemented for `CustomErrorHandler` │ │ │ required by a bound introduced by this call ╰╴ help: there are multiple different versions of crate `c` in the dependency graph ╭▸ src/main.rs:1:5 │ 1 │ use b::CustomErrorHandler; │ ━ one version of crate `c` is used here, as a dependency of crate `b` 2 │ use c::cnb_runtime; ╰╴ ━ one version of crate `c` is used here, as a direct dependency of the current crate ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/examples.rs000064400000000000000000000071401046102023000227350ustar00use std::collections::BTreeSet; #[test] fn custom_error() { let target = "custom_error"; let expected = snapbox::file!["../examples/custom_error.svg": TermSvg]; assert_example(target, expected); } #[test] fn custom_level() { let target = "custom_level"; let expected = snapbox::file!["../examples/custom_level.svg": TermSvg]; assert_example(target, expected); } #[test] fn elide_header() { let target = "elide_header"; let expected = snapbox::file!["../examples/elide_header.svg": TermSvg]; assert_example(target, expected); } #[test] fn expected_type() { let target = "expected_type"; let expected = snapbox::file!["../examples/expected_type.svg": TermSvg]; assert_example(target, expected); } #[test] fn footer() { let target = "footer"; let expected = snapbox::file!["../examples/footer.svg": TermSvg]; assert_example(target, expected); } #[test] fn format() { let target = "format"; let expected = snapbox::file!["../examples/format.svg": TermSvg]; assert_example(target, expected); } #[test] fn highlight_source() { let target = "highlight_source"; let expected = snapbox::file!["../examples/highlight_source.svg": TermSvg]; assert_example(target, expected); } #[test] fn highlight_message() { let target = "highlight_message"; let expected = snapbox::file!["../examples/highlight_message.svg": TermSvg]; assert_example(target, expected); } #[test] fn id_hyperlink() { let target = "id_hyperlink"; let expected = snapbox::file!["../examples/id_hyperlink.svg": TermSvg]; assert_example(target, expected); } #[test] fn multislice() { let target = "multislice"; let expected = snapbox::file!["../examples/multislice.svg": TermSvg]; assert_example(target, expected); } #[test] fn multi_suggestion() { let target = "multi_suggestion"; let expected = snapbox::file!["../examples/multi_suggestion.svg": TermSvg]; assert_example(target, expected); } #[test] fn struct_name_as_context() { let target = "struct_name_as_context"; let expected = snapbox::file!["../examples/struct_name_as_context.svg": TermSvg]; assert_example(target, expected); } #[track_caller] fn assert_example(target: &str, expected: snapbox::Data) { let bin_path = snapbox::cmd::compile_example(target, ["--features=testing-colors"]).unwrap(); snapbox::cmd::Command::new(bin_path) .env("CLICOLOR_FORCE", "1") .env_remove("NO_COLOR") .assert() .success() .stdout_eq(expected.raw()); } #[test] fn ensure_all_examples_have_tests() { let path = snapbox::utils::current_rs!(); let actual = std::fs::read_to_string(&path).unwrap(); let actual = actual .lines() .filter_map(|l| { if l.starts_with("fn ") && !l.starts_with("fn all_examples_have_tests") && !l.starts_with("fn assert_example") { Some(l[3..l.len() - 4].to_string()) } else { None } }) .collect::>(); let expected = std::fs::read_dir("examples") .unwrap() .map(|res| res.map(|e| e.path().file_stem().unwrap().display().to_string())) .collect::, std::io::Error>>() .unwrap(); let mut diff = expected.difference(&actual).collect::>(); diff.sort(); let mut need_added = String::new(); for name in &diff { need_added.push_str(&format!("{name}\n")); } assert!( diff.is_empty(), "\n`Please add a test for the following examples to `tests/examples.rs`:\n{need_added}", ); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/formatter.rs000064400000000000000000005464351046102023000231410ustar00use annotate_snippets::{ Annotation, AnnotationKind, Group, Level, Origin, Padding, Patch, Renderer, Snippet, }; use annotate_snippets::renderer::DecorStyle; use snapbox::{assert_data_eq, str}; #[test] fn test_i_29() { let input = &[Level::ERROR.primary_title("oops").element( Snippet::source("First line\r\nSecond oops line") .path("") .annotation(AnnotationKind::Primary.span(19..23).label("oops")), )]; let expected_ascii = str![[r#" error: oops --> :2:8 | 2 | Second oops line | ^^^^ oops "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ :2:8 │ 2 │ Second oops line ╰╴ ━━━━ oops "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_point_to_double_width_characters() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("こんにちは、世界") .path("") .annotation(AnnotationKind::Primary.span(18..24).label("world")), )]; let expected_ascii = str![[r#" error: --> :1:7 | 1 | こんにちは、世界 | ^^^^ world "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:7 │ 1 │ こんにちは、世界 ╰╴ ━━━━ world "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_point_to_double_width_characters_across_lines() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("おはよう\nございます") .path("") .annotation(AnnotationKind::Primary.span(6..22).label("Good morning")), )]; let expected_ascii = str![[r#" error: --> :1:3 | 1 | おはよう | _____^ 2 | | ございます | |______^ Good morning "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:3 │ 1 │ おはよう │ ┏━━━━━┛ 2 │ ┃ ございます ╰╴┗━━━━━━┛ Good morning "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_point_to_double_width_characters_multiple() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("お寿司\n食べたい🍣") .path("") .annotation(AnnotationKind::Primary.span(0..9).label("Sushi1")) .annotation(AnnotationKind::Context.span(16..22).label("Sushi2")), )]; let expected_ascii = str![[r#" error: --> :1:1 | 1 | お寿司 | ^^^^^^ Sushi1 2 | 食べたい🍣 | ---- Sushi2 "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:1 │ 1 │ お寿司 │ ━━━━━━ Sushi1 2 │ 食べたい🍣 ╰╴ ──── Sushi2 "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_point_to_double_width_characters_mixed() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("こんにちは、新しいWorld!") .path("") .annotation(AnnotationKind::Primary.span(18..32).label("New world")), )]; let expected_ascii = str![[r#" error: --> :1:7 | 1 | こんにちは、新しいWorld! | ^^^^^^^^^^^ New world "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:7 │ 1 │ こんにちは、新しいWorld! ╰╴ ━━━━━━━━━━━ New world "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_title() { let input = &[Group::with_title( Level::ERROR.primary_title("This is a title").id("E0001"), )]; let expected_ascii = str![r#"error[E0001]: This is a title"#]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str!["error[E0001]: This is a title"]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } /// Tests that we can format a message *without* a header. /// /// This uses `Level::None`, which is somewhat of a hacky API addition I made /// to our vendored copy of `annotate-snippets` in order to do exactly what /// this test asserts: skip the header. #[test] fn test_format_skip_title() { let source = "# Docstring followed by a newline\n\ndef foobar(foot, bar={}):\n \"\"\"\n \"\"\"\n"; let src_annotation = AnnotationKind::Primary.span(56..58).label("B006"); let snippet = Snippet::source(source) .line_start(1) .annotation(src_annotation) .fold(false); let message = Group::with_level(Level::ERROR).element(snippet); let expected = str![[r#" | 1 | # Docstring followed by a newline 2 | 3 | def foobar(foot, bar={}): | ^^ B006 4 | """ 5 | """ | "#]]; assert_data_eq!(Renderer::plain().render(&[message]).clone(), expected); } #[test] fn test_format_no_severity() { let input = &[Group::with_title( Level::ERROR .no_name() .primary_title("This is a title") .id("E0001"), )]; let expected_ascii = str!["E0001 This is a title"]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str!["E0001 This is a title"]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_no_id() { let input = &[Group::with_title( Level::ERROR.primary_title("This is a title"), )]; let expected_ascii = str!["error: This is a title"]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str!["error: This is a title"]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_no_severity_or_id() { let input = &[Group::with_title( Level::ERROR.no_name().primary_title("This is a title"), )]; let expected_ascii = str!["This is a title"]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str!["This is a title"]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_snippet_only() { let source = "This is line 1\nThis is line 2"; let input = &[Level::ERROR.primary_title("").element( Snippet::>::source(source) .line_start(5402) .fold(false), )]; let expected_ascii = str![[r#" error: | 5402 | This is line 1 5403 | This is line 2 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 5402 │ This is line 1 5403 │ This is line 2 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_snippets_continuation() { let src_0 = "This is slice 1"; let src_1 = "This is slice 2"; let input = &[Level::ERROR .primary_title("") .element( Snippet::>::source(src_0) .line_start(5402) .path("file1.rs") .fold(false), ) .element( Snippet::>::source(src_1) .line_start(2) .path("file2.rs") .fold(false), )]; let expected_ascii = str![[r#" error: --> file1.rs | 5402 | This is slice 1 | ::: file2.rs:2 | 2 | This is slice 2 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file1.rs │ 5402 │ This is slice 1 │ ⸬ file2.rs:2 │ 2 │ This is slice 2 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_snippet_annotation_standalone() { let line_1 = "This is line 1"; let line_2 = "This is line 2"; let source = [line_1, line_2].join("\n"); // In line 2 let range = 22..24; let input = &[Level::ERROR.primary_title("").element( Snippet::source(&source) .line_start(5402) .fold(false) .annotation( AnnotationKind::Context .span(range.clone()) .label("Test annotation"), ), )]; let expected_ascii = str![[r#" error: | 5402 | This is line 1 5403 | This is line 2 | -- Test annotation "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 5402 │ This is line 1 5403 │ This is line 2 ╰╴ ── Test annotation "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_format_footer_title() { let input = &[Level::ERROR .primary_title("") .element(Level::ERROR.message("This __is__ a title"))]; let expected_ascii = str![[r#" error: | = error: This __is__ a title "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: │ ╰ error: This __is__ a title "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_multi_group_no_snippet() { let input = &[ Group::with_title(Level::ERROR.primary_title("the core problem")), Group::with_title(Level::NOTE.secondary_title("more information")), Group::with_title(Level::HELP.secondary_title("a way to fix this")), ]; let expected_ascii = str![[r#" error: the core problem | note: more information help: a way to fix this "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: the core problem ╰╴ note: more information help: a way to fix this "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_multi_secondary_group_no_snippet() { let input = &[ Group::with_title(Level::ERROR.secondary_title("the core problem")), Group::with_title(Level::NOTE.secondary_title("more information")), Group::with_title(Level::HELP.secondary_title("a way to fix this")), ]; let expected_ascii = str![[r#" error: the core problem note: more information help: a way to fix this "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: the core problem note: more information help: a way to fix this "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] #[should_panic] fn test_i26() { let source = "short"; let label = "label"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source).line_start(0).annotation( AnnotationKind::Primary .span(0..source.len() + 2) .label(label), ), )]; let renderer = Renderer::plain(); let _ = renderer.render(input); } #[test] fn test_source_content() { let source = "This is an example\nof content lines"; let input = &[Level::ERROR.primary_title("").element( Snippet::>::source(source) .line_start(56) .fold(false), )]; let expected_ascii = str![[r#" error: | 56 | This is an example 57 | of content lines | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 56 │ This is an example 57 │ of content lines ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_source_annotation_standalone_singleline() { let source = "tests"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Context.span(0..5).label("Example string")), )]; let expected_ascii = str![[r#" error: | 1 | tests | ----- Example string "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 1 │ tests ╰╴───── Example string "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_source_annotation_standalone_multiline() { let source = "tests"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Context.span(0..5).label("Example string")) .annotation(AnnotationKind::Context.span(0..5).label("Second line")), )]; let expected_ascii = str![[r#" error: | 1 | tests | ----- | | | Example string | Second line "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 1 │ tests │ ┬──── │ │ │ Example string ╰╴Second line "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_only_source() { let input = &[Level::ERROR.primary_title("").element( Snippet::>::source("") .path("file.rs") .fold(false), )]; let expected_ascii = str![[r#" error: --> file.rs | 1 | | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file.rs │ 1 │ ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn test_anon_lines() { let source = "This is an example\nof content lines\n\nabc"; let input = &[Level::ERROR.primary_title("").element( Snippet::>::source(source) .line_start(56) .fold(false), )]; let expected_ascii = str![[r#" error: | 56 | This is an example 57 | of content lines 58 | 59 | abc | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 56 │ This is an example 57 │ of content lines 58 │ 59 │ abc ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn issue_130() { let input = &[Level::ERROR.primary_title("dummy").element( Snippet::source("foo\nbar\nbaz") .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(4..11)), // bar\nbaz )]; let expected_ascii = str![[r#" error: dummy --> file/path:4:1 | 4 | / bar 5 | | baz | |___^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: dummy ╭▸ file/path:4:1 │ 4 │ ┏ bar 5 │ ┃ baz ╰╴┗━━━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unterminated_string_multiline() { let source = "\ a\" // ... "; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(0..10)), // 1..10 works )]; let expected_ascii = str![[r#" error: --> file/path:3:1 | 3 | / a" 4 | | // ... | |_______^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:1 │ 3 │ ┏ a" 4 │ ┃ // ... ╰╴┗━━━━━━━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn char_and_nl_annotate_char() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .fold(false) .annotation(AnnotationKind::Primary.span(0..2)), // a\r )]; let expected_ascii = str![[r#" error: --> file/path:3:1 | 3 | a | ^ 4 | b | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:1 │ 3 │ a │ ━ 4 │ b ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn char_eol_annotate_char() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(0..3)), // a\r\n )]; let expected_ascii = str![[r#" error: --> file/path:3:1 | 3 | a | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:1 │ 3 │ a ╰╴━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn char_eol_annotate_char_double_width() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("こん\r\nにちは\r\n世界") .path("") .fold(false) .annotation(AnnotationKind::Primary.span(3..8)), // ん\r\n )]; let expected_ascii = str![[r#" error: --> :1:2 | 1 | こん | ^^ 2 | にちは 3 | 世界 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:2 │ 1 │ こん │ ━━ 2 │ にちは 3 │ 世界 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_newline_empty_span() { let input = &[Level::ERROR.primary_title("bad").element( Snippet::source("\n\n\n\n\n\n\n") .path("test.txt") .annotation(AnnotationKind::Primary.span(0..0)), )]; let expected_ascii = str![[r#" error: bad --> test.txt:1:1 | 1 | | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: bad ╭▸ test.txt:1:1 │ 1 │ ╰╴━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_eol() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .fold(false) .annotation(AnnotationKind::Primary.span(1..2)), // \r )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | ^ 4 | b | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a │ ━ 4 │ b ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_eol2() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(1..3)), // \r\n )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a ╰╴ ━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_eol3() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(2..3)), // \n )]; let expected_ascii = str![[r#" error: --> file/path:3:3 | 3 | a | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:3 │ 3 │ a ╰╴ ━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_eol4() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .fold(false) .annotation(AnnotationKind::Primary.span(2..2)), // \n )]; let expected_ascii = str![[r#" error: --> file/path:3:3 | 3 | a | ^ 4 | b | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:3 │ 3 │ a │ ━ 4 │ b ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn annotate_eol_double_width() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("こん\r\nにちは\r\n世界") .path("") .fold(false) .annotation(AnnotationKind::Primary.span(7..8)), // \n )]; let expected_ascii = str![[r#" error: --> :1:4 | 1 | こん | ^ 2 | にちは 3 | 世界 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:4 │ 1 │ こん │ ━ 2 │ にちは 3 │ 世界 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(1..4)), // \r\nb )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | __^ 4 | | b | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start2() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(2..4)), // \nb )]; let expected_ascii = str![[r#" error: --> file/path:3:3 | 3 | a | __^ 4 | | b | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:3 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start3() { let source = "a\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(1..3)), // \nb )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | __^ 4 | | b | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_double_width() { let input = &[Level::ERROR.primary_title("").element( Snippet::source("こん\r\nにちは\r\n世界") .path("") .fold(false) .annotation(AnnotationKind::Primary.span(7..11)), // \r\nに )]; let expected_ascii = str![[r#" error: --> :1:4 | 1 | こん | _____^ 2 | | にちは | |__^ 3 | 世界 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ :1:4 │ 1 │ こん │ ┏━━━━━┛ 2 │ ┃ にちは │ ┗━━┛ 3 │ 世界 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_eol_end() { let source = "a\nb\nc"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(1..4)), // \nb\n )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | __^ 4 | | b | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_eol_end2() { let source = "a\r\nb\r\nc"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .fold(false) .annotation(AnnotationKind::Primary.span(2..5)), // \nb\r )]; let expected_ascii = str![[r#" error: --> file/path:3:3 | 3 | a | __^ 4 | | b | |__^ 5 | c | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:3 │ 3 │ a │ ┏━━┛ 4 │ ┃ b │ ┗━━┛ 5 │ c ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_eol_end3() { let source = "a\r\nb\r\nc"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(2..6)), // \nb\r\n )]; let expected_ascii = str![[r#" error: --> file/path:3:3 | 3 | a | __^ 4 | | b | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:3 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_eof_end() { let source = "a\r\nb"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(1..5)), // \r\nb(EOF) )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | a | __^ 4 | | b | |__^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ a │ ┏━━┛ 4 │ ┃ b ╰╴┗━━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_eol_start_eof_end_double_width() { let source = "ん\r\nに"; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source) .path("file/path") .line_start(3) .annotation(AnnotationKind::Primary.span(3..9)), // \r\nに(EOF) )]; let expected_ascii = str![[r#" error: --> file/path:3:2 | 3 | ん | ___^ 4 | | に | |___^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ file/path:3:2 │ 3 │ ん │ ┏━━━┛ 4 │ ┃ に ╰╴┗━━━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn two_single_line_same_line() { let source = r#"bar = { version = "0.1.0", optional = true }"#; let input = &[Level::ERROR .primary_title("unused optional dependency") .element( Snippet::source(source) .path("Cargo.toml") .line_start(4) .annotation( AnnotationKind::Primary .span(0..3) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Context .span(27..42) .label("This should also be long but not too long"), ), )]; let expected_ascii = str![[r#" error: unused optional dependency --> Cargo.toml:4:1 | 4 | bar = { version = "0.1.0", optional = true } | ^^^ --------------- This should also be long but not too long | | | I need this to be really long so I can test overlaps "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unused optional dependency ╭▸ Cargo.toml:4:1 │ 4 │ bar = { version = "0.1.0", optional = true } │ ┯━━ ─────────────── This should also be long but not too long │ │ ╰╴I need this to be really long so I can test overlaps "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multi_and_single() { let source = r#"bar = { version = "0.1.0", optional = true } this is another line so is this bar = { version = "0.1.0", optional = true } "#; let input = &[Level::ERROR .primary_title("unused optional dependency") .element( Snippet::source(source) .line_start(4) .annotation( AnnotationKind::Primary .span(41..119) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Context .span(27..42) .label("This should also be long but not too long"), ), )]; let expected_ascii = str![[r#" error: unused optional dependency | 4 | bar = { version = "0.1.0", optional = true } | ____________________________--------------^ | | | | | This should also be long but not too long 5 | | this is another line 6 | | so is this 7 | | bar = { version = "0.1.0", optional = true } | |__________________________________________^ I need this to be really long so I can test overlaps "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unused optional dependency ╭▸ 4 │ bar = { version = "0.1.0", optional = true } │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┬─────────────┛ │ ┃ │ │ ┃ This should also be long but not too long 5 │ ┃ this is another line 6 │ ┃ so is this 7 │ ┃ bar = { version = "0.1.0", optional = true } ╰╴┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ I need this to be really long so I can test overlaps "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn two_multi_and_single() { let source = r#"bar = { version = "0.1.0", optional = true } this is another line so is this bar = { version = "0.1.0", optional = true } "#; let input = &[Level::ERROR .primary_title("unused optional dependency") .element( Snippet::source(source) .line_start(4) .annotation( AnnotationKind::Primary .span(41..119) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Primary .span(8..102) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Context .span(27..42) .label("This should also be long but not too long"), ), )]; let expected_ascii = str![[r#" error: unused optional dependency | 4 | bar = { version = "0.1.0", optional = true } | __________^__________________--------------^ | | | | | | _________| This should also be long but not too long | || 5 | || this is another line 6 | || so is this 7 | || bar = { version = "0.1.0", optional = true } | ||_________________________^________________^ I need this to be really long so I can test overlaps | |_________________________| | I need this to be really long so I can test overlaps "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unused optional dependency ╭▸ 4 │ bar = { version = "0.1.0", optional = true } │ ┏━━━━━━━━━━╿━━━━━━━━━━━━━━━━━━┬─────────────┛ │ ┃ │ │ │ ┃┏━━━━━━━━━┙ This should also be long but not too long │ ┃┃ 5 │ ┃┃ this is another line 6 │ ┃┃ so is this 7 │ ┃┃ bar = { version = "0.1.0", optional = true } │ ┗┃━━━━━━━━━━━━━━━━━━━━━━━━━╿━━━━━━━━━━━━━━━━┛ I need this to be really long so I can test overlaps │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┥ ╰╴ I need this to be really long so I can test overlaps "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn three_multi_and_single() { let source = r#"bar = { version = "0.1.0", optional = true } this is another line so is this bar = { version = "0.1.0", optional = true } this is another line "#; let input = &[Level::ERROR .primary_title("unused optional dependency") .element( Snippet::source(source) .line_start(4) .annotation( AnnotationKind::Primary .span(41..119) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Primary .span(8..102) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Primary .span(48..126) .label("I need this to be really long so I can test overlaps"), ) .annotation( AnnotationKind::Context .span(27..42) .label("This should also be long but not too long"), ), )]; let expected_ascii = str![[r#" error: unused optional dependency | 4 | bar = { version = "0.1.0", optional = true } | ___________^__________________--------------^ | | | | | | __________| This should also be long but not too long | || 5 | || this is another line | || ____^ 6 | ||| so is this 7 | ||| bar = { version = "0.1.0", optional = true } | |||_________________________^________________^ I need this to be really long so I can test overlaps | ||_________________________| | | I need this to be really long so I can test overlaps 8 | | this is another line | |____^ I need this to be really long so I can test overlaps "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unused optional dependency ╭▸ 4 │ bar = { version = "0.1.0", optional = true } │ ┏━━━━━━━━━━━╿━━━━━━━━━━━━━━━━━━┬─────────────┛ │ ┃ │ │ │ ┃┏━━━━━━━━━━┙ This should also be long but not too long │ ┃┃ 5 │ ┃┃ this is another line │ ┃┃┏━━━━┛ 6 │ ┃┃┃ so is this 7 │ ┃┃┃ bar = { version = "0.1.0", optional = true } │ ┗┃┃━━━━━━━━━━━━━━━━━━━━━━━━━╿━━━━━━━━━━━━━━━━┛ I need this to be really long so I can test overlaps │ ┗┃━━━━━━━━━━━━━━━━━━━━━━━━━┥ │ ┃ I need this to be really long so I can test overlaps 8 │ ┃ this is another line ╰╴ ┗━━━━┛ I need this to be really long so I can test overlaps "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn origin_correct_start_line() { let source = "aaa\nbbb\nccc\nddd\n"; let input = &[Level::ERROR.primary_title("title").element( Snippet::source(source) .path("origin.txt") .fold(false) .annotation(AnnotationKind::Primary.span(8..8 + 3).label("annotation")), )]; let expected_ascii = str![[r#" error: title --> origin.txt:3:1 | 1 | aaa 2 | bbb 3 | ccc | ^^^ annotation 4 | ddd | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: title ╭▸ origin.txt:3:1 │ 1 │ aaa 2 │ bbb 3 │ ccc │ ━━━ annotation 4 │ ddd ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn origin_correct_mid_line() { let source = "aaa\nbbb\nccc\nddd\n"; let input = &[Level::ERROR.primary_title("title").element( Snippet::source(source) .path("origin.txt") .fold(false) .annotation( AnnotationKind::Primary .span(8 + 1..8 + 3) .label("annotation"), ), )]; let expected_ascii = str![[r#" error: title --> origin.txt:3:2 | 1 | aaa 2 | bbb 3 | ccc | ^^ annotation 4 | ddd | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: title ╭▸ origin.txt:3:2 │ 1 │ aaa 2 │ bbb 3 │ ccc │ ━━ annotation 4 │ ddd ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn two_suggestions_same_span() { let source = r#" A.foo();"#; let input = &[ Level::ERROR .primary_title("expected value, found enum `A`") .id("E0423") .element(Snippet::source(source).annotation(AnnotationKind::Primary.span(4..5))), Level::HELP .secondary_title("you might have meant to use one of the following enum variants") .element(Snippet::source(source).patch(Patch::new(4..5, "(A::Tuple())"))) .element(Snippet::source(source).patch(Patch::new(4..5, "A::Unit"))), ]; let expected_ascii = str![[r#" error[E0423]: expected value, found enum `A` | 1 | A.foo(); | ^ | help: you might have meant to use one of the following enum variants | 1 - A.foo(); 1 + (A::Tuple()).foo(); | 1 | A::Unit.foo(); | ++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0423]: expected value, found enum `A` ╭▸ 1 │ A.foo(); │ ━ ╰╴ help: you might have meant to use one of the following enum variants ╭╴ 1 - A.foo(); 1 + (A::Tuple()).foo(); ├╴ 1 │ A::Unit.foo(); ╰╴ ++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn two_suggestions_same_span2() { let source = r#" mod banana { pub struct Chaenomeles; pub trait Apple { fn pick(&self) {} } impl Apple for Chaenomeles {} pub trait Peach { fn pick(&self, a: &mut ()) {} } impl Peach for Box {} impl Peach for Chaenomeles {} } fn main() { banana::Chaenomeles.pick() }"#; let input = &[Level::ERROR .primary_title("no method named `pick` found for struct `Chaenomeles` in the current scope") .id("E0599").element( Snippet::source(source) .line_start(1) .annotation( AnnotationKind::Context .span(18..40) .label("method `pick` not found for this struct"), ) .annotation( AnnotationKind::Primary .span(318..322) .label("method not found in `Chaenomeles`"), ), ), Level::HELP.secondary_title( "the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them", ) .element( Snippet::source(source) .patch(Patch::new(1..1, "use banana::Apple;\n")), ) .element( Snippet::source(source) .patch(Patch::new(1..1, "use banana::Peach;\n")), )]; let expected_ascii = str![[r#" error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope | 3 | pub struct Chaenomeles; | ---------------------- method `pick` not found for this struct ... 18 | banana::Chaenomeles.pick() | ^^^^ method not found in `Chaenomeles` | help: the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them | 2 + use banana::Apple; | 2 + use banana::Peach; | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope ╭▸ 3 │ pub struct Chaenomeles; │ ────────────────────── method `pick` not found for this struct ┆ 18 │ banana::Chaenomeles.pick() │ ━━━━ method not found in `Chaenomeles` ╰╴ help: the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them ╭╴ 2 + use banana::Apple; ├╴ 2 + use banana::Peach; ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn single_line_non_overlapping_suggestions() { let source = r#" A.foo();"#; let input = &[ Level::ERROR .primary_title("expected value, found enum `A`") .id("E0423") .element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Primary.span(4..5)), ), Level::HELP .secondary_title("make these changes and things will work") .element( Snippet::source(source) .patch(Patch::new(4..5, "(A::Tuple())")) .patch(Patch::new(6..9, "bar")), ), ]; let expected_ascii = str![[r#" error[E0423]: expected value, found enum `A` | 1 | A.foo(); | ^ | help: make these changes and things will work | 1 - A.foo(); 1 + (A::Tuple()).bar(); | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0423]: expected value, found enum `A` ╭▸ 1 │ A.foo(); │ ━ ╰╴ help: make these changes and things will work ╭╴ 1 - A.foo(); 1 + (A::Tuple()).bar(); ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn single_line_non_overlapping_suggestions2() { let source = r#" ThisIsVeryLong.foo();"#; let input = &[ Level::ERROR .primary_title("Found `ThisIsVeryLong`") .id("E0423") .element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Primary.span(4..18)), ), Level::HELP .secondary_title("make these changes and things will work") .element( Snippet::source(source) .patch(Patch::new(4..18, "(A::Tuple())")) .patch(Patch::new(19..22, "bar")), ), ]; let expected_ascii = str![[r#" error[E0423]: Found `ThisIsVeryLong` | 1 | ThisIsVeryLong.foo(); | ^^^^^^^^^^^^^^ | help: make these changes and things will work | 1 - ThisIsVeryLong.foo(); 1 + (A::Tuple()).bar(); | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0423]: Found `ThisIsVeryLong` ╭▸ 1 │ ThisIsVeryLong.foo(); │ ━━━━━━━━━━━━━━ ╰╴ help: make these changes and things will work ╭╴ 1 - ThisIsVeryLong.foo(); 1 + (A::Tuple()).bar(); ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_replacements() { let source = r#" let y = || { self.bar(); }; self.qux(); y(); "#; let input = &[ Level::ERROR .primary_title( "cannot borrow `*self` as mutable because it is also borrowed as immutable", ) .id("E0502") .element( Snippet::source(source) .line_start(1) .annotation( AnnotationKind::Primary .span(49..59) .label("mutable borrow occurs here"), ) .annotation( AnnotationKind::Primary .span(13..15) .label("immutable borrow occurs here"), ) .annotation( AnnotationKind::Primary .span(26..30) .label("first borrow occurs due to use of `*self` in closure"), ) .annotation( AnnotationKind::Primary .span(65..66) .label("immutable borrow later used here"), ), ), Level::HELP .secondary_title("try explicitly pass `&Self` into the Closure as an argument") .element( Snippet::source(source) .patch(Patch::new(14..14, "this: &Self")) .patch(Patch::new(26..30, "this")) .patch(Patch::new(66..68, "(self)")), ), ]; let expected_ascii = str![[r#" error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable | 2 | let y = || { | ^^ immutable borrow occurs here 3 | self.bar(); | ^^^^ first borrow occurs due to use of `*self` in closure 4 | }; 5 | self.qux(); | ^^^^^^^^^^ mutable borrow occurs here 6 | y(); | ^ immutable borrow later used here | help: try explicitly pass `&Self` into the Closure as an argument | 2 ~ let y = |this: &Self| { 3 ~ this.bar(); 4 | }; 5 | self.qux(); 6 ~ y(self); | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable ╭▸ 2 │ let y = || { │ ━━ immutable borrow occurs here 3 │ self.bar(); │ ━━━━ first borrow occurs due to use of `*self` in closure 4 │ }; 5 │ self.qux(); │ ━━━━━━━━━━ mutable borrow occurs here 6 │ y(); │ ━ immutable borrow later used here ╰╴ help: try explicitly pass `&Self` into the Closure as an argument ╭╴ 2 ± let y = |this: &Self| { 3 ± this.bar(); 4 │ }; 5 │ self.qux(); 6 ± y(self); ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_replacements2() { let source = r#" fn test1() { let mut chars = "Hello".chars(); for _c in chars.by_ref() { chars.next(); } } fn main() { test1(); }"#; let input = &[ Level::ERROR .primary_title("cannot borrow `chars` as mutable more than once at a time") .id("E0499") .element( Snippet::source(source) .line_start(1) .annotation( AnnotationKind::Context .span(65..70) .label("first mutable borrow occurs here"), ) .annotation( AnnotationKind::Primary .span(90..95) .label("second mutable borrow occurs here"), ) .annotation( AnnotationKind::Context .span(65..79) .label("first borrow later used here"), ), ), Level::HELP.secondary_title( "if you want to call `next` on a iterator within the loop, consider using `while let`", ) .element( Snippet::source(source) .patch(Patch::new( 55..59, "let iter = chars.by_ref();\n while let Some(", )) .patch(Patch::new(61..79, ") = iter.next()")) .patch(Patch::new(90..95, "iter")), ), ]; let expected_ascii = str![[r#" error[E0499]: cannot borrow `chars` as mutable more than once at a time | 4 | for _c in chars.by_ref() { | -------------- | | | first mutable borrow occurs here | first borrow later used here 5 | chars.next(); | ^^^^^ second mutable borrow occurs here | help: if you want to call `next` on a iterator within the loop, consider using `while let` | 4 ~ let iter = chars.by_ref(); 5 ~ while let Some(_c) = iter.next() { 6 ~ iter.next(); | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0499]: cannot borrow `chars` as mutable more than once at a time ╭▸ 4 │ for _c in chars.by_ref() { │ ┬───────────── │ │ │ first mutable borrow occurs here │ first borrow later used here 5 │ chars.next(); │ ━━━━━ second mutable borrow occurs here ╰╴ help: if you want to call `next` on a iterator within the loop, consider using `while let` ╭╴ 4 ± let iter = chars.by_ref(); 5 ± while let Some(_c) = iter.next() { 6 ± iter.next(); ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn diff_format() { let source = r#" use st::cell::Cell; mod bar { pub fn bar() { bar::baz(); } fn baz() {} } use bas::bar; struct Foo { bar: st::cell::Cell } fn main() {}"#; let input = &[ Level::ERROR .primary_title("failed to resolve: use of undeclared crate or module `st`") .id("E0433") .element( Snippet::source(source).line_start(1).annotation( AnnotationKind::Primary .span(122..124) .label("use of undeclared crate or module `st`"), ), ), Level::HELP .secondary_title("there is a crate or module with a similar name") .element(Snippet::source(source).patch(Patch::new(122..124, "std"))), Level::HELP .secondary_title("consider importing this module") .element(Snippet::source(source).patch(Patch::new(1..1, "use std::cell;\n"))), Level::HELP .secondary_title("if you import `cell`, refer to it directly") .element(Snippet::source(source).patch(Patch::new(122..126, ""))), ]; let expected_ascii = str![[r#" error[E0433]: failed to resolve: use of undeclared crate or module `st` | 13 | bar: st::cell::Cell | ^^ use of undeclared crate or module `st` | help: there is a crate or module with a similar name | 13 | bar: std::cell::Cell | + help: consider importing this module | 2 + use std::cell; | help: if you import `cell`, refer to it directly | 13 - bar: st::cell::Cell 13 + bar: cell::Cell | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0433]: failed to resolve: use of undeclared crate or module `st` ╭▸ 13 │ bar: st::cell::Cell │ ━━ use of undeclared crate or module `st` ╰╴ help: there is a crate or module with a similar name ╭╴ 13 │ bar: std::cell::Cell ╰╴ + help: consider importing this module ╭╴ 2 + use std::cell; ╰╴ help: if you import `cell`, refer to it directly ╭╴ 13 - bar: st::cell::Cell 13 + bar: cell::Cell ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_removal() { let source = r#" struct Wrapper(T); fn foo(foo: Wrapper) where T : ? Sized { // } fn main() {}"#; let input = &[ Level::ERROR .primary_title("the size for values of type `T` cannot be known at compilation time") .id("E0277") .element( Snippet::source(source) .line_start(1) .annotation( AnnotationKind::Primary .span(39..49) .label("doesn't have a size known at compile-time"), ) .annotation( AnnotationKind::Context .span(31..32) .label("this type parameter needs to be `Sized`"), ), ), Level::HELP .secondary_title( "consider removing the `?Sized` bound to make the type parameter `Sized`", ) .element(Snippet::source(source).patch(Patch::new(52..85, ""))), ]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | 4 | fn foo(foo: Wrapper) | - ^^^^^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `Sized` | help: consider removing the `?Sized` bound to make the type parameter `Sized` | 6 - where 7 - T 8 - : 9 - ? 10 - Sized | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╭▸ 4 │ fn foo(foo: Wrapper) │ ┬ ━━━━━━━━━━ doesn't have a size known at compile-time │ │ │ this type parameter needs to be `Sized` ╰╴ help: consider removing the `?Sized` bound to make the type parameter `Sized` ╭╴ 6 - where 7 - T 8 - : 9 - ? 10 - Sized ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_replacement() { let source = r#" struct Wrapper(T); fn foo(foo: Wrapper) and where T : ? Sized { // } fn main() {}"#; let input = &[ Level::ERROR .primary_title("the size for values of type `T` cannot be known at compilation time") .id("E0277").element(Snippet::source(source) .line_start(1) .path("$DIR/removal-of-multiline-trait-bound-in-where-clause.rs") .annotation( AnnotationKind::Primary .span(39..49) .label("doesn't have a size known at compile-time"), ) .annotation( AnnotationKind::Context .span(31..32) .label("this type parameter needs to be `Sized`"), ) ), Level::NOTE .secondary_title("required by an implicit `Sized` bound in `Wrapper`") .element( Snippet::source(source) .line_start(1) .path("$DIR/removal-of-multiline-trait-bound-in-where-clause.rs") .annotation( AnnotationKind::Primary .span(16..17) .label("required by the implicit `Sized` requirement on this type parameter in `Wrapper`"), ) ), Level::HELP .secondary_title("you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box`") .element( Snippet::source(source) .line_start(1) .path("$DIR/removal-of-multiline-trait-bound-in-where-clause.rs") .annotation( AnnotationKind::Primary .span(16..17) .label("this could be changed to `T: ?Sized`..."), ) .annotation( AnnotationKind::Context .span(19..20) .label("...if indirection were used here: `Box`"), ) ), Level::HELP .secondary_title("consider removing the `?Sized` bound to make the type parameter `Sized`") .element( Snippet::source(source) .patch(Patch::new(56..89, "")) .patch(Patch::new(89..89, "+ Send")) , ) ]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:4:16 | 4 | fn foo(foo: Wrapper) | - ^^^^^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `Sized` | note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:2:16 | 2 | struct Wrapper(T); | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:2:16 | 2 | struct Wrapper(T); | ^ - ...if indirection were used here: `Box` | | | this could be changed to `T: ?Sized`... help: consider removing the `?Sized` bound to make the type parameter `Sized` | 6 - and where 7 - T 8 - : 9 - ? 10 - Sized 6 + and + Send | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╭▸ $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:4:16 │ 4 │ fn foo(foo: Wrapper) │ ┬ ━━━━━━━━━━ doesn't have a size known at compile-time │ │ │ this type parameter needs to be `Sized` ╰╴ note: required by an implicit `Sized` bound in `Wrapper` ╭▸ $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:2:16 │ 2 │ struct Wrapper(T); ╰╴ ━ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` ╭▸ $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:2:16 │ 2 │ struct Wrapper(T); │ ┯ ─ ...if indirection were used here: `Box` │ │ ╰╴ this could be changed to `T: ?Sized`... help: consider removing the `?Sized` bound to make the type parameter `Sized` ╭╴ 6 - and where 7 - T 8 - : 9 - ? 10 - Sized 6 + and + Send ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiline_removal2() { let source = r#" cargo fuzzy pizza jumps crazy quack zappy "#; let input = &[ Group::with_title( Level::ERROR .primary_title( "the size for values of type `T` cannot be known at compilation time", ) .id("E0277"), ), // We need an empty group here to ensure the HELP line is rendered correctly Level::HELP .secondary_title( "consider removing the `?Sized` bound to make the type parameter `Sized`", ) .element( Snippet::source(source) .line_start(7) .patch(Patch::new(3..21, "")) .patch(Patch::new(22..40, "")), ), ]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | help: consider removing the `?Sized` bound to make the type parameter `Sized` | 8 - cargo 9 - fuzzy 10 - pizza 11 - jumps 12 - crazy 13 - quack 14 - zappy 8 + campy | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╰╴ help: consider removing the `?Sized` bound to make the type parameter `Sized` ╭╴ 8 - cargo 9 - fuzzy 10 - pizza 11 - jumps 12 - crazy 13 - quack 14 - zappy 8 + campy ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn e0271() { let source = r#" trait Future { type Error; } impl Future for Result { type Error = E; } impl Future for Option { type Error = (); } struct Foo; fn foo() -> Box> { Box::new( Ok::<_, ()>( Err::<(), _>( Ok::<_, ()>( Err::<(), _>( Ok::<_, ()>( Err::<(), _>(Some(5)) ) ) ) ) ) ) } fn main() { } "#; let input = &[ Level::ERROR .primary_title("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .element(Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .annotation( AnnotationKind::Primary .span(208..510) .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), ) ), Level::NOTE.secondary_title("expected this to be `Foo`") .element( Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .annotation(AnnotationKind::Primary.span(89..90)) ) .element( Level::NOTE .message("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") ) ]; let expected_ascii = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` --> $DIR/E0271.rs:20:5 | 20 | / Box::new( 21 | | Ok::<_, ()>( 22 | | Err::<(), _>( 23 | | Ok::<_, ()>( ... | 32 | | ) | |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` | note: expected this to be `Foo` --> $DIR/E0271.rs:10:18 | 10 | type Error = E; | ^ = note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` "#]]; let renderer = Renderer::plain().term_width(40); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` ╭▸ $DIR/E0271.rs:20:5 │ 20 │ ┏ Box::new( 21 │ ┃ Ok::<_, ()>( 22 │ ┃ Err::<(), _>( 23 │ ┃ Ok::<_, ()>( ┆ ┇ 32 │ ┃ ) │ ┗━━━━━┛ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` ╰╴ note: expected this to be `Foo` ╭▸ $DIR/E0271.rs:10:18 │ 10 │ type Error = E; │ ━ ╰ note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn e0271_2() { let source = r#" trait Future { type Error; } impl Future for Result { type Error = E; } impl Future for Option { type Error = (); } struct Foo; fn foo() -> Box> { Box::new( Ok::<_, ()>( Err::<(), _>( Ok::<_, ()>( Err::<(), _>( Ok::<_, ()>( Err::<(), _>(Some(5)) ) ) ) ) ) ) } fn main() { } "#; let input = &[ Level::ERROR .primary_title("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .element(Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .annotation( AnnotationKind::Primary .span(208..510) .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), ) ), Level::NOTE.secondary_title("expected this to be `Foo`") .element( Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .annotation(AnnotationKind::Primary.span(89..90)) ).element( Level::NOTE .message("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") ).element( Level::NOTE.message("a second note"), ) ]; let expected_ascii = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` --> $DIR/E0271.rs:20:5 | 20 | / Box::new( 21 | | Ok::<_, ()>( 22 | | Err::<(), _>( 23 | | Ok::<_, ()>( ... | 32 | | ) | |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` | note: expected this to be `Foo` --> $DIR/E0271.rs:10:18 | 10 | type Error = E; | ^ = note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` = note: a second note "#]]; let renderer = Renderer::plain().term_width(40); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` ╭▸ $DIR/E0271.rs:20:5 │ 20 │ ┏ Box::new( 21 │ ┃ Ok::<_, ()>( 22 │ ┃ Err::<(), _>( 23 │ ┃ Ok::<_, ()>( ┆ ┇ 32 │ ┃ ) │ ┗━━━━━┛ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` ╰╴ note: expected this to be `Foo` ╭▸ $DIR/E0271.rs:10:18 │ 10 │ type Error = E; │ ━ ├ note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` ╰ note: a second note "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_e0308() { let source = r#" mod a { // Force the "short path for unique types" machinery to trip up pub struct Atype; pub struct Btype; pub struct Ctype; } mod b { pub struct Atype(T, K); pub struct Btype(T, K); pub struct Ctype(T, K); } use b::*; fn main() { let x: Atype< Btype< Ctype< Atype< Btype< Ctype< Atype< Btype< Ctype, i32 >, i32 >, i32 >, i32 >, i32 >, i32 >, i32 >, i32 > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok("") )))))))))))))))))))))))))))))) )))))))))))))))))))))))))))))]; //~^^^^^ ERROR E0308 let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( Some(Some(Some(Some(Some(Some(Some(Some(Some(""))))))))) ))))))))))))))))) )))))))))))))))))) ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) )))))))))))))))))))))))))))))) )))))))))))))))))))))))]; //~^^^^^ ERROR E0308 let x: Atype< Btype< Ctype< Atype< Btype< Ctype< Atype< Btype< Ctype, i32 >, i32 >, i32 >, i32 >, i32 >, i32 >, i32 >, i32 > = (); //~^ ERROR E0308 let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) )))))))))))))))))))))))))))))) )))))))))))))))))))))))]; //~^^^^^ ERROR E0308 } "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .line_start(7) .path("$DIR/long-E0308.rs") .annotation( AnnotationKind::Primary .span(719..1001) .label("expected `Atype, i32>, i32>`, found `Result, _>, _>`"), ) .annotation( AnnotationKind::Context .span(293..716) .label("expected due to this"), ) ).element( Level::NOTE .message("expected struct `Atype, i32>`\n found enum `Result, _>`") ).element( Level::NOTE .message("the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'") ).element( Level::NOTE .message("consider using `--verbose` to print the full type name to the console") , )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/long-E0308.rs:48:9 | 24 | let x: Atype< | _____________- 25 | | Btype< 26 | | Ctype< 27 | | Atype< ... | 47 | | i32 48 | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... | | _____-___^ | ||_____| | | expected due to this 49 | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... 50 | | Ok("") 51 | | )))))))))))))))))))))))))))))) 52 | | )))))))))))))))))))))))))))))]; | |__________________________________^ expected `Atype, i32>, i32>`, found `Result, _>, _>` | = note: expected struct `Atype, i32>` found enum `Result, _>` = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console "#]]; let renderer = Renderer::plain().term_width(60); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/long-E0308.rs:48:9 │ 24 │ let x: Atype< │ ┌─────────────┘ 25 │ │ Btype< 26 │ │ Ctype< 27 │ │ Atype< ┆ ┆ 47 │ │ i32 48 │ │ > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… │ │┏━━━━━│━━━┛ │ └┃─────┤ │ ┃ expected due to this 49 │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… 50 │ ┃ Ok("") 51 │ ┃ )))))))))))))))))))))))))))))) 52 │ ┃ )))))))))))))))))))))))))))))]; │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, i32>, i32>`, found `Result, _>, _>` │ ├ note: expected struct `Atype, i32>` │ found enum `Result, _>` ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn highlighting() { let source = r#" use core::pin::Pin; use core::future::Future; use core::any::Any; fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static )>>) {} fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin, String>> + Send + 'static )>> { Box::pin(async { Err("nope".into()) }) } fn main() { query(wrapped_fn); } "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .line_start(7) .path("$DIR/unicode-output.rs") .annotation( AnnotationKind::Primary .span(430..440) .label("one type is more general than the other"), ) .annotation( AnnotationKind::Context .span(424..429) .label("arguments to this function are incorrect"), ), ).element( Level::NOTE .message("expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>`\n found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}`") , ), Level::NOTE.secondary_title("function defined here") .element( Snippet::source(source) .line_start(7) .path("$DIR/unicode-output.rs") .annotation(AnnotationKind::Primary.span(77..210)) .annotation(AnnotationKind::Context.span(71..76)), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/unicode-output.rs:23:11 | 23 | query(wrapped_fn); | ----- ^^^^^^^^^^ one type is more general than the other | | | arguments to this function are incorrect | = note: expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>` found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}` note: function defined here --> $DIR/unicode-output.rs:12:10 | 12 | fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static 14 | | )>>) {} | |___^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/unicode-output.rs:23:11 │ 23 │ query(wrapped_fn); │ ┬──── ━━━━━━━━━━ one type is more general than the other │ │ │ arguments to this function are incorrect │ ╰ note: expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>` found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}` note: function defined here ╭▸ $DIR/unicode-output.rs:12:10 │ 12 │ fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static 14 │ ┃ )>>) {} ╰╴┗━━━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } // This tests that an ellipsis is not inserted into Unicode text when a line // wasn't actually trimmed. // // This is a regression test where `...` was inserted because the code wasn't // properly accounting for the *rendered* length versus the length in bytes in // all cases. #[test] fn unicode_cut_handling() { let source = "version = \"0.1.0\"\n# Ensure that the spans from toml handle utf-8 correctly\nauthors = [\n { name = \"Z\u{351}\u{36b}\u{343}\u{36a}\u{302}\u{36b}\u{33d}\u{34f}\u{334}\u{319}\u{324}\u{31e}\u{349}\u{35a}\u{32f}\u{31e}\u{320}\u{34d}A\u{36b}\u{357}\u{334}\u{362}\u{335}\u{31c}\u{330}\u{354}L\u{368}\u{367}\u{369}\u{358}\u{320}G\u{311}\u{357}\u{30e}\u{305}\u{35b}\u{341}\u{334}\u{33b}\u{348}\u{34d}\u{354}\u{339}O\u{342}\u{30c}\u{30c}\u{358}\u{328}\u{335}\u{339}\u{33b}\u{31d}\u{333}\", email = 1 }\n]\n"; let input = &[Level::ERROR.primary_title("title").element( Snippet::source(source) .fold(false) .annotation(AnnotationKind::Primary.span(85..228).label("annotation")), )]; let expected_ascii = str![[r#" error: title | 1 | version = "0.1.0" 2 | # Ensure that the spans from toml handle utf-8 correctly 3 | authors = [ | ___________^ 4 | | { name = "Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯̞̠͍A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘", email = 1 } 5 | | ] | |_^ annotation "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: title ╭▸ 1 │ version = "0.1.0" 2 │ # Ensure that the spans from toml handle utf-8 correctly 3 │ authors = [ │ ┏━━━━━━━━━━━┛ 4 │ ┃ { name = "Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯̞̠͍A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘", email = 1 } 5 │ ┃ ] ╰╴┗━┛ annotation "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_ascii_end_with_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source).annotation( AnnotationKind::Primary .span(499..500) .label("expected item"), ), )]; let expected_ascii = str![[r#" | 1 | ... 的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/? | ^ expected item "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/? ╰╴ ━ expected item "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_ascii_end_no_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = &[Group::with_level(Level::ERROR) .element(Snippet::source(source).annotation(AnnotationKind::Primary.span(499..500)))]; let expected_ascii = str![[r#" | 1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/? | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/? ╰╴ ━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_unicode_end_with_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source).annotation( AnnotationKind::Primary .span(499..502) .label("expected item"), ), )]; let expected_ascii = str![[r#" | 1 | ... 的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好 | ^^ expected item "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好 ╰╴ ━━ expected item "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_unicode_end_no_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好"; let input = &[Group::with_level(Level::ERROR) .element(Snippet::source(source).annotation(AnnotationKind::Primary.span(499..502)))]; let expected_ascii = str![[r#" | 1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好 | ^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好 ╰╴ ━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_unicode_middle_with_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source).annotation( AnnotationKind::Primary .span(251..254) .label("expected item"), ), )]; let expected_ascii = str![[r#" | 1 | ... 这是宽的。这是宽的。这是宽的。... | ^^ expected item "#]]; let renderer = Renderer::plain().term_width(43); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 。这是宽的。这是宽的。这是宽的。这… ╰╴ ━━ expected item "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_unicode_annotate_unicode_middle_no_label() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = &[Group::with_level(Level::ERROR) .element(Snippet::source(source).annotation(AnnotationKind::Primary.span(251..254)))]; let expected_ascii = str![[r#" | 1 | ... 是宽的。这是宽的。这是宽的。这... | ^^ "#]]; let renderer = Renderer::plain().term_width(43); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ … 这是宽的。这是宽的。这是宽的。这是… ╰╴ ━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_ascii_annotate_ascii_end_with_label() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source).annotation( AnnotationKind::Primary .span(334..335) .label("expected item"), ), )]; let expected_ascii = str![[r#" | 1 | ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/? | ^ expected item "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ …aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/? ╰╴ ━ expected item "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trim_ascii_annotate_ascii_end_no_label() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; let input = &[Group::with_level(Level::ERROR) .element(Snippet::source(source).annotation(AnnotationKind::Primary.span(334..335)))]; let expected_ascii = str![[r#" | 1 | ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/? | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 1 │ …aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/? ╰╴ ━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn diagnostic_width() { let source = r##"// ignore-tidy-linelength fn main() { let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; //~^ ERROR mismatched types } "##; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/non-whitespace-trimming-unicode.rs") .annotation( AnnotationKind::Primary .span(1207..1209) .label("expected `()`, found integer"), ) .annotation( AnnotationKind::Context .span(1202..1204) .label("expected due to this"), ), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/non-whitespace-trimming-unicode.rs:4:415 | 4 | ...♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲... | -- ^^ expected `()`, found integer | | | expected due to this "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/non-whitespace-trimming-unicode.rs:4:415 │ 4 │ …♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳… │ ┬─ ━━ expected `()`, found integer │ │ ╰╴ expected due to this "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn diagnostic_width2() { let source = r##"//@ revisions: ascii unicode //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength fn main() { let unicode_is_fun = "؁‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥"; let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; //[ascii]~^ ERROR cannot add `&str` to `&str` } "##; let input = &[ Level::ERROR .primary_title("cannot add `&str` to `&str`") .id("E0369") .element( Snippet::source(source) .path("$DIR/non-1-width-unicode-multiline-label.rs") .annotation(AnnotationKind::Context.span(970..984).label("&str")) .annotation(AnnotationKind::Context.span(987..1001).label("&str")) .annotation( AnnotationKind::Primary .span(985..986) .label("`+` cannot be used to concatenate two `&str` strings"), ), ) .element( Level::NOTE.message("string concatenation requires an owned `String` on the left"), ), Level::HELP .secondary_title("create an owned `String` from a string reference") .element( Snippet::source(source) .path("$DIR/non-1-width-unicode-multiline-label.rs") .patch(Patch::new(984..984, ".to_owned()")), ), ]; let expected_ascii = str![[r#" error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:7:260 | 7 | ...࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str | | | | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference | 7 | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; | +++++++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:260 │ 7 │ …࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; │ ┬───────────── ┯ ────────────── &str │ │ │ │ │ `+` cannot be used to concatenate two `&str` strings │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference ╭╴ 7 │ let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; ╰╴ +++++++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn macros_not_utf8() { let source = r##"//@ error-pattern: did not contain valid UTF-8 //@ reference: input.encoding.utf8 //@ reference: input.encoding.invalid fn foo() { include!("not-utf8.bin"); } "##; let bin_source = "�|�\u{0002}!5�cc\u{0015}\u{0002}�Ӻi��WWj�ȥ�'�}�\u{0012}�J�ȉ��W�\u{001e}O�@����\u{001c}w�V���LO����\u{0014}[ \u{0003}_�'���SQ�~ذ��ų&��-\t��lN~��!@␌ _#���kQ��h�\u{001d}�:�\u{001c}\u{0007}�"; let input = &[Level::ERROR .primary_title("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8").element( Snippet::source(source) .path("$DIR/not-utf8.rs") .annotation(AnnotationKind::Primary.span(136..160)), ), Level::NOTE.secondary_title("byte `193` is not valid utf-8") .element( Snippet::source(bin_source) .path("$DIR/not-utf8.bin") .annotation(AnnotationKind::Primary.span(0..0)), ) .element(Level::NOTE.message("this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)")), ]; let expected_ascii = str![[r#" error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 --> $DIR/not-utf8.rs:6:5 | 6 | include!("not-utf8.bin"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: byte `193` is not valid utf-8 --> $DIR/not-utf8.bin:1:1 | 1 | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�␜␇� | ^ = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 ╭▸ $DIR/not-utf8.rs:6:5 │ 6 │ include!("not-utf8.bin"); │ ━━━━━━━━━━━━━━━━━━━━━━━━ ╰╴ note: byte `193` is not valid utf-8 ╭▸ $DIR/not-utf8.bin:1:1 │ 1 │ �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�␜␇� │ ━ ╰ note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn secondary_title_no_level_text() { let source = r#"fn main() { let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/mismatched-types.rs") .annotation( AnnotationKind::Primary .span(105..131) .label("expected `&str`, found `&[u8; 0]`"), ) .annotation( AnnotationKind::Context .span(98..102) .label("expected due to this"), ), ) .element( Level::NOTE .no_name() .message("expected reference `&str`\nfound reference `&'static [u8; 0]`"), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/mismatched-types.rs:3:19 | 3 | let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]` | | | expected due to this | = expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/mismatched-types.rs:3:19 │ 3 │ let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types │ ┬─── ━━━━━━━━━━━━━━━━━━━━━━━━━━ expected `&str`, found `&[u8; 0]` │ │ │ expected due to this │ ╰ expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn secondary_title_custom_level_text() { let source = r#"fn main() { let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/mismatched-types.rs") .annotation( AnnotationKind::Primary .span(105..131) .label("expected `&str`, found `&[u8; 0]`"), ) .annotation( AnnotationKind::Context .span(98..102) .label("expected due to this"), ), ) .element( Level::NOTE .with_name(Some("custom")) .message("expected reference `&str`\nfound reference `&'static [u8; 0]`"), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/mismatched-types.rs:3:19 | 3 | let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]` | | | expected due to this | = custom: expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/mismatched-types.rs:3:19 │ 3 │ let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types │ ┬─── ━━━━━━━━━━━━━━━━━━━━━━━━━━ expected `&str`, found `&[u8; 0]` │ │ │ expected due to this │ ╰ custom: expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn id_on_title() { let source = r#"// Regression test for issue #114529 // Tests that we do not ICE during const eval for a // break-with-value in contexts where it is illegal #[allow(while_true)] fn main() { [(); { while true { break 9; //~ ERROR `break` with value from a `while` loop }; 51 }]; [(); { while let Some(v) = Some(9) { break v; //~ ERROR `break` with value from a `while` loop }; 51 }]; while true { break (|| { //~ ERROR `break` with value from a `while` loop let local = 9; }); } } "#; let input = &[ Level::ERROR .primary_title("`break` with value from a `while` loop") .id("E0571") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .annotation( AnnotationKind::Primary .span(483..581) .label("can only break with a value inside `loop` or breakable block"), ) .annotation( AnnotationKind::Context .span(462..472) .label("you can't `break` with a value in a `while` loop"), ), ), Level::HELP .with_name(Some("suggestion")) .secondary_title("use `break` on its own without a value inside this `while` loop") .id("S0123") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .patch(Patch::new(483..581, "break")), ), ]; let expected_ascii = str![[r#" error[E0571]: `break` with value from a `while` loop --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 | 21 | while true { | ---------- you can't `break` with a value in a `while` loop 22 | / break (|| { //~ ERROR `break` with value from a `while` loop 23 | | let local = 9; 24 | | }); | |__________^ can only break with a value inside `loop` or breakable block | suggestion[S0123]: use `break` on its own without a value inside this `while` loop | 22 - break (|| { //~ ERROR `break` with value from a `while` loop 23 - let local = 9; 24 - }); 22 + break; | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0571]: `break` with value from a `while` loop ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 │ 21 │ while true { │ ────────── you can't `break` with a value in a `while` loop 22 │ ┏ break (|| { //~ ERROR `break` with value from a `while` loop 23 │ ┃ let local = 9; 24 │ ┃ }); │ ┗━━━━━━━━━━┛ can only break with a value inside `loop` or breakable block ╰╴ suggestion[S0123]: use `break` on its own without a value inside this `while` loop ╭╴ 22 - break (|| { //~ ERROR `break` with value from a `while` loop 23 - let local = 9; 24 - }); 22 + break; ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn max_line_num_no_fold() { let source = r#"cargo fuzzy pizza jumps crazy quack zappy "#; let input = &[Level::ERROR .primary_title("the size for values of type `T` cannot be known at compilation time") .id("E0277") .element( Snippet::source(source) .line_start(8) .fold(false) .annotation(AnnotationKind::Primary.span(6..11)), )]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | 8 | cargo 9 | fuzzy | ^^^^^ 10 | pizza 11 | jumps 12 | crazy 13 | quack 14 | zappy | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╭▸ 8 │ cargo 9 │ fuzzy │ ━━━━━ 10 │ pizza 11 │ jumps 12 │ crazy 13 │ quack 14 │ zappy ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn empty_span_end_line() { let source = "#: E112\nif False:\nprint()\n#: E113\nprint()\n"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source) .line_start(7) .fold(false) .annotation(AnnotationKind::Primary.span(17..17).label("E112")), )]; let expected_ascii = str![[r#" | 7 | #: E112 8 | if False: | ^ E112 9 | print() 10 | #: E113 11 | print() | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 7 │ #: E112 8 │ if False: │ ━ E112 9 │ print() 10 │ #: E113 11 │ print() ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn span_eol() { let source = "#: E112\nif False:\nprint()\n#: E113\nprint()\n"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source) .line_start(7) .fold(false) .annotation(AnnotationKind::Primary.span(17..18).label("E112")), )]; let expected_ascii = str![[r#" | 7 | #: E112 8 | if False: | ^ E112 9 | print() 10 | #: E113 11 | print() | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 7 │ #: E112 8 │ if False: │ ━ E112 9 │ print() 10 │ #: E113 11 │ print() ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn empty_span_start_line() { let source = "#: E112\nif False:\nprint()\n#: E113\nprint()\n"; let input = &[Group::with_level(Level::ERROR).element( Snippet::source(source) .line_start(7) .fold(false) .annotation(AnnotationKind::Primary.span(18..18).label("E112")), )]; let expected_ascii = str![[r#" | 7 | #: E112 8 | if False: 9 | print() | ^ E112 10 | #: E113 11 | print() | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ 7 │ #: E112 8 │ if False: 9 │ print() │ ━ E112 10 │ #: E113 11 │ print() ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggestion_span_line_end() { let source = r#"#![allow(unused)] fn main() { [1, 2, 3].into_iter().for_each(|n| { *n; }); } "#; let long_title1 = "this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021"; let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; let input = &[ Level::WARNING .primary_title(long_title1) .element( Snippet::source(source) .path("lint_example.rs") .annotation(AnnotationKind::Primary.span(40..49)), ) .element(Level::WARNING.message("this changes meaning in Rust 2021")) .element(Level::NOTE.message(long_title2)) .element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")), Level::HELP .secondary_title("use `.iter()` instead of `.into_iter()` to avoid ambiguity") .element( Snippet::source(source) .path("lint_example.rs") .line_start(3) .patch(Patch::new(40..49, "iter")), ), Level::HELP.secondary_title(long_title3).element( Snippet::source(source) .path("lint_example.rs") .line_start(3) .patch(Patch::new(74..74, " // Span after line end")), ), ]; let expected_ascii = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 --> lint_example.rs:3:11 | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see = note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | 5 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 5 + [1, 2, 3].iter().for_each(|n| { *n; }); | help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | 5 | [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end | ++++++++++++++++++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 ╭▸ lint_example.rs:3:11 │ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); │ ━━━━━━━━━ │ ├ warning: this changes meaning in Rust 2021 ├ note: for more information, see ╰ note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity ╭╴ 5 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 5 + [1, 2, 3].iter().for_each(|n| { *n; }); ╰╴ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value ╭╴ 5 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end ╰╴ ++++++++++++++++++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggestion_span_source_end() { let snippet_source = r#"#![allow(unused)] fn main() { [1, 2, 3].into_iter().for_each(|n| { *n; }); } "#; let suggestion_source = r#"[1, 2, 3].into_iter().for_each(|n| { *n; }); "#; let long_title1 = "this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021"; let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; let input = &[ Level::WARNING .primary_title(long_title1) .element( Snippet::source(snippet_source) .path("lint_example.rs") .annotation(AnnotationKind::Primary.span(40..49)), ) .element(Level::WARNING.message("this changes meaning in Rust 2021")) .element(Level::NOTE.message(long_title2)) .element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")), Level::HELP .secondary_title("use `.iter()` instead of `.into_iter()` to avoid ambiguity") .element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new(10..19, "iter")), ), Level::HELP.secondary_title(long_title3).element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new( suggestion_source.len()..suggestion_source.len(), " // Span after line end", )), ), ]; let expected_ascii = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 --> lint_example.rs:3:11 | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see = note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); | help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end | ++++++++++++++++++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 ╭▸ lint_example.rs:3:11 │ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); │ ━━━━━━━━━ │ ├ warning: this changes meaning in Rust 2021 ├ note: for more information, see ╰ note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity ╭╴ 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); ╰╴ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value ╭╴ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end ╰╴ ++++++++++++++++++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggestion_span_one_bigger_than_source() { let snippet_source = r#"#![allow(unused)] fn main() { [1, 2, 3].into_iter().for_each(|n| { *n; }); } "#; let suggestion_source = r#"[1, 2, 3].into_iter().for_each(|n| { *n; }); "#; let long_title1 = "this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021"; let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; let input = &[ Level::WARNING .primary_title(long_title1) .element( Snippet::source(snippet_source) .path("lint_example.rs") .annotation(AnnotationKind::Primary.span(40..49)), ) .element(Level::WARNING.message("this changes meaning in Rust 2021")) .element(Level::NOTE.message(long_title2)) .element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")), Level::HELP .secondary_title("use `.iter()` instead of `.into_iter()` to avoid ambiguity") .element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new(10..19, "iter")), ), Level::HELP.secondary_title(long_title3).element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new( suggestion_source.len() + 1..suggestion_source.len() + 1, " // Span after line end", )), ), ]; let expected_ascii = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 --> lint_example.rs:3:11 | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see = note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); | help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end | ++++++++++++++++++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 ╭▸ lint_example.rs:3:11 │ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); │ ━━━━━━━━━ │ ├ warning: this changes meaning in Rust 2021 ├ note: for more information, see ╰ note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity ╭╴ 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); ╰╴ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value ╭╴ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); // Span after line end ╰╴ ++++++++++++++++++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] #[should_panic = "Patch span `47..47` is beyond the end of buffer `45`"] fn suggestion_span_bigger_than_source() { let snippet_source = r#"#![allow(unused)] fn main() { [1, 2, 3].into_iter().for_each(|n| { *n; }); } "#; let suggestion_source = r#"[1, 2, 3].into_iter().for_each(|n| { *n; }); "#; let long_title1 = "this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021"; let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; let input = &[ Level::WARNING .primary_title(long_title1) .element( Snippet::source(snippet_source) .path("lint_example.rs") .annotation(AnnotationKind::Primary.span(40..49)), ) .element(Level::WARNING.message("this changes meaning in Rust 2021")) .element(Level::NOTE.message(long_title2)) .element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")), Level::HELP .secondary_title("use `.iter()` instead of `.into_iter()` to avoid ambiguity") .element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new(10..19, "iter")), ), Level::HELP.secondary_title(long_title3).element( Snippet::source(suggestion_source) .path("lint_example.rs") .line_start(3) .patch(Patch::new( suggestion_source.len() + 2..suggestion_source.len() + 2, " // Span after line end", )), ), ]; let renderer = Renderer::plain(); renderer.render(input); } #[test] fn snippet_no_path() { // Taken from: https://docs.python.org/3/library/typing.html#annotating-callable-objects let source = "def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ..."; let input = &[Level::ERROR.primary_title("").element( Snippet::source(source).annotation(AnnotationKind::Primary.span(4..12).label("annotation")), )]; let expected_ascii = str![[r#" error: | 1 | def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... | ^^^^^^^^ annotation "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 1 │ def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... ╰╴ ━━━━━━━━ annotation "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_snippet_no_path() { // Taken from: https://docs.python.org/3/library/typing.html#annotating-callable-objects let source = "def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ..."; let input = &[Level::ERROR .primary_title("") .element( Snippet::source(source) .annotation(AnnotationKind::Primary.span(4..12).label("annotation")), ) .element( Snippet::source(source) .annotation(AnnotationKind::Primary.span(4..12).label("annotation")), )]; let expected_ascii = str![[r#" error: | 1 | def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... | ^^^^^^^^ annotation | ::: 1 | def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... | ^^^^^^^^ annotation "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ╭▸ 1 │ def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... │ ━━━━━━━━ annotation │ ⸬ 1 │ def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ... ╰╴ ━━━━━━━━ annotation "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn padding_last_in_group() { let source = r#"// When the type of a method call's receiver is unknown, the span should point // to the receiver (and not the entire call, as was previously the case before // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { let x: Option<_> = None; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { data.iter() .sum::<_>() //~ ERROR type annotations needed .to_string() } fn main() {} "#; let input = &[Level::ERROR .primary_title("type annotations needed") .id("E0282") .element( Snippet::source(source) .path("$DIR/issue-42234-unknown-receiver-type.rs") .annotation(AnnotationKind::Primary.span(449..452).label( "cannot infer type of the type parameter `S` declared on the method `sum`", )), ) .element(Padding)]; let expected_ascii = str![[r#" error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:12:10 | 12 | .sum::<_>() //~ ERROR type annotations needed | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0282]: type annotations needed ╭▸ $DIR/issue-42234-unknown-receiver-type.rs:12:10 │ 12 │ .sum::<_>() //~ ERROR type annotations needed │ ━━━ cannot infer type of the type parameter `S` declared on the method `sum` ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn padding_last_in_group_with_group_after() { let source = r#"// When the type of a method call's receiver is unknown, the span should point // to the receiver (and not the entire call, as was previously the case before // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { let x: Option<_> = None; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { data.iter() .sum::<_>() //~ ERROR type annotations needed .to_string() } fn main() {} "#; let input = &[ Level::ERROR .primary_title("type annotations needed") .id("E0282") .element( Snippet::source(source) .path("$DIR/issue-42234-unknown-receiver-type.rs") .annotation(AnnotationKind::Primary.span(449..452).label( "cannot infer type of the type parameter `S` declared on the method `sum`", )), ) .element(Padding), Level::HELP .secondary_title("consider specifying the generic argument") .element( Snippet::source(source) .path("$DIR/issue-42234-unknown-receiver-type.rs") .line_start(12) .fold(true) .patch(Patch::new(452..457, "::")), ), ]; let expected_ascii = str![[r#" error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:12:10 | 12 | .sum::<_>() //~ ERROR type annotations needed | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | help: consider specifying the generic argument | 23 - .sum::<_>() //~ ERROR type annotations needed 23 + .sum::() //~ ERROR type annotations needed | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0282]: type annotations needed ╭▸ $DIR/issue-42234-unknown-receiver-type.rs:12:10 │ 12 │ .sum::<_>() //~ ERROR type annotations needed │ ━━━ cannot infer type of the type parameter `S` declared on the method `sum` ╰╴ help: consider specifying the generic argument ╭╴ 23 - .sum::<_>() //~ ERROR type annotations needed 23 + .sum::() //~ ERROR type annotations needed ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggestion_same_as_source() { let source = r#"// When the type of a method call's receiver is unknown, the span should point // to the receiver (and not the entire call, as was previously the case before // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { let x: Option<_> = None; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { data.iter() .sum::<_>() //~ ERROR type annotations needed .to_string() } fn main() {} "#; let input = &[ Level::ERROR .primary_title("type annotations needed") .id("E0282") .element( Snippet::source(source) .path("$DIR/issue-42234-unknown-receiver-type.rs") .annotation(AnnotationKind::Primary.span(449..452).label( "cannot infer type of the type parameter `S` declared on the method `sum`", )), ), Level::HELP .secondary_title("consider specifying the generic argument") .element( Snippet::source(source) .path("$DIR/issue-42234-unknown-receiver-type.rs") .line_start(12) .fold(true) .patch(Patch::new(452..457, "::<_>")), ), ]; let expected_ascii = str![[r#" error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:12:10 | 12 | .sum::<_>() //~ ERROR type annotations needed | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | help: consider specifying the generic argument | 23 | .sum::<_>() //~ ERROR type annotations needed | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0282]: type annotations needed ╭▸ $DIR/issue-42234-unknown-receiver-type.rs:12:10 │ 12 │ .sum::<_>() //~ ERROR type annotations needed │ ━━━ cannot infer type of the type parameter `S` declared on the method `sum` ╰╴ help: consider specifying the generic argument ╭╴ 23 │ .sum::<_>() //~ ERROR type annotations needed ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn keep_lines1() { let source = r#" cargo fuzzy pizza jumps crazy quack zappy "#; let input = &[Level::ERROR .primary_title("the size for values of type `T` cannot be known at compilation time") .id("E0277") .element( Snippet::source(source) .line_start(11) .annotation(AnnotationKind::Primary.span(1..6)) .annotation(AnnotationKind::Visible.span(37..41)), )]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | 12 | cargo | ^^^^^ ... 18 | zappy | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╭▸ 12 │ cargo │ ━━━━━ ┆ 18 │ zappy ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn keep_lines2() { let source = r#" cargo fuzzy pizza jumps crazy quack zappy "#; let input = &[Level::ERROR .primary_title("the size for values of type `T` cannot be known at compilation time") .id("E0277") .element( Snippet::source(source) .line_start(11) .annotation(AnnotationKind::Primary.span(1..6)) .annotation(AnnotationKind::Visible.span(16..18)), )]; let expected_ascii = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | 12 | cargo | ^^^^^ 13 | fuzzy 14 | pizza | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time ╭▸ 12 │ cargo │ ━━━━━ 13 │ fuzzy 14 │ pizza ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn message_before_primary_snippet() { let source = r#"struct Thing { a0: Foo, a1: Foo, a2: Foo, a3: Foo, a4: Foo, a5: Foo, a6: Foo, a7: Foo, a8: Foo, a9: Foo, } struct Foo { field: Field, } struct Field; impl Foo { fn bar(&self) {} } fn bar(t: Thing) { t.bar(); t.field; } fn main() {} "#; let input = &[Level::ERROR .primary_title("no field `field` on type `Thing`") .id("E0609") .element(Level::NOTE.message("a `Title` then a `Message`!?!?")) .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .annotation( AnnotationKind::Primary .span(270..275) .label("unknown field"), ), )]; let expected_ascii = str![[r#" error[E0609]: no field `field` on type `Thing` | = note: a `Title` then a `Message`!?!? --> $DIR/too-many-field-suggestions.rs:26:7 | 26 | t.field; | ^^^^^ unknown field "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0609]: no field `field` on type `Thing` │ ├ note: a `Title` then a `Message`!?!? ├▸ $DIR/too-many-field-suggestions.rs:26:7 │ 26 │ t.field; ╰╴ ━━━━━ unknown field "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_line_num_widths() { let source = r#" cargo-features = ["path-bases"] [package] name = "foo" version = "0.5.0" authors = ["wycats@example.com"] [dependencies] bar = { base = '^^not-valid^^', path = 'bar' } "#; let title = "invalid character `^` in path base name: `^^not-valid^^`, the first character must be a Unicode XID start character (most letters or `_`)"; let input = &[Level::ERROR.primary_title(title).element( Snippet::source(source) .path("Cargo.toml") .annotation(AnnotationKind::Primary.span(243..282)) .annotation(AnnotationKind::Visible.span(206..219)), )]; let expected_ascii = str![[r#" error: invalid character `^` in path base name: `^^not-valid^^`, the first character must be a Unicode XID start character (most letters or `_`) --> Cargo.toml:10:24 | 9 | [dependencies] 10 | bar = { base = '^^not-valid^^', path = 'bar' } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: invalid character `^` in path base name: `^^not-valid^^`, the first character must be a Unicode XID start character (most letters or `_`) ╭▸ Cargo.toml:10:24 │ 9 │ [dependencies] 10 │ bar = { base = '^^not-valid^^', path = 'bar' } ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn tab() { let source = " t \tt "; let title = "showing how tabs are rendered"; let input = &[Level::ERROR.primary_title(title).element( Snippet::source(source) .path("tabbed.txt") .annotation(AnnotationKind::Primary.span(2..3)) .annotation(AnnotationKind::Context.span(5..6)), )]; let expected_ascii = str![[r#" error: showing how tabs are rendered --> tabbed.txt:2:2 | 2 | t | ^ 3 | t | - "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: showing how tabs are rendered ╭▸ tabbed.txt:2:2 │ 2 │ t │ ━ 3 │ t ╰╴ ─ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn duplicate_annotations() { let source = r#"foobar foobar 🚀 "#; let report = &[Level::WARNING.primary_title("whatever").element( Snippet::source(source) .path("whatever") .annotation(AnnotationKind::Primary.span(0..source.len()).label("blah")) .annotation(AnnotationKind::Primary.span(0..source.len()).label("blah")), )]; let expected_ascii = str![[r#" warning: whatever --> whatever:1:1 | 1 | / foobar 2 | | 3 | | foobar 🚀 | | ^ | | | | |______________________blah | blah "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(report), expected_ascii); let expected_unicode = str![[r#" warning: whatever ╭▸ whatever:1:1 │ 1 │ ┏ foobar 2 │ ┃ 3 │ ┃ foobar 🚀 │ ┃ ╿ │ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━blah ╰╴ blah "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(report), expected_unicode); } #[test] fn alignment() { let source = "SELECT bar"; let title = "ensure single line at line 0 rendered correctly with group line lined up"; let input = &[Level::ERROR.primary_title(title).element( Snippet::source(source) .path("Cargo.toml") .line_start(0) .annotation( AnnotationKind::Primary .span(7..10) .label("unexpected token"), ) .annotation( AnnotationKind::Visible .span(0..10) .label("while parsing statement"), ), )]; let expected_ascii = str![[r#" error: ensure single line at line 0 rendered correctly with group line lined up --> Cargo.toml:0:8 | 0 | SELECT bar | ^^^ unexpected token "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: ensure single line at line 0 rendered correctly with group line lined up ╭▸ Cargo.toml:0:8 │ 0 │ SELECT bar ╰╴ ━━━ unexpected token "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trimmed_multiline_suggestion() { let source = r#"fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32, f: i32) {} fn main() { let variable_name = 42; function_with_lots_of_arguments( variable_name, variable_name, variable_name, variable_name, variable_name, ); //~^^^^^^^ ERROR this function takes 6 arguments but 5 arguments were supplied [E0061] } "#; let path = "$DIR/trimmed_multiline_suggestion.rs"; let input = &[ Group::with_title( Level::ERROR .primary_title("this function takes 6 arguments but 5 arguments were supplied") .id("E0061"), ) .element( Snippet::source(source) .path(path) .annotation( AnnotationKind::Context .span(196..209) .label("argument #2 of type `char` is missing"), ) .annotation(AnnotationKind::Primary.span(132..163)), ), Group::with_title(Level::NOTE.secondary_title("function defined here")).element( Snippet::source(source) .path(path) .annotation(AnnotationKind::Context.span(43..50).label("")) .annotation(AnnotationKind::Primary.span(3..34)), ), Group::with_title(Level::HELP.secondary_title("provide the argument")).element( Snippet::source(source).path(path).patch(Patch::new( 163..285, "( variable_name, /* char */, variable_name, variable_name, variable_name, variable_name, )", )), ), ]; let expected_ascii = str![[r#" error[E0061]: this function takes 6 arguments but 5 arguments were supplied --> $DIR/trimmed_multiline_suggestion.rs:5:5 | 5 | function_with_lots_of_arguments( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | variable_name, 7 | variable_name, | ------------- argument #2 of type `char` is missing | note: function defined here --> $DIR/trimmed_multiline_suggestion.rs:1:4 | 1 | fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32, f: i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- help: provide the argument | 5 | function_with_lots_of_arguments( 6 | variable_name, 7 ~ /* char */, 8 ~ variable_name, | "#]]; let renderer_ascii = Renderer::plain(); assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0061]: this function takes 6 arguments but 5 arguments were supplied ╭▸ $DIR/trimmed_multiline_suggestion.rs:5:5 │ 5 │ function_with_lots_of_arguments( │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6 │ variable_name, 7 │ variable_name, │ ───────────── argument #2 of type `char` is missing ╰╴ note: function defined here ╭▸ $DIR/trimmed_multiline_suggestion.rs:1:4 │ 1 │ fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32, f: i32) {} ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ─────── help: provide the argument ╭╴ 5 │ function_with_lots_of_arguments( 6 │ variable_name, 7 ± /* char */, 8 ± variable_name, ╰╴ "#]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(input), expected_unicode); } #[test] fn trimmed_multiline_suggestion_elided_lines() { let source_0 = r#" nums.iter().for_each(|x| { if *x > 0 { println!("Positive number"); } else { println!("Negative number"); } }) "#; let source_1 = r#"#![deny(clippy::semicolon_if_nothing_returned)] "#; let input = &[ Group::with_title(Level::ERROR.primary_title( "consider adding a `;` to the last statement for consistent formatting", )) .element( Snippet::source(source_0) .path("tests/ui/semicolon_if_nothing_returned_testing.rs") .line_start(4) .annotation(AnnotationKind::Primary.span(4..166)), ), Group::with_title(Level::NOTE.secondary_title("the lint level is defined here")).element( Snippet::source(source_1) .path("tests/ui/semicolon_if_nothing_returned_testing.rs") .line_start(2) .annotation(AnnotationKind::Primary.span(8..45)), ), Group::with_title(Level::HELP.secondary_title("add a `;` here")).element( Snippet::source(source_0) .path("tests/ui/semicolon_if_nothing_returned_testing.rs") .line_start(4) .fold(true) .patch(Patch::new( 4..166, r#"nums.iter().for_each(|x| { if *x > 0 { println!("Positive number"); } else { println!("Negative number"); } });"#, )), ), ]; let expected_ascii = str![[r#" error: consider adding a `;` to the last statement for consistent formatting --> tests/ui/semicolon_if_nothing_returned_testing.rs:4:5 | 4 | / nums.iter().for_each(|x| { 5 | | if *x > 0 { 6 | | println!("Positive number"); 7 | | } else { ... | 10 | | }) | |______^ | note: the lint level is defined here --> tests/ui/semicolon_if_nothing_returned_testing.rs:2:9 | 2 | #![deny(clippy::semicolon_if_nothing_returned)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here | 4 | nums.iter().for_each(|x| { ... 9 | } 10 ~ }); | "#]]; let renderer_ascii = Renderer::plain(); assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: consider adding a `;` to the last statement for consistent formatting ╭▸ tests/ui/semicolon_if_nothing_returned_testing.rs:4:5 │ 4 │ ┏ nums.iter().for_each(|x| { 5 │ ┃ if *x > 0 { 6 │ ┃ println!("Positive number"); 7 │ ┃ } else { ┆ ┇ 10 │ ┃ }) │ ┗━━━━━━┛ ╰╴ note: the lint level is defined here ╭▸ tests/ui/semicolon_if_nothing_returned_testing.rs:2:9 │ 2 │ #![deny(clippy::semicolon_if_nothing_returned)] ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ help: add a `;` here ╭╴ 4 │ nums.iter().for_each(|x| { … 9 │ } 10 ± }); ╰╴ "#]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(input), expected_unicode); } #[test] fn suggestion_no_fold() { let source = r#"fn main() { let variable_name = 42; function_with_lots_of_arguments( variable_name, variable_name, variable_name, variable_name, ); }"#; let path = "$DIR/trimmed_multiline_suggestion.rs"; let input = &[ Group::with_title( Level::ERROR .primary_title("this function takes 6 arguments but 5 arguments were supplied") .id("E0061"), ) .element( Snippet::source(source) .path(path) .annotation( AnnotationKind::Context .span(108..121) .label("argument #2 of type `char` is missing"), ) .annotation(AnnotationKind::Primary.span(44..75)), ), Group::with_title(Level::HELP.secondary_title("provide the argument")).element( Snippet::source(source) .path(path) .fold(false) .patch(Patch::new( 75..174, "( variable_name, /* char */, variable_name, variable_name, variable_name, )", )), ), ]; let expected_ascii = str![[r#" error[E0061]: this function takes 6 arguments but 5 arguments were supplied --> $DIR/trimmed_multiline_suggestion.rs:3:5 | 3 | function_with_lots_of_arguments( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | variable_name, 5 | variable_name, | ------------- argument #2 of type `char` is missing | help: provide the argument | 1 | fn main() { 2 | let variable_name = 42; 3 | function_with_lots_of_arguments( 4 | variable_name, 5 ~ /* char */, 6 ~ variable_name, 7 | variable_name, 8 | variable_name, 9 | ); 10 | } | "#]]; let renderer_ascii = Renderer::plain(); assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0061]: this function takes 6 arguments but 5 arguments were supplied ╭▸ $DIR/trimmed_multiline_suggestion.rs:3:5 │ 3 │ function_with_lots_of_arguments( │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4 │ variable_name, 5 │ variable_name, │ ───────────── argument #2 of type `char` is missing ╰╴ help: provide the argument ╭╴ 1 │ fn main() { 2 │ let variable_name = 42; 3 │ function_with_lots_of_arguments( 4 │ variable_name, 5 ± /* char */, 6 ± variable_name, 7 │ variable_name, 8 │ variable_name, 9 │ ); 10 │ } ╰╴ "#]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(input), expected_unicode); } #[test] fn suggestion_no_fold_replacement_ends_with_newline() { let source = r#" use st::cell::Cell; mod bar { pub fn bar() { bar::baz(); } fn baz() {} } use bas::bar; struct Foo { bar: st::cell::Cell } fn main() {}"#; let input = &[ Level::ERROR .primary_title("failed to resolve: use of undeclared crate or module `st`") .id("E0433") .element( Snippet::source(source).line_start(1).annotation( AnnotationKind::Primary .span(122..124) .label("use of undeclared crate or module `st`"), ), ), Level::HELP .secondary_title("consider importing this module") .element( Snippet::source(source) .fold(false) .patch(Patch::new(1..1, "use std::cell;\n")), ), ]; let expected_ascii = str![[r#" error[E0433]: failed to resolve: use of undeclared crate or module `st` | 13 | bar: st::cell::Cell | ^^ use of undeclared crate or module `st` | help: consider importing this module | 1 | 2 + use std::cell; 3 | use st::cell::Cell; 4 | 5 | mod bar { 6 | pub fn bar() { bar::baz(); } 7 | 8 | fn baz() {} 9 | } 10 | 11 | use bas::bar; 12 | 13 | struct Foo { 14 | bar: st::cell::Cell 15 | } 16 | 17 | fn main() {} | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0433]: failed to resolve: use of undeclared crate or module `st` ╭▸ 13 │ bar: st::cell::Cell │ ━━ use of undeclared crate or module `st` ╰╴ help: consider importing this module ╭╴ 1 │ 2 + use std::cell; 3 │ use st::cell::Cell; 4 │ 5 │ mod bar { 6 │ pub fn bar() { bar::baz(); } 7 │ 8 │ fn baz() {} 9 │ } 10 │ 11 │ use bas::bar; 12 │ 13 │ struct Foo { 14 │ bar: st::cell::Cell 15 │ } 16 │ 17 │ fn main() {} ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn original_matches_replacement_suffix() { let source = r#"use sync;"#; let input = &[ Group::with_level(Level::ERROR).element( Snippet::source(source).path("/tmp/test.rs").annotation( AnnotationKind::Primary .span(4..8) .label("no `sync` in the root"), ), ), Level::HELP .secondary_title("consider importing this module instead") .element( Snippet::source(source) .path("/tmp/test.rs") .patch(Patch::new(4..8, "std::sync")), ), ]; let expected_ascii = str![[r#" --> /tmp/test.rs:1:5 | 1 | use sync; | ^^^^ no `sync` in the root | help: consider importing this module instead | 1 | use std::sync; | +++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" ╭▸ /tmp/test.rs:1:5 │ 1 │ use sync; │ ━━━━ no `sync` in the root ╰╴ help: consider importing this module instead ╭╴ 1 │ use std::sync; ╰╴ +++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn dont_panic_narrow_term_width_short_span() { let source = "pub fn f() { let mut foo_bar = 0; }"; let input = &[Level::WARNING .primary_title("variable does not need to be mutable") .element( Snippet::source(source).path("ice.rs").annotation( AnnotationKind::Primary .span(17..28) .label("help: remove this `mut`"), ), )]; let expected_ascii = str![[r#" warning: variable does not need to be mutable --> ice.rs:1:18 | 1 | ...et mut foo_bar = ... | ^^^^^^^^^^^ help: remove this `mut` "#]]; let renderer = Renderer::plain().term_width(8); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: variable does not need to be mutable ╭▸ ice.rs:1:18 │ 1 │ … let mut foo_bar = 0;… ╰╴ ━━━━━━━━━━━ help: remove this `mut` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggestion_different_path_than_primary() { let source = r#" foo.bar();"#; let secondary_source = r#"fn bar(&self) {"#; let input = &[ Level::ERROR .primary_title("method `five_years` is private") .id("E0624") .element( Snippet::source(source) .path("lib.rs") .annotation(AnnotationKind::Primary.span(8..13).label("private method")), ) .element( Snippet::source(secondary_source) .path("other.rs") .annotation( AnnotationKind::Context .span(3..13) .label("private method defined here"), ), ), Level::HELP .secondary_title("consider making `bar` public") .element( Snippet::source(secondary_source) .path("other.rs") .patch(Patch::new(0..0, "pub ")), ), ]; let expected_ascii = str![[r#" error[E0624]: method `five_years` is private --> lib.rs:1:9 | 1 | foo.bar(); | ^^^^^ private method | ::: other.rs:1:4 | 1 | fn bar(&self) { | ---------- private method defined here | help: consider making `bar` public ::: other.rs:1:1 | 1 | pub fn bar(&self) { | +++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0624]: method `five_years` is private ╭▸ lib.rs:1:9 │ 1 │ foo.bar(); │ ━━━━━ private method │ ⸬ other.rs:1:4 │ 1 │ fn bar(&self) { │ ────────── private method defined here ╰╴ help: consider making `bar` public ⸬ other.rs:1:1 │ 1 │ pub fn bar(&self) { ╰╴+++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn prefer_first_annotation_on_secondary_snippets() { let input = &[Level::ERROR .primary_title("main diagnostic message") .id("test-diagnostics") .element( Snippet::source("aardvark\nbeetle\ncanary\n") .path("animals") .fold(false) .annotation(AnnotationKind::Primary.span(0..8)), ) .element( Snippet::source("inchworm\njackrabbit\nkangaroo\n") .path("animals") .fold(false) .annotation(AnnotationKind::Context.span(20..28)), )]; let expected_ascii = str![[r#" error[test-diagnostics]: main diagnostic message --> animals:1:1 | 1 | aardvark | ^^^^^^^^ 2 | beetle 3 | canary | ::: animals:3:1 | 1 | inchworm 2 | jackrabbit 3 | kangaroo | -------- "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[test-diagnostics]: main diagnostic message ╭▸ animals:1:1 │ 1 │ aardvark │ ━━━━━━━━ 2 │ beetle 3 │ canary │ ⸬ animals:3:1 │ 1 │ inchworm 2 │ jackrabbit 3 │ kangaroo ╰╴──────── "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn consistent_indentation_with_trailing_newline() { let input = &[Level::ERROR .primary_title("main diagnostic message") .id("test-diagnostic") .element( Snippet::source("dog\nelephant\nfinch\n") .path("spacey-animals") .fold(false) .line_start(7) .annotation(AnnotationKind::Primary.span(4..12)), )]; let expected_ascii = str![[r#" error[test-diagnostic]: main diagnostic message --> spacey-animals:8:1 | 7 | dog 8 | elephant | ^^^^^^^^ 9 | finch | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[test-diagnostic]: main diagnostic message ╭▸ spacey-animals:8:1 │ 7 │ dog 8 │ elephant │ ━━━━━━━━ 9 │ finch ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_line_cut() { let source = "abcd abcd abcd abcd abcd abcd abcd"; let input = Level::ERROR.primary_title("").element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Primary.span(0..4)), ); let expected = str![[r#" error: | 1 | abcd abcd a... | ^^^^ "#]]; let renderer = Renderer::plain().term_width(18); assert_data_eq!(renderer.render(&[input]).clone(), expected); } #[test] fn long_line_cut_custom() { let source = "abcd abcd abcd abcd abcd abcd abcd"; let input = Level::ERROR.primary_title("").element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Primary.span(0..4)), ); // This trims a little less because `…` is visually smaller than `...`. let expected = str![[r#" error: | 1 | abcd abcd abc… | ^^^^ "#]]; let renderer = Renderer::plain().term_width(18).cut_indicator("…"); assert_data_eq!(renderer.render(&[input]).clone(), expected); } #[test] fn leading_nbsp_no_overflow() { // Regression test: an annotation pointing at leading whitespace caused a // subtraction overflow in Margin::compute because `label_right` can be less // than `whitespace_left`. See https://github.com/astral-sh/ty/issues/836 let source = " \u{00A0} 'betting_env.datastructure.team_lineup.Tamheet.get_latest': ( 'dataStructure/team_lineup.htm#teamsheet.getlatest',"; let input = Level::ERROR.primary_title("test").element( Snippet::source(source) .line_start(1) .annotation(AnnotationKind::Primary.span(0..1)), ); // Should not panic. let renderer = Renderer::plain(); let _ = renderer.render(&[input]).clone(); } #[test] fn hide_snippet() { // tests/ui/traits/alias/object-fail.rs let source = r#"#![feature(trait_alias)] trait EqAlias = Eq; trait IteratorAlias = Iterator; fn main() { let _: &dyn EqAlias = &123; //~^ ERROR the trait alias `EqAlias` is not dyn compatible [E0038] let _: &dyn IteratorAlias = &vec![123].into_iter(); //~^ ERROR must be specified } "#; let input = &[Level::ERROR .primary_title("the trait alias `EqAlias` is not dyn compatible") .id("E0038") .element( Snippet::source(source) .line_start(1) .path("$DIR/object-fail.rs") .annotation( AnnotationKind::Primary .span(107..114) .label("`EqAlias` is not dyn compatible") .hide_snippet(true), ), )]; let expected_ascii = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible --> $DIR/object-fail.rs:7:17 "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible ─▸ $DIR/object-fail.rs:7:17 "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn only_origin() { let input = &[Level::ERROR .primary_title("the trait alias `EqAlias` is not dyn compatible") .id("E0038") .element( Origin::path("$SRC_DIR/core/src/cmp.rs") .line(334) .char_column(14), )]; let expected_ascii = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible --> $SRC_DIR/core/src/cmp.rs:334:14 "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible ─▸ $SRC_DIR/core/src/cmp.rs:334:14 "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn lineno_offset() { let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source("First line\r\nSecond oops line") .path("") .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::NOTE.secondary_title("details").element( Snippet::source("First line\r\nSecond oops line") .path("") .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("suggestion") .element(Origin::path("")) .lineno_offset(10), ]; let expected_ascii = str![[r#" error: oops --> :2:8 | 2 | Second oops line | ^^^^ oops | note: details --> :2:8 | 2 | Second oops line | ^^^^ oops help: suggestion --> "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ :2:8 │ 2 │ Second oops line │ ━━━━ oops ╰╴ note: details ╭▸ :2:8 │ 2 │ Second oops line ╰╴ ━━━━ oops help: suggestion ─▸ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn trailing_newline_span() { let input = &[Level::ERROR .primary_title("Extra newline at end of file") .id("W391") .is_fixable(true) .element( Snippet::source(" foo()\n bar()\n\n") .path("W391_0.py") .line_start(12) .annotation(AnnotationKind::Primary.span(20..21)) .fold(false), )]; let expected_ascii = str![[r#" error[W391][*]: Extra newline at end of file --> W391_0.py:14:1 | 12 | foo() 13 | bar() 14 | | ^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[W391][*]: Extra newline at end of file ╭▸ W391_0.py:14:1 │ 12 │ foo() 13 │ bar() 14 │ ╰╴━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multi_newline_span() { let input = &[Level::ERROR .primary_title("Too many newlines at end of cell") .id("W391") .is_fixable(true) .element( Snippet::source("\n\n") .path("W391.ipynb") .line_start(19) .annotation(AnnotationKind::Primary.span(0..2)) .fold(false), )]; let expected_ascii = str![[r#" error[W391][*]: Too many newlines at end of cell --> W391.ipynb:19:1 | 19 | / 20 | | | |_^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[W391][*]: Too many newlines at end of cell ╭▸ W391.ipynb:19:1 │ 19 │ ┏ 20 │ ┃ ╰╴┗━┛ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/ruff.rs000064400000000000000000000337471046102023000220750ustar00use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet}; use annotate_snippets::renderer::DecorStyle; use snapbox::{assert_data_eq, str}; #[test] fn snippet_with_cell() { let source = "First line\r\nSecond oops line"; let input = &[Level::ERROR.primary_title("oops").element( Snippet::source(source) .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), )]; let expected_ascii = str![[r#" error: oops | 2 | Second oops line | ^^^^ oops "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ 2 │ Second oops line ╰╴ ━━━━ oops "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn snippet_with_path_cell() { let source = "First line\r\nSecond oops line"; let input = &[Level::ERROR.primary_title("oops").element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), )]; let expected_ascii = str![[r#" error: oops --> foo.ipynb:cell 1:2:8 | 2 | Second oops line | ^^^^ oops "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ foo.ipynb:cell 1:2:8 │ 2 │ Second oops line ╰╴ ━━━━ oops "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_primary_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .cell_index(Some(1)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .cell_index(Some(1)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: cell 1:2:8 | 2 - Second oops line 2 + Second line | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ cell 1:2:8 │ 2 - Second oops line 2 + Second line ├╴ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_primary_path_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops --> foo.ipynb:cell 1:2:8 | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: cell 1:2:8 | 2 - Second oops line 2 + Second line | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ foo.ipynb:cell 1:2:8 │ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ cell 1:2:8 │ 2 - Second oops line 2 + Second line ├╴ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_primary_path_incrementing_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(2)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops --> foo.ipynb:cell 1:2:8 | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: cell 1:2:8 | 2 - Second oops line 2 + Second line | ::: cell 2:2:12 | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ foo.ipynb:cell 1:2:8 │ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ cell 1:2:8 │ 2 - Second oops line 2 + Second line │ ⸬ cell 2:2:12 │ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_other_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .cell_index(Some(2)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .cell_index(Some(2)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: cell 2:2:8 | 2 - Second oops line 2 + Second line | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ cell 2:2:8 │ 2 - Second oops line 2 + Second line ├╴ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_other_path_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .path("bar.ipynb") .cell_index(Some(2)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .path("bar.ipynb") .cell_index(Some(2)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops --> foo.ipynb:cell 1:2:8 | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: bar.ipynb:cell 2:2:8 | 2 - Second oops line 2 + Second line | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ foo.ipynb:cell 1:2:8 │ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ bar.ipynb:cell 2:2:8 │ 2 - Second oops line 2 + Second line ├╴ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn patch_with_other_path_incrementing_cell() { let source = "First line\r\nSecond oops line"; let input = &[ Level::ERROR.primary_title("oops").element( Snippet::source(source) .path("foo.ipynb") .cell_index(Some(1)) .annotation(AnnotationKind::Primary.span(19..23).label("oops")), ), Level::HELP .secondary_title("remove the entry") .element( Snippet::source(source) .path("bar.ipynb") .cell_index(Some(2)) .patch(Patch::new(19..24, "")), ) .element( Snippet::source(source) .path("bar.ipynb") .cell_index(Some(3)) .patch(Patch::new(23..28, "")), ), ]; let expected_ascii = str![[r#" error: oops --> foo.ipynb:cell 1:2:8 | 2 | Second oops line | ^^^^ oops | help: remove the entry ::: bar.ipynb:cell 2:2:8 | 2 - Second oops line 2 + Second line | ::: bar.ipynb:cell 3:2:12 | 2 - Second oops line 2 + Second oops | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: oops ╭▸ foo.ipynb:cell 1:2:8 │ 2 │ Second oops line │ ━━━━ oops ╰╴ help: remove the entry ⸬ bar.ipynb:cell 2:2:8 │ 2 - Second oops line 2 + Second line │ ⸬ bar.ipynb:cell 3:2:12 │ 2 - Second oops line 2 + Second oops ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn insertion_with_trailing_whitespace() { let source = "line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\nline 13\n"; let input = &[ Level::ERROR .primary_title("main diagnostic message") .id("test-diagnostic") .element( Snippet::source(source) .path("example.py") .annotation(AnnotationKind::Primary.span(7..13)), ), Level::HELP .secondary_title("Replace three lines") .element(Snippet::source(source).patch(Patch::new(7..7, "fixed "))), ]; let expected_ascii = str![[r#" error[test-diagnostic]: main diagnostic message --> example.py:2:1 | 2 | line 2 | ^^^^^^ | help: Replace three lines | 2 | fixed line 2 | +++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[test-diagnostic]: main diagnostic message ╭▸ example.py:2:1 │ 2 │ line 2 │ ━━━━━━ ╰╴ help: Replace three lines ╭╴ 2 │ fixed line 2 ╰╴+++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_insertions() { let source = "line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\nline 13\n"; let input = &[ Level::ERROR .primary_title("main diagnostic message") .id("test-diagnostic") .element( Snippet::source(source) .path("example.py") .annotation(AnnotationKind::Primary.span(7..13)), ), Level::HELP.secondary_title("Replace three lines").element( Snippet::source(source) .patch(Patch::new(7..7, "fixed ")) .patch(Patch::new(42..42, "fixed ")) .patch(Patch::new(87..87, "fixed ")), ), ]; let expected_ascii = str![[r#" error[test-diagnostic]: main diagnostic message --> example.py:2:1 | 2 | line 2 | ^^^^^^ | help: Replace three lines | 2 ~ fixed line 2 3 | line 3 ... 6 | line 6 7 ~ fixed line 7 8 | line 8 ... 12 | line 12 13 ~ fixed line 13 | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[test-diagnostic]: main diagnostic message ╭▸ example.py:2:1 │ 2 │ line 2 │ ━━━━━━ ╰╴ help: Replace three lines ╭╴ 2 ± fixed line 2 3 │ line 3 … 6 │ line 6 7 ± fixed line 7 8 │ line 8 … 12 │ line 12 13 ± fixed line 13 ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } ast_serialize-0.13.1/crates/ruff_annotate_snippets/tests/rustc_tests.rs000064400000000000000000006475131046102023000235170ustar00//! These tests have been adapted from [Rust's parser tests][parser-tests]. //! //! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs use annotate_snippets::{AnnotationKind, Group, Level, Origin, Padding, Patch, Renderer, Snippet}; use annotate_snippets::renderer::DecorStyle; use snapbox::{IntoData, assert_data_eq, str}; #[test] fn ends_on_col0() { let source = r#" fn foo() { } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(10..13).label("test")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:2:10 | 2 | fn foo() { | __________^ 3 | | } | |_^ test "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:2:10 │ 2 │ fn foo() { │ ┏━━━━━━━━━━┛ 3 │ ┃ } ╰╴┗━┛ test "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn ends_on_col2() { let source = r#" fn foo() { } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(10..17).label("test")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:2:10 | 2 | fn foo() { | __________^ ... | 5 | | } | |___^ test "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:2:10 │ 2 │ fn foo() { │ ┏━━━━━━━━━━┛ ┆ ┇ 5 │ ┃ } ╰╴┗━━━┛ test "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn non_nested() { let source = r#" fn foo() { X0 Y0 X1 Y1 X2 Y2 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..32) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(17..35) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | X0 Y0 | ____^ - | | ______| 4 | || X1 Y1 5 | || X2 Y2 | ||____^__- `Y` is a good letter too | |_____| | `X` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ X0 Y0 │ ┏━━━━┛ │ │ ┃┌──────┘ 4 │ ┃│ X1 Y1 5 │ ┃│ X2 Y2 │ ┃└────╿──┘ `Y` is a good letter too │ ┗━━━━━┥ ╰╴ `X` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn nested() { let source = r#" fn foo() { X0 Y0 Y1 X1 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..27) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(17..24) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | X0 Y0 | ____^ - | | ______| 4 | || Y1 X1 | ||____-__^ `X` is a good letter | |____| | `Y` is a good letter too "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ X0 Y0 │ ┏━━━━┛ │ │ ┃┌──────┘ 4 │ ┃│ Y1 X1 │ ┗│━━━━│━━┛ `X` is a good letter │ └────┤ ╰╴ `Y` is a good letter too "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn different_overlap() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(17..38) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(31..49) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 | _______^ 4 | | X1 Y1 Z1 | | _________- 5 | || X2 Y2 Z2 | ||____^ `X` is a good letter 6 | | X3 Y3 Z3 | |____- `Y` is a good letter too "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:6 │ 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ 4 │ ┃ X1 Y1 Z1 │ ┃┌─────────┘ 5 │ ┃│ X2 Y2 Z2 │ ┗│━━━━┛ `X` is a good letter 6 │ │ X3 Y3 Z3 ╰╴ └────┘ `Y` is a good letter too "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn triple_overlap() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..38) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(17..41) .label("`Y` is a good letter too"), ) .annotation(AnnotationKind::Context.span(20..44).label("`Z` label")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | X0 Y0 Z0 | _____^ - - | | _______| | | || _________| 4 | ||| X1 Y1 Z1 5 | ||| X2 Y2 Z2 | |||____^__-__- `Z` label | ||_____|__| | |______| `Y` is a good letter too | `X` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ X0 Y0 Z0 │ ┏━━━━━┛ │ │ │ ┃┌───────┘ │ │ ┃│┌─────────┘ 4 │ ┃││ X1 Y1 Z1 5 │ ┃││ X2 Y2 Z2 │ ┃│└────╿──│──┘ `Z` label │ ┃└─────│──┤ │ ┗━━━━━━┥ `Y` is a good letter too ╰╴ `X` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn triple_exact_overlap() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..38) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(14..38) .label("`Y` is a good letter too"), ) .annotation(AnnotationKind::Context.span(14..38).label("`Z` label")), )]; // This should have a `^` but we currently don't support the idea of a // "primary" annotation, which would solve this let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | / X0 Y0 Z0 4 | | X1 Y1 Z1 5 | | X2 Y2 Z2 | | ^ | | | | | `X` is a good letter | |____`Y` is a good letter too | `Z` label "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ ┏ X0 Y0 Z0 4 │ ┃ X1 Y1 Z1 5 │ ┃ X2 Y2 Z2 │ ┃ ╿ │ ┃ │ │ ┃ `X` is a good letter │ ┗━━━━`Y` is a good letter too ╰╴ `Z` label "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn minimum_depth() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(17..27) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(28..44) .label("`Y` is a good letter too"), ) .annotation(AnnotationKind::Context.span(36..52).label("`Z`")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 | _______^ 4 | | X1 Y1 Z1 | | ____^_- | ||____| | | `X` is a good letter 5 | | X2 Y2 Z2 | |___-______- `Y` is a good letter too | ___| | | 6 | | X3 Y3 Z3 | |_______- `Z` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:6 │ 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ 4 │ ┃ X1 Y1 Z1 │ ┃┌────╿─┘ │ ┗│━━━━┥ │ │ `X` is a good letter 5 │ │ X2 Y2 Z2 │ └───│──────┘ `Y` is a good letter too │ ┌───┘ │ │ 6 │ │ X3 Y3 Z3 ╰╴ └───────┘ `Z` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn non_overlapping() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..27) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(39..55) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | / X0 Y0 Z0 4 | | X1 Y1 Z1 | |____^ `X` is a good letter 5 | X2 Y2 Z2 | ______- 6 | | X3 Y3 Z3 | |__________- `Y` is a good letter too "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ ┏ X0 Y0 Z0 4 │ ┃ X1 Y1 Z1 │ ┗━━━━┛ `X` is a good letter 5 │ X2 Y2 Z2 │ ┌──────┘ 6 │ │ X3 Y3 Z3 ╰╴└──────────┘ `Y` is a good letter too "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn overlapping_start_and_end() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(17..27) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(31..55) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 | _______^ 4 | | X1 Y1 Z1 | | ____^____- | ||____| | | `X` is a good letter 5 | | X2 Y2 Z2 6 | | X3 Y3 Z3 | |__________- `Y` is a good letter too "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:6 │ 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ 4 │ ┃ X1 Y1 Z1 │ ┃┌────╿────┘ │ ┗│━━━━┥ │ │ `X` is a good letter 5 │ │ X2 Y2 Z2 6 │ │ X3 Y3 Z3 ╰╴ └──────────┘ `Y` is a good letter too "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_primary_without_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(18..25).label("")) .annotation( AnnotationKind::Context .span(14..27) .label("`a` is a good letter"), ) .annotation(AnnotationKind::Context.span(22..23).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:7 | 3 | a { b { c } d } | ----^^^^-^^-- `a` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:7 │ 3 │ a { b { c } d } ╰╴ ────━━━━─━━── `a` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_secondary_without_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..27) .label("`a` is a good letter"), ) .annotation(AnnotationKind::Context.span(18..25).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^-------^^ `a` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } ╰╴ ━━━━───────━━ `a` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_primary_without_message_2() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(18..25) .label("`b` is a good letter"), ) .annotation(AnnotationKind::Context.span(14..27).label("")) .annotation(AnnotationKind::Context.span(22..23).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:7 | 3 | a { b { c } d } | ----^^^^-^^-- | | | `b` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:7 │ 3 │ a { b { c } d } │ ────┯━━━─━━── │ │ ╰╴ `b` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_secondary_without_message_2() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(14..27).label("")) .annotation( AnnotationKind::Context .span(18..25) .label("`b` is a good letter"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^-------^^ | | | `b` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } │ ━━━━┬──────━━ │ │ ╰╴ `b` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_secondary_without_message_3() { let source = r#" fn foo() { a bc d } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..18) .label("`a` is a good letter"), ) .annotation(AnnotationKind::Context.span(18..22).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a bc d | ^^^^---- | | | `a` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a bc d │ ┯━━━──── │ │ ╰╴ `a` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_without_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(14..27).label("")) .annotation(AnnotationKind::Context.span(18..25).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^-------^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } ╰╴ ━━━━───────━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_without_message_2() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(18..25).label("")) .annotation(AnnotationKind::Context.span(14..27).label("")) .annotation(AnnotationKind::Context.span(22..23).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:7 | 3 | a { b { c } d } | ----^^^^-^^-- "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:7 │ 3 │ a { b { c } d } ╰╴ ────━━━━─━━── "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_labels_with_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..27) .label("`a` is a good letter"), ) .annotation( AnnotationKind::Context .span(18..25) .label("`b` is a good letter"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^-------^^ | | | | | `b` is a good letter | `a` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } │ ┯━━━┬──────━━ │ │ │ │ │ `b` is a good letter ╰╴ `a` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn ingle_label_with_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(14..27) .label("`a` is a good letter"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^^^^^^^^^^ `a` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } ╰╴ ━━━━━━━━━━━━━ `a` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn single_label_without_message() { let source = r#" fn foo() { a { b { c } d } } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation(AnnotationKind::Primary.span(14..27).label("")), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:3 | 3 | a { b { c } d } | ^^^^^^^^^^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:3 │ 3 │ a { b { c } d } ╰╴ ━━━━━━━━━━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_snippet() { let source = r#" fn foo() { X0 Y0 Z0 X1 Y1 Z1 1 2 3 4 5 6 7 8 9 10 X2 Y2 Z2 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(17..27) .label("`X` is a good letter"), ) .annotation( AnnotationKind::Context .span(31..76) .label("`Y` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 | _______^ 4 | | X1 Y1 Z1 | | ____^____- | ||____| | | `X` is a good letter 5 | | 1 6 | | 2 7 | | 3 ... | 15 | | X2 Y2 Z2 16 | | X3 Y3 Z3 | |__________- `Y` is a good letter too "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:6 │ 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ 4 │ ┃ X1 Y1 Z1 │ ┃┌────╿────┘ │ ┗│━━━━┥ │ │ `X` is a good letter 5 │ │ 1 6 │ │ 2 7 │ │ 3 ┆ ┆ 15 │ │ X2 Y2 Z2 16 │ │ X3 Y3 Z3 ╰╴ └──────────┘ `Y` is a good letter too "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_snippet_multiple_spans() { let source = r#" fn foo() { X0 Y0 Z0 1 2 3 X1 Y1 Z1 4 5 6 X2 Y2 Z2 7 8 9 10 X3 Y3 Z3 } "#; let input = &[Level::ERROR.primary_title("foo").element( Snippet::source(source) .line_start(1) .path("test.rs") .annotation( AnnotationKind::Primary .span(17..73) .label("`Y` is a good letter"), ) .annotation( AnnotationKind::Context .span(37..56) .label("`Z` is a good letter too"), ), )]; let expected_ascii = str![[r#" error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 | _______^ 4 | | 1 5 | | 2 6 | | 3 7 | | X1 Y1 Z1 | | _________- 8 | || 4 9 | || 5 10 | || 6 11 | || X2 Y2 Z2 | ||__________- `Z` is a good letter too ... | 15 | | 10 16 | | X3 Y3 Z3 | |________^ `Y` is a good letter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: foo ╭▸ test.rs:3:6 │ 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ 4 │ ┃ 1 5 │ ┃ 2 6 │ ┃ 3 7 │ ┃ X1 Y1 Z1 │ ┃┌─────────┘ 8 │ ┃│ 4 9 │ ┃│ 5 10 │ ┃│ 6 11 │ ┃│ X2 Y2 Z2 │ ┃└──────────┘ `Z` is a good letter too ┆ ┇ 15 │ ┃ 10 16 │ ┃ X3 Y3 Z3 ╰╴┗━━━━━━━━┛ `Y` is a good letter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn issue_91334() { let source = r#"// Regression test for the ICE described in issue #91334. //@ error-pattern: this file contains an unclosed delimiter #![feature(coroutines)] fn f(){||yield(((){), "#; let input = &[Level::ERROR .primary_title("this file contains an unclosed delimiter") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-91334.rs") .annotation( AnnotationKind::Context .span(151..152) .label("unclosed delimiter"), ) .annotation( AnnotationKind::Context .span(159..160) .label("unclosed delimiter"), ) .annotation( AnnotationKind::Context .span(164..164) .label("missing open `(` for this delimiter"), ) .annotation(AnnotationKind::Primary.span(167..167)), )]; let expected_ascii = str![[r#" error: this file contains an unclosed delimiter --> $DIR/issue-91334.rs:7:23 | 7 | fn f(){||yield(((){), | - - - ^ | | | | | | | missing open `(` for this delimiter | | unclosed delimiter | unclosed delimiter "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: this file contains an unclosed delimiter ╭▸ $DIR/issue-91334.rs:7:23 │ 7 │ fn f(){||yield(((){), │ ┬ ┬ ┬ ━ │ │ │ │ │ │ │ missing open `(` for this delimiter │ │ unclosed delimiter ╰╴ unclosed delimiter "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn issue_114529_illegal_break_with_value() { // tests/ui/typeck/issue-114529-illegal-break-with-value.rs let source = r#"// Regression test for issue #114529 // Tests that we do not ICE during const eval for a // break-with-value in contexts where it is illegal #[allow(while_true)] fn main() { [(); { while true { break 9; //~ ERROR `break` with value from a `while` loop }; 51 }]; [(); { while let Some(v) = Some(9) { break v; //~ ERROR `break` with value from a `while` loop }; 51 }]; while true { break (|| { //~ ERROR `break` with value from a `while` loop let local = 9; }); } } "#; let input = &[ Level::ERROR .primary_title("`break` with value from a `while` loop") .id("E0571") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .annotation( AnnotationKind::Primary .span(483..581) .label("can only break with a value inside `loop` or breakable block"), ) .annotation( AnnotationKind::Context .span(462..472) .label("you can't `break` with a value in a `while` loop"), ), ), Level::HELP .secondary_title("use `break` on its own without a value inside this `while` loop") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") .annotation(AnnotationKind::Context.span(483..581).label("break")), ), ]; let expected_ascii = str![[r#" error[E0571]: `break` with value from a `while` loop --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 | 21 | while true { | ---------- you can't `break` with a value in a `while` loop 22 | / break (|| { //~ ERROR `break` with value from a `while` loop 23 | | let local = 9; 24 | | }); | |__________^ can only break with a value inside `loop` or breakable block | help: use `break` on its own without a value inside this `while` loop --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 | 22 | / break (|| { //~ ERROR `break` with value from a `while` loop 23 | | let local = 9; 24 | | }); | |__________- break "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0571]: `break` with value from a `while` loop ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 │ 21 │ while true { │ ────────── you can't `break` with a value in a `while` loop 22 │ ┏ break (|| { //~ ERROR `break` with value from a `while` loop 23 │ ┃ let local = 9; 24 │ ┃ }); │ ┗━━━━━━━━━━┛ can only break with a value inside `loop` or breakable block ╰╴ help: use `break` on its own without a value inside this `while` loop ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 │ 22 │ ┌ break (|| { //~ ERROR `break` with value from a `while` loop 23 │ │ let local = 9; 24 │ │ }); ╰╴└──────────┘ break "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn primitive_reprs_should_have_correct_length() { // tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs let source = r#"//! An enum with a primitive repr should have exactly the size of that primitive. #![crate_type = "lib"] #![feature(transmutability)] #![allow(dead_code)] mod assert { use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where Dst: TransmuteFrom {} } #[repr(C)] struct Zst; #[derive(Clone, Copy)] #[repr(i8)] enum V0i8 { V } #[repr(u8)] enum V0u8 { V } #[repr(i16)] enum V0i16 { V } #[repr(u16)] enum V0u16 { V } #[repr(i32)] enum V0i32 { V } #[repr(u32)] enum V0u32 { V } #[repr(i64)] enum V0i64 { V } #[repr(u64)] enum V0u64 { V } #[repr(isize)] enum V0isize { V } #[repr(usize)] enum V0usize { V } fn n8() { type Smaller = Zst; type Analog = u8; type Larger = u16; fn i_should_have_correct_length() { type Current = V0i8; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn u_should_have_correct_length() { type Current = V0u8; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } } fn n16() { type Smaller = u8; type Analog = u16; type Larger = u32; fn i_should_have_correct_length() { type Current = V0i16; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn u_should_have_correct_length() { type Current = V0u16; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } } fn n32() { type Smaller = u16; type Analog = u32; type Larger = u64; fn i_should_have_correct_length() { type Current = V0i32; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn u_should_have_correct_length() { type Current = V0u32; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } } fn n64() { type Smaller = u32; type Analog = u64; type Larger = u128; fn i_should_have_correct_length() { type Current = V0i64; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn u_should_have_correct_length() { type Current = V0u64; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } } fn nsize() { type Smaller = u8; type Analog = usize; type Larger = [usize; 2]; fn i_should_have_correct_length() { type Current = V0isize; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn u_should_have_correct_length() { type Current = V0usize; assert::is_transmutable::(); //~ ERROR cannot be safely transmuted assert::is_transmutable::(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } } "#; let input = &[ Level::ERROR .primary_title("`V0usize` cannot be safely transmuted into `[usize; 2]`") .id("E0277") .element( Snippet::source(source) .line_start(1) .path("$DIR/primitive_reprs_should_have_correct_length.rs") .annotation(AnnotationKind::Primary.span(4375..4381).label( "the size of `V0usize` is smaller than the size of `[usize; 2]`", )), ), Level::NOTE .secondary_title("required by a bound in `is_transmutable`") .element( Snippet::source(source) .line_start(1) .path("$DIR/primitive_reprs_should_have_correct_length.rs") .annotation( AnnotationKind::Context .span(225..240) .label("required by a bound in this function"), ) .annotation( AnnotationKind::Primary .span(276..470) .label("required by this bound in `is_transmutable`"), ), ), ]; let expected_ascii = str![[r#" error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44 | 144 | assert::is_transmutable::(); //~ ERROR cannot be safely transmuted | ^^^^^^ the size of `V0usize` is smaller than the size of `[usize; 2]` | note: required by a bound in `is_transmutable` --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | 10 | pub fn is_transmutable() | --------------- required by a bound in this function 11 | where 12 | Dst: TransmuteFrom | |__________^ required by this bound in `is_transmutable` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` ╭▸ $DIR/primitive_reprs_should_have_correct_length.rs:144:44 │ 144 │ assert::is_transmutable::(); //~ ERROR cannot be safely transmuted │ ━━━━━━ the size of `V0usize` is smaller than the size of `[usize; 2]` ╰╴ note: required by a bound in `is_transmutable` ╭▸ $DIR/primitive_reprs_should_have_correct_length.rs:12:14 │ 10 │ pub fn is_transmutable() │ ─────────────── required by a bound in this function 11 │ where 12 │ Dst: TransmuteFrom ╰╴┗━━━━━━━━━━┛ required by this bound in `is_transmutable` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn align_fail() { // tests/ui/transmutability/alignment/align-fail.rs let source = r#"//@ check-fail #![feature(transmutability)] mod assert { use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where Dst: TransmuteFrom {} } fn main() { assert::is_maybe_transmutable::<&'static [u8; 0], &'static [u16; 0]>(); //~ ERROR `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` } "#; let input = &[Level::ERROR .primary_title("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") .id("E027s7").element( Snippet::source(source) .line_start(1) .path("$DIR/align-fail.rs") .annotation( AnnotationKind::Primary .span(442..459) .label("the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2)") ), )]; let expected_ascii = str![[r#" error[E027s7]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` --> $DIR/align-fail.rs:21:55 | 21 | ...ic [u8; 0], &'static [u16; 0]>(); //~ ERROR `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` | ^^^^^^^^^^^^^^^^^ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E027s7]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` ╭▸ $DIR/align-fail.rs:21:55 │ 21 │ …atic [u8; 0], &'static [u16; 0]>(); //~ ERROR `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` ╰╴ ━━━━━━━━━━━━━━━━━ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn missing_semicolon() { // tests/ui/suggestions/missing-semicolon.rs let source = r#"//@ run-rustfix #![allow(dead_code, unused_variables, path_statements)] fn a() { let x = 5; let y = x //~ ERROR expected function () //~ ERROR expected `;`, found `}` } fn b() { let x = 5; let y = x //~ ERROR expected function (); } fn c() { let x = 5; x //~ ERROR expected function () } fn d() { // ok let x = || (); x () } fn e() { // ok let x = || (); x (); } fn f() { let y = 5 //~ ERROR expected function () //~ ERROR expected `;`, found `}` } fn g() { 5 //~ ERROR expected function (); } fn main() {} "#; let input = &[Level::ERROR .primary_title("expected function, found `{integer}`") .id("E0618") .element( Snippet::source(source) .line_start(1) .path("$DIR/missing-semicolon.rs") .annotation( AnnotationKind::Context .span(108..144) .label("call expression requires function"), ) .annotation( AnnotationKind::Context .span(89..90) .label("`x` has type `{integer}`"), ) .annotation(AnnotationKind::Context.span(109..109).label( "help: consider using a semicolon here to finish the statement: `;`", )) .annotation(AnnotationKind::Primary.span(108..109)), )]; let expected_ascii = str![[r#" error[E0618]: expected function, found `{integer}` --> $DIR/missing-semicolon.rs:5:13 | 4 | let x = 5; | - `x` has type `{integer}` 5 | let y = x //~ ERROR expected function | ^- help: consider using a semicolon here to finish the statement: `;` | _____________| | | 6 | | () //~ ERROR expected `;`, found `}` | |______- call expression requires function "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0618]: expected function, found `{integer}` ╭▸ $DIR/missing-semicolon.rs:5:13 │ 4 │ let x = 5; │ ─ `x` has type `{integer}` 5 │ let y = x //~ ERROR expected function │ ━─ help: consider using a semicolon here to finish the statement: `;` │ ┌─────────────┘ │ │ 6 │ │ () //~ ERROR expected `;`, found `}` ╰╴└──────┘ call expression requires function "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn nested_macro_rules() { // tests/ui/proc-macro/nested-macro-rules.rs let source = r#"//@ run-pass //@ aux-build:nested-macro-rules.rs //@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug -Z macro-backtrace //@ edition:2018 #![no_std] // Don't load unnecessary hygiene information from std #![warn(non_local_definitions)] extern crate std; extern crate nested_macro_rules; extern crate test_macros; use test_macros::{print_bang, print_attr}; use nested_macro_rules::FirstStruct; struct SecondStruct; fn main() { nested_macro_rules::inner_macro!(print_bang, print_attr); nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); //~^ WARN non-local `macro_rules!` definition inner_macro!(print_bang, print_attr); } "#; let aux_source = r#"pub struct FirstStruct; #[macro_export] macro_rules! outer_macro { ($name:ident, $attr_struct_name:ident) => { #[macro_export] macro_rules! inner_macro { ($bang_macro:ident, $attr_macro:ident) => { $bang_macro!($name); #[$attr_macro] struct $attr_struct_name {} } } } } outer_macro!(FirstStruct, FirstAttrStruct); "#; let input = &[ Level::WARNING .primary_title("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") .element( Snippet::source(aux_source) .line_start(1) .path("$DIR/auxiliary/nested-macro-rules.rs") .annotation( AnnotationKind::Context .span(41..65) .label("in this expansion of `nested_macro_rules::outer_macro!`"), ) .annotation(AnnotationKind::Primary.span(148..350)), ) .element( Snippet::source(source) .line_start(1) .path("$DIR/nested-macro-rules.rs") .annotation( AnnotationKind::Context .span(510..574) .label("in this macro invocation"), ), ) .element( Level::HELP .message("remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main`") ) .element( Level::NOTE .message("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute") ), Level::NOTE.secondary_title("the lint level is defined here") .element( Snippet::source(source) .line_start(1) .path("$DIR/nested-macro-rules.rs") .annotation(AnnotationKind::Primary.span(224..245)), )]; let expected_ascii = str![[r#" warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/auxiliary/nested-macro-rules.rs:7:9 | 4 | macro_rules! outer_macro { | ------------------------ in this expansion of `nested_macro_rules::outer_macro!` ... 7 | / macro_rules! inner_macro { 8 | | ($bang_macro:ident, $attr_macro:ident) => { 9 | | $bang_macro!($name); 10 | | #[$attr_macro] struct $attr_struct_name {} 11 | | } 12 | | } | |_________^ | ::: $DIR/nested-macro-rules.rs:23:5 | 23 | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | ---------------------------------------------------------------- in this macro invocation | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute note: the lint level is defined here --> $DIR/nested-macro-rules.rs:8:9 | 8 | #![warn(non_local_definitions)] | ^^^^^^^^^^^^^^^^^^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module ╭▸ $DIR/auxiliary/nested-macro-rules.rs:7:9 │ 4 │ macro_rules! outer_macro { │ ──────────────────────── in this expansion of `nested_macro_rules::outer_macro!` ┆ 7 │ ┏ macro_rules! inner_macro { 8 │ ┃ ($bang_macro:ident, $attr_macro:ident) => { 9 │ ┃ $bang_macro!($name); 10 │ ┃ #[$attr_macro] struct $attr_struct_name {} 11 │ ┃ } 12 │ ┃ } │ ┗━━━━━━━━━┛ │ ⸬ $DIR/nested-macro-rules.rs:23:5 │ 23 │ nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); │ ──────────────────────────────────────────────────────────────── in this macro invocation │ ├ help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` ╰ note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute note: the lint level is defined here ╭▸ $DIR/nested-macro-rules.rs:8:9 │ 8 │ #![warn(non_local_definitions)] ╰╴ ━━━━━━━━━━━━━━━━━━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn method_on_ambiguous_numeric_type() { // tests/ui/methods/method-on-ambiguous-numeric-type.rs let source = r#"//@ aux-build:macro-in-other-crate.rs #[macro_use] extern crate macro_in_other_crate; macro_rules! local_mac { ($ident:ident) => { let $ident = 42; } } macro_rules! local_mac_tt { ($tt:tt) => { let $tt = 42; } } fn main() { let x = 2.0.neg(); //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` let y = 2.0; let x = y.neg(); //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` println!("{:?}", x); for i in 0..100 { println!("{}", i.pow(2)); //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` } local_mac!(local_bar); local_bar.pow(2); //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` local_mac_tt!(local_bar_tt); local_bar_tt.pow(2); //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` } fn qux() { mac!(bar); bar.pow(2); //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` } "#; let aux_source = r#"#[macro_export] macro_rules! mac { ($ident:ident) => { let $ident = 42; } } #[macro_export] macro_rules! inline { () => () } "#; let input = &[ Level::ERROR .primary_title("can't call method `pow` on ambiguous numeric type `{integer}`") .id("E0689") .element( Snippet::source(source) .line_start(1) .path("$DIR/method-on-ambiguous-numeric-type.rs") .annotation(AnnotationKind::Primary.span(916..919)), ), Level::HELP .secondary_title("you must specify a type for this binding, like `i32`") .element( Snippet::source(aux_source) .line_start(1) .path("$DIR/auxiliary/macro-in-other-crate.rs") .annotation(AnnotationKind::Context.span(69..69).label(": i32")), ), ]; let expected_ascii = str![[r#" error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> $DIR/method-on-ambiguous-numeric-type.rs:37:9 | 37 | bar.pow(2); | ^^^ | help: you must specify a type for this binding, like `i32` --> $DIR/auxiliary/macro-in-other-crate.rs:3:35 | 3 | ($ident:ident) => { let $ident = 42; } | - : i32 "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` ╭▸ $DIR/method-on-ambiguous-numeric-type.rs:37:9 │ 37 │ bar.pow(2); │ ━━━ ╰╴ help: you must specify a type for this binding, like `i32` ╭▸ $DIR/auxiliary/macro-in-other-crate.rs:3:35 │ 3 │ ($ident:ident) => { let $ident = 42; } ╰╴ ─ : i32 "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn issue_42234_unknown_receiver_type() { // tests/ui/span/issue-42234-unknown-receiver-type.rs let source = r#"//@ revisions: full generic_arg #![cfg_attr(generic_arg, feature(generic_arg_infer))] // When the type of a method call's receiver is unknown, the span should point // to the receiver (and not the entire call, as was previously the case before // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { let x: Option<_> = None; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { data.iter() .sum::<_>() //~ ERROR type annotations needed .to_string() } fn main() {} "#; let input = &[Level::ERROR .primary_title("type annotations needed") .id("E0282") .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-42234-unknown-receiver-type.rs") .annotation(AnnotationKind::Primary.span(536..539).label( "cannot infer type of the type parameter `S` declared on the method `sum`", )), )]; let expected_ascii = str![[r#" error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 | 15 | .sum::<_>() //~ ERROR type annotations needed | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0282]: type annotations needed ╭▸ $DIR/issue-42234-unknown-receiver-type.rs:15:10 │ 15 │ .sum::<_>() //~ ERROR type annotations needed ╰╴ ━━━ cannot infer type of the type parameter `S` declared on the method `sum` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn pattern_usefulness_empty_match() { // tests/ui/pattern/usefulness/empty-match.rs let source = r##"//@ revisions: normal exhaustive_patterns // // This tests a match with no arms on various types. #![feature(never_type)] #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![deny(unreachable_patterns)] fn nonempty(arrayN_of_empty: [!; N]) { macro_rules! match_no_arms { ($e:expr) => { match $e {} }; } macro_rules! match_guarded_arm { ($e:expr) => { match $e { _ if false => {} } }; } struct NonEmptyStruct1; struct NonEmptyStruct2(bool); union NonEmptyUnion1 { foo: (), } union NonEmptyUnion2 { foo: (), bar: !, } enum NonEmptyEnum1 { Foo(bool), } enum NonEmptyEnum2 { Foo(bool), Bar, } enum NonEmptyEnum5 { V1, V2, V3, V4, V5, } let array0_of_empty: [!; 0] = []; match_no_arms!(0u8); //~ ERROR type `u8` is non-empty match_no_arms!(0i8); //~ ERROR type `i8` is non-empty match_no_arms!(0usize); //~ ERROR type `usize` is non-empty match_no_arms!(0isize); //~ ERROR type `isize` is non-empty match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered match_no_arms!(array0_of_empty); //~ ERROR type `[!; 0]` is non-empty match_no_arms!(arrayN_of_empty); //~ ERROR type `[!; N]` is non-empty match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered match_guarded_arm!(0usize); //~ ERROR `0_usize..` not covered match_guarded_arm!(0isize); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered match_guarded_arm!(array0_of_empty); //~ ERROR `[]` not covered match_guarded_arm!(arrayN_of_empty); //~ ERROR `[]` not covered } fn main() {} "##; let input = &[Level::ERROR .primary_title( "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" ) .id("E0004") .element( Snippet::source(source) .line_start(1) .path("$DIR/empty-match.rs") .annotation( AnnotationKind::Primary .span(2911..2928) .label("patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered") ), ), Level::NOTE.secondary_title("`NonEmptyEnum5` defined here") .element( Snippet::source(source) .line_start(1) .path("$DIR/empty-match.rs") .annotation(AnnotationKind::Primary.span(818..831)) .annotation(AnnotationKind::Context.span(842..844).label("not covered")) .annotation(AnnotationKind::Context.span(854..856).label("not covered")) .annotation(AnnotationKind::Context.span(866..868).label("not covered")) .annotation(AnnotationKind::Context.span(878..880).label("not covered")) .annotation(AnnotationKind::Context.span(890..892).label("not covered")) ) .element(Level::NOTE.message("the matched value is of type `NonEmptyEnum5`")) .element(Level::NOTE.message("match arms with guards don't count towards exhaustivity") ), Level::HELP .secondary_title("ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms") .element( Snippet::source(source) .line_start(1) .path("$DIR/empty-match.rs") .annotation(AnnotationKind::Context.span(485..485).label(",\n _ => todo!()")) ) ]; let expected_ascii = str![[r#" error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 | 71 | match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:38:10 | 38 | enum NonEmptyEnum5 { | ^^^^^^^^^^^^^ 39 | V1, | -- not covered 40 | V2, | -- not covered 41 | V3, | -- not covered 42 | V4, | -- not covered 43 | V5, | -- not covered = note: the matched value is of type `NonEmptyEnum5` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms --> $DIR/empty-match.rs:17:33 | 17 | _ if false => {} | - , _ => todo!() "#]]; let renderer = Renderer::plain().term_width(annotate_snippets::renderer::DEFAULT_TERM_WIDTH + 4); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered ╭▸ $DIR/empty-match.rs:71:24 │ 71 │ match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered │ ━━━━━━━━━━━━━━━━━ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered ╰╴ note: `NonEmptyEnum5` defined here ╭▸ $DIR/empty-match.rs:38:10 │ 38 │ enum NonEmptyEnum5 { │ ━━━━━━━━━━━━━ 39 │ V1, │ ── not covered 40 │ V2, │ ── not covered 41 │ V3, │ ── not covered 42 │ V4, │ ── not covered 43 │ V5, │ ── not covered ├ note: the matched value is of type `NonEmptyEnum5` ╰ note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms ╭▸ $DIR/empty-match.rs:17:33 │ 17 │ _ if false => {} ╰╴ ─ , _ => todo!() "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn object_fail() { // tests/ui/traits/alias/object-fail.rs let source = r#"#![feature(trait_alias)] trait EqAlias = Eq; trait IteratorAlias = Iterator; fn main() { let _: &dyn EqAlias = &123; //~^ ERROR the trait alias `EqAlias` is not dyn compatible [E0038] let _: &dyn IteratorAlias = &vec![123].into_iter(); //~^ ERROR must be specified } "#; let input = &[Level::ERROR .primary_title("the trait alias `EqAlias` is not dyn compatible") .id("E0038").element( Snippet::source(source) .line_start(1) .path("$DIR/object-fail.rs") .annotation( AnnotationKind::Primary .span(107..114) .label("`EqAlias` is not dyn compatible"), ), ), Level::NOTE .secondary_title("for a trait to be dyn compatible it needs to allow building a vtable\nfor more information, visit ") .element( Origin::path("$SRC_DIR/core/src/cmp.rs") .line(334) .char_column(14) ) .element(Padding) .element(Level::NOTE.message("...because it uses `Self` as a type parameter")) .element( Snippet::source(source) .line_start(1) .path("$DIR/object-fail.rs") .annotation( AnnotationKind::Context .span(32..39) .label("this trait is not dyn compatible..."), ), )]; let expected_ascii = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible --> $DIR/object-fail.rs:7:17 | 7 | let _: &dyn EqAlias = &123; | ^^^^^^^ `EqAlias` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit --> $SRC_DIR/core/src/cmp.rs:334:14 | = note: ...because it uses `Self` as a type parameter | ::: $DIR/object-fail.rs:3:7 | 3 | trait EqAlias = Eq; | ------- this trait is not dyn compatible... "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible ╭▸ $DIR/object-fail.rs:7:17 │ 7 │ let _: &dyn EqAlias = &123; │ ━━━━━━━ `EqAlias` is not dyn compatible ╰╴ note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit ╭▸ $SRC_DIR/core/src/cmp.rs:334:14 │ ├ note: ...because it uses `Self` as a type parameter │ ⸬ $DIR/object-fail.rs:3:7 │ 3 │ trait EqAlias = Eq; ╰╴ ─────── this trait is not dyn compatible... "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_span_shortest() { // tests/ui/diagnostic-width/long-span.rs let source = r#" const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 main() {} "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0038") .element( Snippet::source(source) .path("$DIR/long-span.rs") .annotation( AnnotationKind::Primary .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), )]; let expected_ascii = str![[r#" error[E0038]: mismatched types --> $DIR/long-span.rs:2:15 | 2 | ... = [0, 0...0, 0]; | ^^^^^...^^^^^ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = Renderer::plain().term_width(8); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0…0, 0]; ╰╴ ━━━━━…━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_span_short() { // tests/ui/diagnostic-width/long-span.rs let source = r#" const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 main() {} "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0038") .element( Snippet::source(source) .path("$DIR/long-span.rs") .annotation( AnnotationKind::Primary .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), )]; let expected_ascii = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0…0, 0]; ╰╴ ━━━━━…━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = Renderer::plain() .term_width(12) .decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0…0, 0]; ╰╴ ━━━━━…━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_span_long() { // tests/ui/diagnostic-width/long-span.rs let source = r#" const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 main() {} "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0038") .element( Snippet::source(source) .path("$DIR/long-span.rs") .annotation( AnnotationKind::Primary .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), )]; let expected_ascii = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0, 0, 0, 0, 0, 0, 0, …, 0, 0, 0, 0, 0, 0, 0, 0]; ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━…━━━━━━━━━━━━━━━━━━━━━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = Renderer::plain() .term_width(80) .decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0, 0, 0, 0, 0, 0, 0, …, 0, 0, 0, 0, 0, 0, 0, 0]; ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━…━━━━━━━━━━━━━━━━━━━━━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn long_span_longest() { // tests/ui/diagnostic-width/long-span.rs let source = r#" const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 main() {} "#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0038") .element( Snippet::source(source) .path("$DIR/long-span.rs") .annotation( AnnotationKind::Primary .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), )]; let expected_ascii = str![[r#" error[E0038]: mismatched types --> $DIR/long-span.rs:2:15 | 2 | ... = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = Renderer::plain().term_width(120); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 │ 2 │ …u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━…━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ expected `u8`, found `[{integer}; 1680]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn lint_map_unit_fn() { // tests/ui/lint/lint_map_unit_fn.rs let source = r#"#![deny(map_unit_fn)] fn foo(items: &mut Vec) { items.sort(); } fn main() { let mut x: Vec> = vec![vec![0, 2, 1], vec![5, 4, 3]]; x.iter_mut().map(foo); //~^ ERROR `Iterator::map` call that discard the iterator's values x.iter_mut().map(|items| { //~^ ERROR `Iterator::map` call that discard the iterator's values items.sort(); }); let f = |items: &mut Vec| { items.sort(); }; x.iter_mut().map(f); //~^ ERROR `Iterator::map` call that discard the iterator's values } "#; let input = &[Level::ERROR .primary_title("`Iterator::map` call that discard the iterator's values") .element( Snippet::source(source) .path("$DIR/lint_map_unit_fn.rs") .annotation(AnnotationKind::Context.span(271..278).label( "this function returns `()`, which is likely not what you wanted", )) .annotation( AnnotationKind::Context .span(271..379) .label("called `Iterator::map` with callable that returns `()`"), ) .annotation( AnnotationKind::Context .span(267..380) .label("after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items") ) .annotation(AnnotationKind::Primary.span(267..380)), ) .element( Level::NOTE.message("`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated")), Level::HELP.secondary_title("you might have meant to use `Iterator::for_each`") .element( Snippet::source(source) .path("$DIR/lint_map_unit_fn.rs") .patch(Patch::new(267..270, r#"for_each"#)), )]; let expected_ascii = str![[r#" error: `Iterator::map` call that discard the iterator's values --> $DIR/lint_map_unit_fn.rs:11:18 | 11 | x.iter_mut().map(|items| { | ^ ------- | | | | ____________________|___this function returns `()`, which is likely not what you wanted | | __________________| | | | 12 | | | //~^ ERROR `Iterator::map` call that discard the iterator's values 13 | | | items.sort(); 14 | | | }); | | | -^ after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items | | |_____|| | |_______| | called `Iterator::map` with callable that returns `()` | = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated help: you might have meant to use `Iterator::for_each` | 11 - x.iter_mut().map(|items| { 11 + x.iter_mut().for_each(|items| { | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: `Iterator::map` call that discard the iterator's values ╭▸ $DIR/lint_map_unit_fn.rs:11:18 │ 11 │ x.iter_mut().map(|items| { │ ╿ │────── │ │ │ │ ┌────────────────────│───this function returns `()`, which is likely not what you wanted │ │ ┏━━━━━━━━━━━━━━━━━━┙ │ │ ┃ 12 │ │ ┃ //~^ ERROR `Iterator::map` call that discard the iterator's values 13 │ │ ┃ items.sort(); 14 │ │ ┃ }); │ │ ┃ │╿ after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items │ │ ┗━━━━━││ │ └───────┤ │ called `Iterator::map` with callable that returns `()` │ ╰ note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated help: you might have meant to use `Iterator::for_each` ╭╴ 11 - x.iter_mut().map(|items| { 11 + x.iter_mut().for_each(|items| { ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn bad_char_literals() { // tests/ui/parser/bad-char-literals.rs let source = r#"// ignore-tidy-cr // ignore-tidy-tab fn main() { // these literals are just silly. '''; //~^ ERROR: character constant must be escaped: `'` // note that this is a literal "\n" byte ' '; //~^^ ERROR: character constant must be escaped: `\n` // note that this is a literal "\r" byte ; //~ ERROR: character constant must be escaped: `\r` // note that this is a literal NULL '--'; //~ ERROR: character literal may only contain one codepoint // note that this is a literal tab character here ' '; //~^ ERROR: character constant must be escaped: `\t` } "#; let input = &[ Level::ERROR .primary_title("character constant must be escaped: `\\n`") .element( Snippet::source(source) .path("$DIR/bad-char-literals.rs") .annotation(AnnotationKind::Primary.span(204..205)), ), Level::HELP.secondary_title("escape the character").element( Snippet::source(source) .path("$DIR/bad-char-literals.rs") .line_start(1) .patch(Patch::new(204..205, r#"\n"#)), ), ]; let expected_ascii = str![[r#" error: character constant must be escaped: `/n` --> $DIR/bad-char-literals.rs:10:6 | 10 | ' | ^ | help: escape the character | 10 | '/n | ++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: character constant must be escaped: `/n` ╭▸ $DIR/bad-char-literals.rs:10:6 │ 10 │ ' │ ━ ╰╴ help: escape the character ╭╴ 10 │ '/n ╰╴ ++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unclosed_1() { // tests/ui/frontmatter/unclosed-1.rs let source = r#"----cargo //~^ ERROR: unclosed frontmatter // This test checks that the #! characters can help us recover a frontmatter // close. There should not be a "missing `main` function" error as the rest // are properly parsed. #![feature(frontmatter)] fn main() {} "#; let input = &[ Level::ERROR.primary_title("unclosed frontmatter").element( Snippet::source(source) .path("$DIR/unclosed-1.rs") .annotation(AnnotationKind::Primary.span(0..221)), ), Level::NOTE .secondary_title("frontmatter opening here was not closed") .element( Snippet::source(source) .path("$DIR/unclosed-1.rs") .annotation(AnnotationKind::Primary.span(0..4)), ), ]; let expected_ascii = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-1.rs:1:1 | 1 | / ----cargo ... | 6 | | // are properly parsed. | |_______________________^ | note: frontmatter opening here was not closed --> $DIR/unclosed-1.rs:1:1 | 1 | ----cargo | ^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unclosed frontmatter ╭▸ $DIR/unclosed-1.rs:1:1 │ 1 │ ┏ ----cargo ┆ ┇ 6 │ ┃ // are properly parsed. │ ┗━━━━━━━━━━━━━━━━━━━━━━━┛ ╰╴ note: frontmatter opening here was not closed ╭▸ $DIR/unclosed-1.rs:1:1 │ 1 │ ----cargo ╰╴━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unclosed_2() { // tests/ui/frontmatter/unclosed-2.rs let source = r#"----cargo //~^ ERROR: unclosed frontmatter //~| ERROR: frontmatters are experimental //@ compile-flags: --crate-type lib // Leading whitespace on the feature line prevents recovery. However // the dashes quoted will not be used for recovery and the entire file // should be treated as within the frontmatter block. #![feature(frontmatter)] fn foo() -> &str { "----" } "#; let input = &[ Level::ERROR.primary_title("unclosed frontmatter").element( Snippet::source(source) .path("$DIR/unclosed-2.rs") .annotation(AnnotationKind::Primary.span(0..377)), ), Level::NOTE .secondary_title("frontmatter opening here was not closed") .element( Snippet::source(source) .path("$DIR/unclosed-2.rs") .annotation(AnnotationKind::Primary.span(0..4)), ), ]; let expected_ascii = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-2.rs:1:1 | 1 | / ----cargo ... | 14 | | "----" 15 | | } | |__^ | note: frontmatter opening here was not closed --> $DIR/unclosed-2.rs:1:1 | 1 | ----cargo | ^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unclosed frontmatter ╭▸ $DIR/unclosed-2.rs:1:1 │ 1 │ ┏ ----cargo ┆ ┇ 14 │ ┃ "----" 15 │ ┃ } │ ┗━━┛ ╰╴ note: frontmatter opening here was not closed ╭▸ $DIR/unclosed-2.rs:1:1 │ 1 │ ----cargo ╰╴━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unclosed_3() { // tests/ui/frontmatter/unclosed-3.rs let source = r#"----cargo //~^ ERROR: frontmatter close does not match the opening //@ compile-flags: --crate-type lib // Unfortunate recovery situation. Not really preventable with improving the // recovery strategy, but this type of code is rare enough already. #![feature(frontmatter)] fn foo(x: i32) -> i32 { ---x //~^ ERROR: invalid preceding whitespace for frontmatter close //~| ERROR: extra characters after frontmatter close are not allowed } //~^ ERROR: unexpected closing delimiter: `}` "#; let input = &[ Level::ERROR .primary_title("invalid preceding whitespace for frontmatter close") .element( Snippet::source(source) .path("$DIR/unclosed-3.rs") .annotation(AnnotationKind::Primary.span(302..310)), ), Level::NOTE .secondary_title("frontmatter close should not be preceded by whitespace") .element( Snippet::source(source) .path("$DIR/unclosed-3.rs") .annotation(AnnotationKind::Primary.span(302..306)), ), ]; let expected_ascii = str![[r#" error: invalid preceding whitespace for frontmatter close --> $DIR/unclosed-3.rs:12:1 | 12 | ---x | ^^^^^^^^ | note: frontmatter close should not be preceded by whitespace --> $DIR/unclosed-3.rs:12:1 | 12 | ---x | ^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: invalid preceding whitespace for frontmatter close ╭▸ $DIR/unclosed-3.rs:12:1 │ 12 │ ---x │ ━━━━━━━━ ╰╴ note: frontmatter close should not be preceded by whitespace ╭▸ $DIR/unclosed-3.rs:12:1 │ 12 │ ---x ╰╴━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unclosed_4() { // tests/ui/frontmatter/unclosed-4.rs let source = r#"----cargo //~^ ERROR: unclosed frontmatter //! Similarly, a module-level content should allow for recovery as well (as //! per unclosed-1.rs) #![feature(frontmatter)] fn main() {} "#; let input = &[ Level::ERROR.primary_title("unclosed frontmatter").element( Snippet::source(source) .path("$DIR/unclosed-4.rs") .annotation(AnnotationKind::Primary.span(0..43)), ), Level::NOTE .secondary_title("frontmatter opening here was not closed") .element( Snippet::source(source) .path("$DIR/unclosed-4.rs") .annotation(AnnotationKind::Primary.span(0..4)), ), ]; let expected_ascii = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-4.rs:1:1 | 1 | / ----cargo 2 | | //~^ ERROR: unclosed frontmatter | |________________________________^ | note: frontmatter opening here was not closed --> $DIR/unclosed-4.rs:1:1 | 1 | ----cargo | ^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unclosed frontmatter ╭▸ $DIR/unclosed-4.rs:1:1 │ 1 │ ┏ ----cargo 2 │ ┃ //~^ ERROR: unclosed frontmatter │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ╰╴ note: frontmatter opening here was not closed ╭▸ $DIR/unclosed-4.rs:1:1 │ 1 │ ----cargo ╰╴━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unclosed_5() { // tests/ui/frontmatter/unclosed-5.rs let source = r#"----cargo //~^ ERROR: unclosed frontmatter //~| ERROR: frontmatters are experimental // Similarly, a use statement should allow for recovery as well (as // per unclosed-1.rs) use std::env; fn main() {} "#; let input = &[ Level::ERROR.primary_title("unclosed frontmatter").element( Snippet::source(source) .path("$DIR/unclosed-5.rs") .annotation(AnnotationKind::Primary.span(0..176)), ), Level::NOTE .secondary_title("frontmatter opening here was not closed") .element( Snippet::source(source) .path("$DIR/unclosed-5.rs") .annotation(AnnotationKind::Primary.span(0..4)), ), ]; let expected_ascii = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-5.rs:1:1 | 1 | / ----cargo ... | 6 | | // per unclosed-1.rs) | |_____________________^ | note: frontmatter opening here was not closed --> $DIR/unclosed-5.rs:1:1 | 1 | ----cargo | ^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: unclosed frontmatter ╭▸ $DIR/unclosed-5.rs:1:1 │ 1 │ ┏ ----cargo ┆ ┇ 6 │ ┃ // per unclosed-1.rs) │ ┗━━━━━━━━━━━━━━━━━━━━━┛ ╰╴ note: frontmatter opening here was not closed ╭▸ $DIR/unclosed-5.rs:1:1 │ 1 │ ----cargo ╰╴━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn pat_tuple_field_count_cross() { // tests/ui/pattern/pat-tuple-field-count-cross.stderr let source = r#"//@ aux-build:declarations-for-tuple-field-count-errors.rs extern crate declarations_for_tuple_field_count_errors; use declarations_for_tuple_field_count_errors::*; fn main() { match Z0 { Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` } match Z1() { Z1 => {} //~ ERROR match bindings cannot shadow tuple structs Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields } match S(1, 2, 3) { S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields } match M(1, 2, 3) { M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields } match E1::Z0 { E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` E1::Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` } match E1::Z1() { E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` E1::Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields } match E1::S(1, 2, 3) { E1::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields E1::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields E1::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields E1::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields } match E2::S(1, 2, 3) { E2::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields E2::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields E2::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields E2::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields } match E2::M(1, 2, 3) { E2::M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields E2::M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields E2::M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields E2::M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields } } "#; let source1 = r#"pub struct Z0; pub struct Z1(); pub struct S(pub u8, pub u8, pub u8); pub struct M( pub u8, pub u8, pub u8, ); pub enum E1 { Z0, Z1(), S(u8, u8, u8) } pub enum E2 { S(u8, u8, u8), M( u8, u8, u8, ), } "#; let input = &[ Level::ERROR .primary_title( "expected unit struct, unit variant or constant, found tuple variant `E1::Z1`", ) .id(r#"E0532"#) .element( Snippet::source(source) .path("$DIR/pat-tuple-field-count-cross.rs") .annotation(AnnotationKind::Primary.span(1760..1766)), ) .element( Snippet::source(source1) .path("$DIR/auxiliary/declarations-for-tuple-field-count-errors.rs") .annotation( AnnotationKind::Context .span(143..145) .label("`E1::Z1` defined here"), ) .annotation( AnnotationKind::Context .span(139..141) .label("similarly named unit variant `Z0` defined here"), ), ), Level::HELP .secondary_title("use the tuple variant pattern syntax instead") .element( Snippet::source(source) .path("$DIR/pat-tuple-field-count-cross.rs") .patch(Patch::new(1760..1766, r#"E1::Z1()"#)), ), Level::HELP .secondary_title("a unit variant with a similar name exists") .element( Snippet::source(source) .path("$DIR/pat-tuple-field-count-cross.rs") .patch(Patch::new(1764..1766, r#"Z0"#)), ), ]; let expected_ascii = str![[r#" error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1` --> $DIR/pat-tuple-field-count-cross.rs:35:9 | 35 | E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` | ^^^^^^ | ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 | 11 | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } | -- -- `E1::Z1` defined here | | | similarly named unit variant `Z0` defined here | help: use the tuple variant pattern syntax instead | 35 | E1::Z1() => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` | ++ help: a unit variant with a similar name exists | 35 - E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` 35 + E1::Z0 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1` ╭▸ $DIR/pat-tuple-field-count-cross.rs:35:9 │ 35 │ E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` │ ━━━━━━ │ ⸬ $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 │ 11 │ pub enum E1 { Z0, Z1(), S(u8, u8, u8) } │ ┬─ ── `E1::Z1` defined here │ │ │ similarly named unit variant `Z0` defined here ╰╴ help: use the tuple variant pattern syntax instead ╭╴ 35 │ E1::Z1() => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` ╰╴ ++ help: a unit variant with a similar name exists ╭╴ 35 - E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` 35 + E1::Z0 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unterminated_nested_comment() { // tests/ui/lexer/unterminated-nested-comment.rs let source = r#"/* //~ ERROR E0758 /* */ /* */ "#; let input = &[Level::ERROR .primary_title("unterminated block comment") .id("E0758") .element( Snippet::source(source) .path("$DIR/unterminated-nested-comment.rs") .annotation( AnnotationKind::Context .span(0..2) .label("unterminated block comment"), ) .annotation(AnnotationKind::Context.span(25..27).label( "...as last nested comment starts here, maybe you want to close this instead?", )) .annotation( AnnotationKind::Context .span(28..30) .label("...and last nested comment terminates here."), ) .annotation(AnnotationKind::Primary.span(0..31)), )]; let expected_ascii = str![[r#" error[E0758]: unterminated block comment --> $DIR/unterminated-nested-comment.rs:1:1 | 1 | /* //~ ERROR E0758 | ^- | | | _unterminated block comment | | 2 | | /* */ 3 | | /* | | -- | | | | | ...as last nested comment starts here, maybe you want to close this instead? 4 | | */ | |_--^ | | | ...and last nested comment terminates here. "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0758]: unterminated block comment ╭▸ $DIR/unterminated-nested-comment.rs:1:1 │ 1 │ /* //~ ERROR E0758 │ ╿─ │ │ │ ┏━unterminated block comment │ ┃ 2 │ ┃ /* */ 3 │ ┃ /* │ ┃ ┬─ │ ┃ │ │ ┃ ...as last nested comment starts here, maybe you want to close this instead? 4 │ ┃ */ │ ┗━┬─┛ │ │ ╰╴ ...and last nested comment terminates here. "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn mismatched_types1() { // tests/ui/include-macros/mismatched-types.rs let file_txt_source = r#""#; let rust_source = r#"fn main() { let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(file_txt_source) .line_start(3) .path("$DIR/file.txt") .annotation( AnnotationKind::Primary .span(0..0) .label("expected `&[u8]`, found `&str`"), ), ) .element( Snippet::source(rust_source) .path("$DIR/mismatched-types.rs") .annotation( AnnotationKind::Context .span(23..28) .label("expected due to this"), ) .annotation( AnnotationKind::Context .span(31..55) .label("in this macro invocation"), ), ) .element( Level::NOTE.message("expected reference `&[u8]`\n found reference `&'static str`"), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/file.txt:3:1 | 3 | | ^ expected `&[u8]`, found `&str` | ::: $DIR/mismatched-types.rs:2:12 | 2 | let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types | ----- ------------------------ in this macro invocation | | | expected due to this | = note: expected reference `&[u8]` found reference `&'static str` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/file.txt:3:1 │ 3 │ │ ━ expected `&[u8]`, found `&str` │ ⸬ $DIR/mismatched-types.rs:2:12 │ 2 │ let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types │ ┬──── ──────────────────────── in this macro invocation │ │ │ expected due to this │ ╰ note: expected reference `&[u8]` found reference `&'static str` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn mismatched_types2() { // tests/ui/include-macros/mismatched-types.rs let source = r#"fn main() { let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; let input = &[Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/mismatched-types.rs") .annotation( AnnotationKind::Primary .span(105..131) .label("expected `&str`, found `&[u8; 0]`"), ) .annotation( AnnotationKind::Context .span(98..102) .label("expected due to this"), ), ) .element( Level::NOTE.message("expected reference `&str`\n found reference `&'static [u8; 0]`"), )]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/mismatched-types.rs:3:19 | 3 | let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]` | | | expected due to this | = note: expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/mismatched-types.rs:3:19 │ 3 │ let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types │ ┬─── ━━━━━━━━━━━━━━━━━━━━━━━━━━ expected `&str`, found `&[u8; 0]` │ │ │ expected due to this │ ╰ note: expected reference `&str` found reference `&'static [u8; 0]` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn short_error_format1() { // tests/ui/short-error-format.rs let source = r#"//@ compile-flags: --error-format=short fn foo(_: u32) {} fn main() { foo("Bonjour".to_owned()); let x = 0u32; x.salut(); } "#; let input = &[ Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/short-error-format.rs") .annotation( AnnotationKind::Primary .span(80..100) .label("expected `u32`, found `String`"), ) .annotation( AnnotationKind::Context .span(76..79) .label("arguments to this function are incorrect"), ), ), Level::NOTE .secondary_title("function defined here") .element( Snippet::source(source) .path("$DIR/short-error-format.rs") .annotation(AnnotationKind::Context.span(48..54).label("")) .annotation(AnnotationKind::Primary.span(44..47)), ), ]; let expected_ascii = str![[r#" $DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String` "#]]; let renderer = Renderer::plain().short_message(true); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![ "$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String`" ]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn short_error_format2() { // tests/ui/short-error-format.rs let source = r#"//@ compile-flags: --error-format=short fn foo(_: u32) {} fn main() { foo("Bonjour".to_owned()); let x = 0u32; x.salut(); } "#; let input = &[Level::ERROR .primary_title("no method named `salut` found for type `u32` in the current scope") .id("E0599") .element( Snippet::source(source) .path("$DIR/short-error-format.rs") .annotation( AnnotationKind::Primary .span(127..132) .label("method not found in `u32`"), ), )]; let expected_ascii = str![[r#" $DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32` "#]]; let renderer = Renderer::plain().short_message(true); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![ "$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32`" ]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn rustdoc_ui_diagnostic_width() { // tests/rustdoc-ui/diagnostic-width.rs let source_0 = r#"//@ compile-flags: --diagnostic-width=10 #![deny(rustdoc::bare_urls)] /// This is a long line that contains a http://link.com pub struct Foo; //~^ ERROR "#; let source_1 = r#"/// This is a long line that contains a http://link.com "#; let input = &[ Level::ERROR .primary_title("this URL is not a hyperlink") .element( Snippet::source(source_0) .path("$DIR/diagnostic-width.rs") .annotation(AnnotationKind::Primary.span(111..126)), ) .element( Level::NOTE.message("bare URLs are not automatically turned into clickable links"), ), Level::NOTE .secondary_title("the lint level is defined here") .element( Snippet::source(source_0) .path("$DIR/diagnostic-width.rs") .annotation(AnnotationKind::Primary.span(49..67)), ), Level::HELP .secondary_title("use an automatic link instead") .element( Snippet::source(source_1) .path("$DIR/diagnostic-width.rs") .line_start(4) .patch(Patch::new(40..40, "<")) .patch(Patch::new(55..55, ">")), ), ]; let expected_ascii = str![[r#" error: this URL is not a hyperlink --> $DIR/diagnostic-width.rs:4:41 | 4 | ... a http:...k.com | ^^^^^...^^^^^ | = note: bare URLs are not automatically turned into clickable links note: the lint level is defined here --> $DIR/diagnostic-width.rs:2:9 | 2 | ...ny(rustd..._urls)] | ^^^^^...^^^^^ help: use an automatic link instead | 4 | /// This is a long line that contains a | + + "#]]; let renderer = Renderer::plain().term_width(10); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: this URL is not a hyperlink ╭▸ $DIR/diagnostic-width.rs:4:41 │ 4 │ …ns a http:…k.com │ ━━━━━…━━━━━ │ ╰ note: bare URLs are not automatically turned into clickable links note: the lint level is defined here ╭▸ $DIR/diagnostic-width.rs:2:9 │ 2 │ …deny(rustd…_urls)] ╰╴ ━━━━━…━━━━━ help: use an automatic link instead ╭╴ 4 │ /// This is a long line that contains a ╰╴ + + "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn array_into_iter() { let source1 = r#"#![allow(unused)] fn main() { [1, 2, 3].into_iter().for_each(|n| { *n; }); } "#; let source2 = r#"[1, 2, 3].into_iter().for_each(|n| { *n; }); "#; let long_title1 = "this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021"; let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; let input = &[ Level::WARNING .primary_title(long_title1) .element( Snippet::source(source1) .path("lint_example.rs") .annotation(AnnotationKind::Primary.span(40..49)), ) .element(Level::WARNING.message("this changes meaning in Rust 2021")) .element(Level::NOTE.message(long_title2)) .element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")), Level::HELP .secondary_title("use `.iter()` instead of `.into_iter()` to avoid ambiguity") .element( Snippet::source(source2) .path("lint_example.rs") .line_start(3) .patch(Patch::new(10..19, "iter")), ), Level::HELP.secondary_title(long_title3).element( Snippet::source(source2) .path("lint_example.rs") .line_start(3) .patch(Patch::new(0..0, "IntoIterator::into_iter(")) .patch(Patch::new(9..21, ")")), ), ]; let expected_ascii = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 --> lint_example.rs:3:11 | 3 | [1, 2, 3].into_iter().for_each(|n| { *n; }); | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see = note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); | help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + IntoIterator::into_iter([1, 2, 3]).for_each(|n| { *n; }); | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 ╭▸ lint_example.rs:3:11 │ 3 │ [1, 2, 3].into_iter().for_each(|n| { *n; }); │ ━━━━━━━━━ │ ├ warning: this changes meaning in Rust 2021 ├ note: for more information, see ╰ note: `#[warn(array_into_iter)]` on by default help: use `.iter()` instead of `.into_iter()` to avoid ambiguity ╭╴ 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + [1, 2, 3].iter().for_each(|n| { *n; }); ╰╴ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value ╭╴ 3 - [1, 2, 3].into_iter().for_each(|n| { *n; }); 3 + IntoIterator::into_iter([1, 2, 3]).for_each(|n| { *n; }); ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn autoderef_box_no_add() { // tests/ui/autoref-autoderef/autoderef-box-no-add.rs let source = r#"//! Tests that auto-dereferencing does not allow addition of `Box` values. //! //! This test ensures that `Box` fields in structs (`Clam` and `Fish`) are not //! automatically dereferenced to `isize` during addition operations, as `Box` //! does not implement the `Add` trait. struct Clam { x: Box, y: Box, } struct Fish { a: Box, } fn main() { let a: Clam = Clam { x: Box::new(1), y: Box::new(2), }; let b: Clam = Clam { x: Box::new(10), y: Box::new(20), }; let z: isize = a.x + b.y; //~^ ERROR cannot add `Box` to `Box` println!("{}", z); assert_eq!(z, 21); let forty: Fish = Fish { a: Box::new(40) }; let two: Fish = Fish { a: Box::new(2) }; let answer: isize = forty.a + two.a; //~^ ERROR cannot add `Box` to `Box` println!("{}", answer); assert_eq!(answer, 42); } "#; let input = &[ Level::ERROR .primary_title("cannot add `Box` to `Box`") .id("E0369") .element( Snippet::source(source) .path("$DIR/autoderef-box-no-add.rs") .annotation(AnnotationKind::Context.span(583..586).label("Box")) .annotation(AnnotationKind::Context.span(589..592).label("Box")) .annotation(AnnotationKind::Primary.span(587..588)), ), Level::NOTE .secondary_title("the foreign item type `Box` doesn't implement `Add`") .element( Origin::path("$SRC_DIR/alloc/src/boxed.rs") .line(231) .char_column(0), ) .element( Origin::path("$SRC_DIR/alloc/src/boxed.rs") .line(234) .char_column(1), ) .element(Padding) .element(Level::NOTE.message("not implement `Add`")), ]; let expected_ascii = str![[r#" error[E0369]: cannot add `Box` to `Box` --> $DIR/autoderef-box-no-add.rs:25:24 | 25 | let z: isize = a.x + b.y; | --- ^ --- Box | | | Box | note: the foreign item type `Box` doesn't implement `Add` --> $SRC_DIR/alloc/src/boxed.rs:231:0 ::: $SRC_DIR/alloc/src/boxed.rs:234:1 | = note: not implement `Add` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0369]: cannot add `Box` to `Box` ╭▸ $DIR/autoderef-box-no-add.rs:25:24 │ 25 │ let z: isize = a.x + b.y; │ ┬── ━ ─── Box │ │ │ Box ╰╴ note: the foreign item type `Box` doesn't implement `Add` ╭▸ $SRC_DIR/alloc/src/boxed.rs:231:0 ⸬ $SRC_DIR/alloc/src/boxed.rs:234:1 │ ╰ note: not implement `Add` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn dont_project_to_specializable_projection() { // tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs let source = r#"//@ edition: 2021 //@ known-bug: #108309 #![feature(min_specialization)] struct MyStruct; trait MyTrait { async fn foo(_: T) -> &'static str; } impl MyTrait for MyStruct { default async fn foo(_: T) -> &'static str { "default" } } impl MyTrait for MyStruct { async fn foo(_: i32) -> &'static str { "specialized" } } async fn async_main() { assert_eq!(MyStruct::foo(42).await, "specialized"); assert_eq!(indirection(42).await, "specialized"); } async fn indirection(x: T) -> &'static str { //explicit type coercion is currently necessary // because of https://github.com/rust-lang/rust/issues/67918 >::foo(x).await } // ------------------------------------------------------------------------- // // Implementation Details Below... use std::pin::{pin, Pin}; use std::task::*; fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { Poll::Pending => {} Poll::Ready(()) => break, } } } "#; let title_0 = "no method named `poll` found for struct `Pin<&mut impl Future>` in the current scope"; let title_1 = "trait `Future` which provides `poll` is implemented but not in scope; perhaps you want to import it"; let input = &[ Level::ERROR.primary_title(title_0).id("E0599").element( Snippet::source(source) .path("$DIR/dont-project-to-specializable-projection.rs") .annotation( AnnotationKind::Primary .span(1071..1075) .label("method not found in `Pin<&mut impl Future>`"), ), ), Group::with_level(Level::ERROR) .element( Origin::path("$SRC_DIR/core/src/future/future.rs") .line(104) .char_column(7), ) .element(Padding) .element( Level::NOTE.message( "the method is available for `Pin<&mut impl Future>` here", ), ) .element(Padding) .element( Level::HELP.message("items from traits can only be used if the trait is in scope"), ), Level::HELP.secondary_title(title_1).element( Snippet::source("struct MyStruct;\n") .path("$DIR/dont-project-to-specializable-projection.rs") .line_start(6) .patch(Patch::new( 0..0, r#"use std::future::Future; "#, )), ), ]; let expected_ascii = str![[r#" error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future>` in the current scope --> $DIR/dont-project-to-specializable-projection.rs:48:28 | 48 | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future>` | --> $SRC_DIR/core/src/future/future.rs:104:7 | = note: the method is available for `Pin<&mut impl Future>` here | = help: items from traits can only be used if the trait is in scope help: trait `Future` which provides `poll` is implemented but not in scope; perhaps you want to import it | 6 + use std::future::Future; | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future>` in the current scope ╭▸ $DIR/dont-project-to-specializable-projection.rs:48:28 │ 48 │ match fut.as_mut().poll(ctx) { │ ━━━━ method not found in `Pin<&mut impl Future>` ╰╴ ╭▸ $SRC_DIR/core/src/future/future.rs:104:7 │ ├ note: the method is available for `Pin<&mut impl Future>` here │ ╰ help: items from traits can only be used if the trait is in scope help: trait `Future` which provides `poll` is implemented but not in scope; perhaps you want to import it ╭╴ 6 + use std::future::Future; ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn binary_op_not_allowed_issue_125631() { // tests/ui/binop/binary-op-not-allowed-issue-125631.rs let source = r#"use std::io::{Error, ErrorKind}; use std::thread; struct T1; struct T2; fn main() { (Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2); //~^ERROR binary operation `==` cannot be applied to type (Error::new(ErrorKind::Other, "2"), thread::current()) == (Error::new(ErrorKind::Other, "2"), thread::current()); //~^ERROR binary operation `==` cannot be applied to type (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2) == (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2); //~^ERROR binary operation `==` cannot be applied to type } "#; let title_0 = "binary operation `==` cannot be applied to type `(std::io::Error, Thread)`"; let title_1 = "the foreign item types don't implement required traits for this operation to be valid"; let input = &[ Level::ERROR.primary_title(title_0).id("E0369").element( Snippet::source(source) .path("$DIR/binary-op-not-allowed-issue-125631.rs") .annotation( AnnotationKind::Context .span(246..300) .label("(std::io::Error, Thread)"), ) .annotation( AnnotationKind::Context .span(312..366) .label("(std::io::Error, Thread)"), ) .annotation(AnnotationKind::Primary.span(309..311)), ), Level::NOTE .secondary_title(title_1) .element( Origin::path("$SRC_DIR/std/src/io/error.rs") .line(65) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("not implement `PartialEq`")), Group::with_level(Level::NOTE) .element( Origin::path("$SRC_DIR/std/src/thread/mod.rs") .line(1415) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("not implement `PartialEq`")), ]; let expected_ascii = str![[r#" error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)` --> $DIR/binary-op-not-allowed-issue-125631.rs:11:9 | 10 | (Error::new(ErrorKind::Other, "2"), thread::current()) | ------------------------------------------------------ (std::io::Error, Thread) 11 | == (Error::new(ErrorKind::Other, "2"), thread::current()); | ^^ ------------------------------------------------------ (std::io::Error, Thread) | note: the foreign item types don't implement required traits for this operation to be valid --> $SRC_DIR/std/src/io/error.rs:65:0 | = note: not implement `PartialEq` --> $SRC_DIR/std/src/thread/mod.rs:1415:0 | = note: not implement `PartialEq` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)` ╭▸ $DIR/binary-op-not-allowed-issue-125631.rs:11:9 │ 10 │ (Error::new(ErrorKind::Other, "2"), thread::current()) │ ────────────────────────────────────────────────────── (std::io::Error, Thread) 11 │ == (Error::new(ErrorKind::Other, "2"), thread::current()); │ ━━ ────────────────────────────────────────────────────── (std::io::Error, Thread) ╰╴ note: the foreign item types don't implement required traits for this operation to be valid ╭▸ $SRC_DIR/std/src/io/error.rs:65:0 │ ╰ note: not implement `PartialEq` ╭▸ $SRC_DIR/std/src/thread/mod.rs:1415:0 │ ╰ note: not implement `PartialEq` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn deriving_meta_unknown_trait() { // tests/ui/derives/deriving-meta-unknown-trait.rs let source = r#"#[derive(Eqr)] //~^ ERROR cannot find derive macro `Eqr` in this scope //~| ERROR cannot find derive macro `Eqr` in this scope struct Foo; pub fn main() {} "#; let input = &[ Level::ERROR .primary_title("cannot find derive macro `Eqr` in this scope") .element( Snippet::source(source) .path("$DIR/deriving-meta-unknown-trait.rs") .annotation( AnnotationKind::Primary .span(9..12) .label("help: a derive macro with a similar name exists: `Eq`"), ), ), Group::with_level(Level::ERROR) .element( Origin::path("$SRC_DIR/core/src/cmp.rs") .line(356) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("similarly named derive macro `Eq` defined here")) .element(Padding) .element( Level::NOTE .message("duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`"), ), ]; let expected_ascii = str![[r#" error: cannot find derive macro `Eqr` in this scope --> $DIR/deriving-meta-unknown-trait.rs:1:10 | 1 | #[derive(Eqr)] | ^^^ help: a derive macro with a similar name exists: `Eq` | --> $SRC_DIR/core/src/cmp.rs:356:0 | = note: similarly named derive macro `Eq` defined here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: cannot find derive macro `Eqr` in this scope ╭▸ $DIR/deriving-meta-unknown-trait.rs:1:10 │ 1 │ #[derive(Eqr)] │ ━━━ help: a derive macro with a similar name exists: `Eq` ╰╴ ╭▸ $SRC_DIR/core/src/cmp.rs:356:0 │ ├ note: similarly named derive macro `Eq` defined here │ ╰ note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn not_repeatable() { // tests/ui/proc-macro/quote/not-repeatable.rs let source = r#"#![feature(proc_macro_quote)] extern crate proc_macro; use proc_macro::quote; struct Ipv4Addr; fn main() { let ip = Ipv4Addr; let _ = quote! { $($ip)* }; //~ ERROR the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied } "#; let label_0 = "method `quote_into_iter` not found for this struct because it doesn't satisfy `Ipv4Addr: Iterator`, `Ipv4Addr: ToTokens`, `Ipv4Addr: proc_macro::ext::RepIteratorExt` or `Ipv4Addr: proc_macro::ext::RepToTokensExt`"; let title_0 = "the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied"; let title_1 = r#"the following trait bounds were not satisfied: `Ipv4Addr: Iterator` which is required by `Ipv4Addr: proc_macro::ext::RepIteratorExt` `&Ipv4Addr: Iterator` which is required by `&Ipv4Addr: proc_macro::ext::RepIteratorExt` `Ipv4Addr: ToTokens` which is required by `Ipv4Addr: proc_macro::ext::RepToTokensExt` `&mut Ipv4Addr: Iterator` which is required by `&mut Ipv4Addr: proc_macro::ext::RepIteratorExt`"#; let input = &[ Level::ERROR .primary_title(title_0) .id("E0599") .element( Snippet::source(source) .path("$DIR/not-repeatable.rs") .annotation(AnnotationKind::Primary.span(146..164).label( "method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds", )) .annotation(AnnotationKind::Context.span(81..96).label(label_0)), ) .element(Level::NOTE.message(title_1)), Level::NOTE .secondary_title("the traits `Iterator` and `ToTokens` must be implemented") .element( Origin::path("$SRC_DIR/proc_macro/src/to_tokens.rs") .line(11) .char_column(0), ), Group::with_level(Level::NOTE).element( Origin::path("$SRC_DIR/core/src/iter/traits/iterator.rs") .line(39) .char_column(0), ), ]; let expected_ascii = str![[r#" error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied --> $DIR/not-repeatable.rs:11:13 | 7 | struct Ipv4Addr; | --------------- method `quote_into_iter` not found for this struct because it doesn't satisfy `Ipv4Addr: Iterator`, `Ipv4Addr: ToTokens`, `Ipv4Addr: proc_macro::ext::RepIteratorExt` or `Ipv4Addr: proc_macro::ext::RepToTokensExt` ... 11 | let _ = quote! { $($ip)* }; //~ ERROR the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not s... | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `Ipv4Addr: Iterator` which is required by `Ipv4Addr: proc_macro::ext::RepIteratorExt` `&Ipv4Addr: Iterator` which is required by `&Ipv4Addr: proc_macro::ext::RepIteratorExt` `Ipv4Addr: ToTokens` which is required by `Ipv4Addr: proc_macro::ext::RepToTokensExt` `&mut Ipv4Addr: Iterator` which is required by `&mut Ipv4Addr: proc_macro::ext::RepIteratorExt` note: the traits `Iterator` and `ToTokens` must be implemented --> $SRC_DIR/proc_macro/src/to_tokens.rs:11:0 --> $SRC_DIR/core/src/iter/traits/iterator.rs:39:0 "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied ╭▸ $DIR/not-repeatable.rs:11:13 │ 7 │ struct Ipv4Addr; │ ─────────────── method `quote_into_iter` not found for this struct because it doesn't satisfy `Ipv4Addr: Iterator`, `Ipv4Addr: ToTokens`, `Ipv4Addr: proc_macro::ext::RepIteratorExt` or `Ipv4Addr: proc_macro::ext::RepToTokensExt` ┆ 11 │ let _ = quote! { $($ip)* }; //~ ERROR the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not sat… │ ━━━━━━━━━━━━━━━━━━ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds │ ╰ note: the following trait bounds were not satisfied: `Ipv4Addr: Iterator` which is required by `Ipv4Addr: proc_macro::ext::RepIteratorExt` `&Ipv4Addr: Iterator` which is required by `&Ipv4Addr: proc_macro::ext::RepIteratorExt` `Ipv4Addr: ToTokens` which is required by `Ipv4Addr: proc_macro::ext::RepToTokensExt` `&mut Ipv4Addr: Iterator` which is required by `&mut Ipv4Addr: proc_macro::ext::RepIteratorExt` note: the traits `Iterator` and `ToTokens` must be implemented ─▸ $SRC_DIR/proc_macro/src/to_tokens.rs:11:0 ─▸ $SRC_DIR/core/src/iter/traits/iterator.rs:39:0 "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn not_found_self_type_differs_shadowing_trait_item() { // tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs let source = r#"#![feature(inherent_associated_types)] #![allow(incomplete_features)] // Check that it's okay to report “[inherent] associated type […] not found” for inherent associated // type candidates that are not applicable (due to unsuitable Self type) even if there exists a // “shadowed” associated type from a trait with the same name since its use would be ambiguous // anyway if the IAT didn't exist. // FIXME(inherent_associated_types): Figure out which error would be more helpful here. //@ revisions: shadowed uncovered struct S(T); trait Tr { type Pr; } impl Tr for S { type Pr = (); } #[cfg(shadowed)] impl S<()> { type Pr = i32; } fn main() { let _: S::::Pr = (); //[shadowed]~^ ERROR associated type `Pr` not found //[uncovered]~^^ ERROR associated type `Pr` not found } "#; let input = &[Level::ERROR .primary_title("associated type `Pr` not found for `S` in the current scope") .id("E0220") .element( Snippet::source(source) .path("$DIR/not-found-self-type-differs-shadowing-trait-item.rs") .annotation( AnnotationKind::Primary .span(705..707) .label("associated item not found in `S`"), ) .annotation( AnnotationKind::Context .span(532..543) .label("associated type `Pr` not found for this struct"), ), ) .element(Level::NOTE.message("the associated type was found for\n"))]; let expected_ascii = str![[r#" error[E0220]: associated type `Pr` not found for `S` in the current scope --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23 | 12 | struct S(T); | ----------- associated type `Pr` not found for this struct ... 28 | let _: S::::Pr = (); | ^^ associated item not found in `S` | = note: the associated type was found for "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0220]: associated type `Pr` not found for `S` in the current scope ╭▸ $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23 │ 12 │ struct S(T); │ ─────────── associated type `Pr` not found for this struct ┆ 28 │ let _: S::::Pr = (); │ ━━ associated item not found in `S` │ ╰ note: the associated type was found for "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn unsafe_extern_suggestion() { // tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs let source = r#"//@ run-rustfix #![deny(missing_unsafe_on_extern)] #![allow(unused)] extern "C" { //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern] //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! static TEST1: i32; fn test1(i: i32); } unsafe extern "C" { static TEST2: i32; fn test2(i: i32); } fn main() {} "#; let title_0 = "this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!"; let title_1 = "for more information, see "; let input = &[ Level::ERROR .primary_title("extern blocks should be unsafe") .element( Snippet::source(source) .path("$DIR/unsafe-extern-suggestion.rs") .annotation( AnnotationKind::Context .span(71..71) .label("help: needs `unsafe` before the extern keyword: `unsafe`"), ) .annotation(AnnotationKind::Primary.span(71..303)), ) .element(Level::WARNING.message(title_0)) .element(Level::NOTE.message(title_1)), Level::NOTE .secondary_title("the lint level is defined here") .element( Snippet::source(source) .path("$DIR/unsafe-extern-suggestion.rs") .annotation(AnnotationKind::Primary.span(25..49)), ), ]; let expected_ascii = str![[r#" error: extern blocks should be unsafe --> $DIR/unsafe-extern-suggestion.rs:6:1 | 6 | extern "C" { | ^ | | | _help: needs `unsafe` before the extern keyword: `unsafe` | | 7 | | //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern] 8 | | //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! 9 | | static TEST1: i32; 10 | | fn test1(i: i32); 11 | | } | |_^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see note: the lint level is defined here --> $DIR/unsafe-extern-suggestion.rs:3:9 | 3 | #![deny(missing_unsafe_on_extern)] | ^^^^^^^^^^^^^^^^^^^^^^^^ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: extern blocks should be unsafe ╭▸ $DIR/unsafe-extern-suggestion.rs:6:1 │ 6 │ extern "C" { │ ╿ │ │ │ ┏━help: needs `unsafe` before the extern keyword: `unsafe` │ ┃ 7 │ ┃ //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern] 8 │ ┃ //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! 9 │ ┃ static TEST1: i32; 10 │ ┃ fn test1(i: i32); 11 │ ┃ } │ ┗━┛ │ ├ warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! ╰ note: for more information, see note: the lint level is defined here ╭▸ $DIR/unsafe-extern-suggestion.rs:3:9 │ 3 │ #![deny(missing_unsafe_on_extern)] ╰╴ ━━━━━━━━━━━━━━━━━━━━━━━━ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn alloc_error_handler_bad_signature_2() { // tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs let source = r#"//@ compile-flags:-C panic=abort #![feature(alloc_error_handler)] #![no_std] #![no_main] struct Layout; #[alloc_error_handler] fn oom( info: Layout, //~^ ERROR mismatched types ) { //~^^ ERROR mismatched types loop {} } #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } "#; let title_0 = "`core::alloc::Layout` and `Layout` have similar names, but are actually distinct types"; let input = &[ Level::ERROR .primary_title("mismatched types") .id("E0308") .element( Snippet::source(source) .path("$DIR/alloc-error-handler-bad-signature-2.rs") .annotation( AnnotationKind::Primary .span(130..230) .label("expected `Layout`, found `core::alloc::Layout`"), ) .annotation( AnnotationKind::Context .span(130..185) .label("arguments to this function are incorrect"), ) .annotation( AnnotationKind::Context .span(107..129) .label("in this procedural macro expansion"), ), ) .element(Level::NOTE.message(title_0)), Level::NOTE .secondary_title("`core::alloc::Layout` is defined in crate `core`") .element( Origin::path("$SRC_DIR/core/src/alloc/layout.rs") .line(40) .char_column(0), ), Level::NOTE .secondary_title("`Layout` is defined in the current crate") .element( Snippet::source(source) .path("$DIR/alloc-error-handler-bad-signature-2.rs") .annotation(AnnotationKind::Primary.span(91..104)), ), Level::NOTE .secondary_title("function defined here") .element( Snippet::source(source) .path("$DIR/alloc-error-handler-bad-signature-2.rs") .annotation(AnnotationKind::Context.span(142..154).label("")) .annotation(AnnotationKind::Primary.span(133..136)), ), ]; let expected_ascii = str![[r#" error[E0308]: mismatched types --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 | 9 | #[alloc_error_handler] | ---------------------- in this procedural macro expansion 10 | // fn oom( 11 | || info: Layout, //~^ ERROR mismatched types 12 | || ) { //~^^ ERROR mismatched types | ||_- arguments to this function are incorrect 13 | | loop {} 14 | | } | |__^ expected `Layout`, found `core::alloc::Layout` | = note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types note: `core::alloc::Layout` is defined in crate `core` --> $SRC_DIR/core/src/alloc/layout.rs:40:0 note: `Layout` is defined in the current crate --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1 | 7 | struct Layout; | ^^^^^^^^^^^^^ note: function defined here --> $DIR/alloc-error-handler-bad-signature-2.rs:10:4 | 10 | fn oom( | ^^^ 11 | info: Layout, //~^ ERROR mismatched types | ------------ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types ╭▸ $DIR/alloc-error-handler-bad-signature-2.rs:10:1 │ 9 │ #[alloc_error_handler] │ ────────────────────── in this procedural macro expansion 10 │ ┏┌ fn oom( 11 │ ┃│ info: Layout, //~^ ERROR mismatched types 12 │ ┃│ ) { //~^^ ERROR mismatched types │ ┃└─┘ arguments to this function are incorrect 13 │ ┃ loop {} 14 │ ┃ } │ ┗━━┛ expected `Layout`, found `core::alloc::Layout` │ ╰ note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types note: `core::alloc::Layout` is defined in crate `core` ─▸ $SRC_DIR/core/src/alloc/layout.rs:40:0 note: `Layout` is defined in the current crate ╭▸ $DIR/alloc-error-handler-bad-signature-2.rs:7:1 │ 7 │ struct Layout; ╰╴━━━━━━━━━━━━━ note: function defined here ╭▸ $DIR/alloc-error-handler-bad-signature-2.rs:10:4 │ 10 │ fn oom( │ ━━━ 11 │ info: Layout, //~^ ERROR mismatched types ╰╴ ──────────── "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn str_escape() { // tests/ui/str/str-escape.rs let source = r#"//@ check-pass // ignore-tidy-tab //@ edition: 2021 fn main() { let s = "\ "; //~^^^ WARNING multiple lines skipped by escaped newline assert_eq!(s, ""); let s = c"foo\   bar "; //~^^^ WARNING whitespace symbol '\u{a0}' is not skipped assert_eq!(s, c"foo  bar\n "); let s = "a\ b"; assert_eq!(s, "ab"); let s = "a\ b"; assert_eq!(s, "ab"); let s = b"a\ b"; //~^^ WARNING whitespace symbol '\u{c}' is not skipped // '\x0c' is ASCII whitespace, but it may not need skipped // discussion: https://github.com/rust-lang/rust/pull/108403 assert_eq!(s, b"a\x0cb"); } "#; let input = &[Level::WARNING .primary_title(r#"whitespace symbol '\u{a0}' is not skipped"#) .element( Snippet::source(source) .path("$DIR/str-escape.rs") .annotation( AnnotationKind::Context .span(203..205) .label(r#"whitespace symbol '\u{a0}' is not skipped"#), ) .annotation(AnnotationKind::Primary.span(199..205)), )]; let expected_ascii = str![[r#" warning: whitespace symbol '\u{a0}' is not skipped --> $DIR/str-escape.rs:12:18 | 12 | let s = c"foo\ | __________________^ 13 | |   bar | | ^ whitespace symbol '\u{a0}' is not skipped | |___| | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii.raw()); let expected_unicode = str![[r#" warning: whitespace symbol '\u{a0}' is not skipped ╭▸ $DIR/str-escape.rs:12:18 │ 12 │ let s = c"foo\ │ ┏━━━━━━━━━━━━━━━━━━┛ 13 │ ┃   bar │ ┃ ╿ whitespace symbol '\u{a0}' is not skipped │ ┗━━━│ ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode.raw()); } #[test] fn origin_path_repeated() { // tests/ui/pattern/usefulness/match-privately-empty.rs let source = r#"//@ revisions: normal exhaustive_patterns #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![feature(never_type)] mod private { pub struct Private { _bot: !, pub misc: bool, } pub const DATA: Option = None; } fn main() { match private::DATA { //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered None => {} Some(private::Private { misc: false, .. }) => {} } } "#; let title_0 = "non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered"; let title_1 = "`Option` defined here"; let title_2 = "ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown"; let input = &[ Level::ERROR.primary_title(title_0).id("E0004").element( Snippet::source(source) .path("$DIR/match-privately-empty.rs") .annotation( AnnotationKind::Primary .span(286..299) .label("pattern `Some(Private { misc: true, .. })` not covered"), ), ), Level::NOTE .secondary_title(title_1) .element( Origin::path("$SRC_DIR/core/src/option.rs") .line(593) .char_column(0), ) .element( Origin::path("$SRC_DIR/core/src/option.rs") .line(601) .char_column(4), ) .element(Padding) .element(Level::NOTE.message("not covered")) .element(Level::NOTE.message("the matched value is of type `Option`")), Level::HELP.secondary_title(title_2).element( Snippet::source(source) .path("$DIR/match-privately-empty.rs") .line_start(17) .fold(true) .patch(Patch::new( 468..468, ", Some(Private { misc: true, .. }) => todo!()", )), ), ]; let expected_ascii = str![[r#" error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered ╭▸ $DIR/match-privately-empty.rs:14:11 │ 14 │ match private::DATA { │ ━━━━━━━━━━━━━ pattern `Some(Private { misc: true, .. })` not covered ╰╴ note: `Option` defined here ╭▸ $SRC_DIR/core/src/option.rs:593:0 ⸬ $SRC_DIR/core/src/option.rs:601:4 │ ├ note: not covered ╰ note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown ╭╴ 33 ± Some(private::Private { misc: false, .. }) => {}, 34 + Some(Private { misc: true, .. }) => todo!() ╰╴ "#]]; let renderer = Renderer::plain().decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered ╭▸ $DIR/match-privately-empty.rs:14:11 │ 14 │ match private::DATA { │ ━━━━━━━━━━━━━ pattern `Some(Private { misc: true, .. })` not covered ╰╴ note: `Option` defined here ╭▸ $SRC_DIR/core/src/option.rs:593:0 ⸬ $SRC_DIR/core/src/option.rs:601:4 │ ├ note: not covered ╰ note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown ╭╴ 33 ± Some(private::Private { misc: false, .. }) => {}, 34 + Some(Private { misc: true, .. }) => todo!() ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn origin_path_repeated_element_between() { // tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs let source = r#"//@ revisions: old new //@[old] edition:2015 //@[new] edition:2021 //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { //[new]~^ ERROR expected a type, found a trait //[old]~^^ ERROR the trait `Ord` is not dyn compatible //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) } fn main() { let _ = ord_prefer_dot(String::new()); } "#; let title_0 = "for a trait to be dyn compatible it needs to allow building a vtable for more information, visit "; let input = &[ Level::ERROR .primary_title("the trait `Ord` is not dyn compatible") .id("E0038") .element( Snippet::source(source) .path("$DIR/bare-trait-dont-suggest-dyn.rs") .annotation( AnnotationKind::Primary .span(149..152) .label("`Ord` is not dyn compatible"), ), ), Level::NOTE .secondary_title(title_0) .element( Origin::path("$SRC_DIR/core/src/cmp.rs") .line(961) .char_column(20), ) .element(Padding) .element(Level::NOTE.message( "the trait is not dyn compatible because it uses `Self` as a type parameter", )) .element( Origin::path("$SRC_DIR/core/src/cmp.rs") .line(338) .char_column(14), ) .element(Padding) .element(Level::NOTE.message( "the trait is not dyn compatible because it uses `Self` as a type parameter", )), Level::HELP .secondary_title("consider using an opaque type instead") .element( Snippet::source(source) .path("$DIR/bare-trait-dont-suggest-dyn.rs") .line_start(6) .fold(true) .patch(Patch::new(149..149, "impl ")), ), ]; let expected_ascii = str![[r#" error[E0038]: the trait `Ord` is not dyn compatible ╭▸ $DIR/bare-trait-dont-suggest-dyn.rs:6:33 │ 6 │ fn ord_prefer_dot(s: String) -> Ord { │ ━━━ `Ord` is not dyn compatible ╰╴ note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit ╭▸ $SRC_DIR/core/src/cmp.rs:961:20 │ ├ note: the trait is not dyn compatible because it uses `Self` as a type parameter ⸬ $SRC_DIR/core/src/cmp.rs:338:14 │ ╰ note: the trait is not dyn compatible because it uses `Self` as a type parameter help: consider using an opaque type instead ╭╴ 11 │ fn ord_prefer_dot(s: String) -> impl Ord { ╰╴ ++++ "#]]; let renderer = Renderer::plain().decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0038]: the trait `Ord` is not dyn compatible ╭▸ $DIR/bare-trait-dont-suggest-dyn.rs:6:33 │ 6 │ fn ord_prefer_dot(s: String) -> Ord { │ ━━━ `Ord` is not dyn compatible ╰╴ note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit ╭▸ $SRC_DIR/core/src/cmp.rs:961:20 │ ├ note: the trait is not dyn compatible because it uses `Self` as a type parameter ⸬ $SRC_DIR/core/src/cmp.rs:338:14 │ ╰ note: the trait is not dyn compatible because it uses `Self` as a type parameter help: consider using an opaque type instead ╭╴ 11 │ fn ord_prefer_dot(s: String) -> impl Ord { ╰╴ ++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multiple_origin() { // tests/ui/binop/binary-op-not-allowed-issue-125631.rs let source_0 = r#"use std::io::{Error, ErrorKind}; use std::thread; struct T1; struct T2; fn main() { (Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2); //~^ERROR binary operation `==` cannot be applied to type (Error::new(ErrorKind::Other, "2"), thread::current()) == (Error::new(ErrorKind::Other, "2"), thread::current()); //~^ERROR binary operation `==` cannot be applied to type (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2) == (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2); //~^ERROR binary operation `==` cannot be applied to type } "#; let title_0 = "the foreign item types don't implement required traits for this operation to be valid"; let input = &[ Level::ERROR .primary_title( "binary operation `==` cannot be applied to type `(std::io::Error, Thread)`", ) .id("E0369") .element( Snippet::source(source_0) .path("$DIR/binary-op-not-allowed-issue-125631.rs") .annotation( AnnotationKind::Context .span(246..300) .label("(std::io::Error, Thread)"), ) .annotation( AnnotationKind::Context .span(312..366) .label("(std::io::Error, Thread)"), ) .annotation(AnnotationKind::Primary.span(309..311)), ), Level::NOTE .secondary_title(title_0) .element( Origin::path("$SRC_DIR/std/src/io/error.rs") .line(65) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("not implement `PartialEq`")), Group::with_level(Level::NOTE) .element( Origin::path("$SRC_DIR/std/src/thread/mod.rs") .line(1439) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("not implement `PartialEq`")), ]; let expected_ascii = str![[r#" error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)` ╭▸ $DIR/binary-op-not-allowed-issue-125631.rs:11:9 │ 10 │ (Error::new(ErrorKind::Other, "2"), thread::current()) │ ────────────────────────────────────────────────────── (std::io::Error, Thread) 11 │ == (Error::new(ErrorKind::Other, "2"), thread::current()); │ ━━ ────────────────────────────────────────────────────── (std::io::Error, Thread) ╰╴ note: the foreign item types don't implement required traits for this operation to be valid ╭▸ $SRC_DIR/std/src/io/error.rs:65:0 │ ╰ note: not implement `PartialEq` ╭▸ $SRC_DIR/std/src/thread/mod.rs:1439:0 │ ╰ note: not implement `PartialEq` "#]]; let renderer = Renderer::plain().decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)` ╭▸ $DIR/binary-op-not-allowed-issue-125631.rs:11:9 │ 10 │ (Error::new(ErrorKind::Other, "2"), thread::current()) │ ────────────────────────────────────────────────────── (std::io::Error, Thread) 11 │ == (Error::new(ErrorKind::Other, "2"), thread::current()); │ ━━ ────────────────────────────────────────────────────── (std::io::Error, Thread) ╰╴ note: the foreign item types don't implement required traits for this operation to be valid ╭▸ $SRC_DIR/std/src/io/error.rs:65:0 │ ╰ note: not implement `PartialEq` ╭▸ $SRC_DIR/std/src/thread/mod.rs:1439:0 │ ╰ note: not implement `PartialEq` "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn const_generics_issue_82656() { // tests/ui/const-generics/issues/issue-82956.rs let source = r#"#![feature(generic_const_exprs)] #![allow(incomplete_features)] pub struct ConstCheck; pub trait True {} impl True for ConstCheck {} pub trait OrdesDec { type Newlen; type Output; fn pop(self) -> (Self::Newlen, Self::Output); } impl OrdesDec for [T; N] where ConstCheck<{N > 1}>: True, [T; N - 1]: Sized, { type Newlen = [T; N - 1]; type Output = T; fn pop(self) -> (Self::Newlen, Self::Output) { let mut iter = IntoIter::new(self); //~^ ERROR: failed to resolve: use of undeclared type `IntoIter` let end = iter.next_back().unwrap(); let new = [(); N - 1].map(move |()| iter.next().unwrap()); (new, end) } } fn main() {} "#; let input = &[ Level::ERROR .primary_title("failed to resolve: use of undeclared type `IntoIter`") .id("E0433") .element( Snippet::source(source) .path("$DIR/issue-82956.rs") .annotation( AnnotationKind::Primary .span(502..510) .label("use of undeclared type `IntoIter`"), ), ), Level::HELP .secondary_title("consider importing one of these structs") .element( Snippet::source(source) .path("$DIR/issue-82956.rs") .patch(Patch::new(65..65, "use std::array::IntoIter;\n\n")), ) .element( Snippet::source(source) .path("$DIR/issue-82956.rs") .patch(Patch::new( 65..65, "use std::collections::binary_heap::IntoIter;\n\n", )), ) .element( Snippet::source(source) .path("$DIR/issue-82956.rs") .patch(Patch::new( 65..65, "use std::collections::btree_map::IntoIter;\n\n", )), ) .element( Snippet::source(source) .path("$DIR/issue-82956.rs") .patch(Patch::new( 65..65, "use std::collections::btree_set::IntoIter;\n\n", )), ) .element(Level::NOTE.no_name().message("and 9 other candidates")), ]; let expected_ascii = str![[r#" error[E0433]: failed to resolve: use of undeclared type `IntoIter` --> $DIR/issue-82956.rs:25:24 | 25 | let mut iter = IntoIter::new(self); | ^^^^^^^^ use of undeclared type `IntoIter` | help: consider importing one of these structs | 4 + use std::array::IntoIter; | 4 + use std::collections::binary_heap::IntoIter; | 4 + use std::collections::btree_map::IntoIter; | 4 + use std::collections::btree_set::IntoIter; | = and 9 other candidates "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0433]: failed to resolve: use of undeclared type `IntoIter` ╭▸ $DIR/issue-82956.rs:25:24 │ 25 │ let mut iter = IntoIter::new(self); │ ━━━━━━━━ use of undeclared type `IntoIter` ╰╴ help: consider importing one of these structs ╭╴ 4 + use std::array::IntoIter; ├╴ 4 + use std::collections::binary_heap::IntoIter; ├╴ 4 + use std::collections::btree_map::IntoIter; ├╴ 4 + use std::collections::btree_set::IntoIter; │ ╰ and 9 other candidates "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn multi_suggestion() { // tests/ui/suggestions/multi-suggestion.rs let source = r#"//@ revisions: ascii unicode //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode #![allow(dead_code)] struct U { wtf: Option>>, x: T, } fn main() { U { wtf: Some(Box(U { //[ascii]~ ERROR cannot initialize a tuple struct which contains private fields wtf: None, x: (), })), x: () }; let _ = std::collections::HashMap(); //[ascii]~^ ERROR expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` let _ = std::collections::HashMap {}; //[ascii]~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields let _ = Box {}; //[ascii]~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields } "#; let title_0 = "expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`"; let input = &[ Level::ERROR .primary_title(title_0) .id("E0423") .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .annotation(AnnotationKind::Primary.span(396..423)), ) .element( Origin::path("$SRC_DIR/std/src/collections/hash/map.rs") .line(242) .char_column(0), ) .element(Padding) .element(Level::NOTE.message("`std::collections::HashMap` defined here")) .element(Padding), Level::HELP .secondary_title( "you might have meant to use an associated function to build this type", ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(421..423, "::new()")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(421..423, "::with_capacity(_)")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(421..423, "::with_hasher(_)")), ) .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(421..423, "::with_capacity_and_hasher(_, _)")), ), Level::HELP .secondary_title("consider using the `Default` trait") .element( Snippet::source(source) .path("$DIR/multi-suggestion.rs") .patch(Patch::new(396..396, "<")) .patch(Patch::new( 421..423, " as std::default::Default>::default()", )), ), ]; let expected_ascii = str![[r#" error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` --> $DIR/multi-suggestion.rs:17:13 | 17 | let _ = std::collections::HashMap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ::: $SRC_DIR/std/src/collections/hash/map.rs:242:0 | = note: `std::collections::HashMap` defined here | help: you might have meant to use an associated function to build this type | 17 | let _ = std::collections::HashMap::new(); | +++++ 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_capacity(_); | 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_hasher(_); | 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _); | help: consider using the `Default` trait | 17 | let _ = ::default(); | + ++++++++++++++++++++++++++++++++++ "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` ╭▸ $DIR/multi-suggestion.rs:17:13 │ 17 │ let _ = std::collections::HashMap(); │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⸬ $SRC_DIR/std/src/collections/hash/map.rs:242:0 │ ├ note: `std::collections::HashMap` defined here ╰╴ help: you might have meant to use an associated function to build this type ╭╴ 17 │ let _ = std::collections::HashMap::new(); ├╴ +++++ 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_capacity(_); ├╴ 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_hasher(_); ├╴ 17 - let _ = std::collections::HashMap(); 17 + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _); ╰╴ help: consider using the `Default` trait ╭╴ 17 │ let _ = ::default(); ╰╴ + ++++++++++++++++++++++++++++++++++ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn suggest_box_new() { // tests/ui/privacy/suggest-box-new.rs let source = r#"//@ revisions: ascii unicode //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode #![allow(dead_code)] struct U { wtf: Option>>, x: T, } fn main() { U { wtf: Some(Box(U { wtf: None, x: (), })), x: () }; let _ = std::collections::HashMap(); //[ascii]~^ ERROR expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` let _ = std::collections::HashMap {}; //[ascii]~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields let _ = Box {}; //[ascii]~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields } "#; let input = &[ Level::ERROR .primary_title("cannot initialize a tuple struct which contains private fields") .id("E0423") .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .annotation(AnnotationKind::Primary.span(220..223)), ), Level::NOTE .secondary_title("constructor is not visible here due to private fields") .element( Origin::path("$SRC_DIR/alloc/src/boxed.rs") .line(234) .char_column(2), ) .element(Padding) .element(Level::NOTE.message("private field")) .element(Padding) .element(Level::NOTE.message("private field")), Level::HELP .secondary_title( "you might have meant to use an associated function to build this type", ) .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .patch(Patch::new(223..280, "::new(_)")), ) .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .patch(Patch::new(223..280, "::new_uninit()")), ) .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .patch(Patch::new(223..280, "::new_zeroed()")), ) .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .patch(Patch::new(223..280, "::new_in(_, _)")), ) .element(Level::NOTE.no_name().message("and 12 other candidates")), Level::HELP .secondary_title("consider using the `Default` trait") .element( Snippet::source(source) .path("$DIR/suggest-box-new.rs") .patch(Patch::new(220..220, "<")) .patch(Patch::new( 223..280, " as std::default::Default>::default()", )), ), ]; let expected_ascii = str![[r#" error[E0423]: cannot initialize a tuple struct which contains private fields --> $DIR/suggest-box-new.rs:11:19 | 11 | wtf: Some(Box(U { | ^^^ | note: constructor is not visible here due to private fields --> $SRC_DIR/alloc/src/boxed.rs:234:2 | = note: private field | = note: private field help: you might have meant to use an associated function to build this type | 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new(_)), | 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_uninit()), | 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_zeroed()), | 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_in(_, _)), | = and 12 other candidates help: consider using the `Default` trait | 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(::default()), | "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0423]: cannot initialize a tuple struct which contains private fields ╭▸ $DIR/suggest-box-new.rs:11:19 │ 11 │ wtf: Some(Box(U { │ ━━━ ╰╴ note: constructor is not visible here due to private fields ╭▸ $SRC_DIR/alloc/src/boxed.rs:234:2 │ ├ note: private field │ ╰ note: private field help: you might have meant to use an associated function to build this type ╭╴ 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new(_)), ├╴ 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_uninit()), ├╴ 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_zeroed()), ├╴ 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(Box::new_in(_, _)), │ ╰ and 12 other candidates help: consider using the `Default` trait ╭╴ 11 - wtf: Some(Box(U { 12 - wtf: None, 13 - x: (), 14 - })), 11 + wtf: Some(::default()), ╰╴ "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn too_many_field_suggestions() { // tests/ui/suggestions/too-many-field-suggestions.rs let source = r#"struct Thing { a0: Foo, a1: Foo, a2: Foo, a3: Foo, a4: Foo, a5: Foo, a6: Foo, a7: Foo, a8: Foo, a9: Foo, } struct Foo { field: Field, } struct Field; impl Foo { fn bar(&self) {} } fn bar(t: Thing) { t.bar(); t.field; } fn main() {} "#; let input = &[ Level::ERROR .primary_title("no method named `bar` found for struct `Thing` in the current scope") .id("E0599") .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .annotation( AnnotationKind::Primary .span(257..260) .label("method not found in `Thing`"), ) .annotation( AnnotationKind::Context .span(0..12) .label("method `bar` not found for this struct"), ), ), Level::HELP .secondary_title("some of the expressions' fields have a method of the same name") .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .patch(Patch::new(257..257, "a0.")), ) .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .patch(Patch::new(257..257, "a1.")), ) .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .patch(Patch::new(257..257, "a2.")), ) .element( Snippet::source(source) .path("$DIR/too-many-field-suggestions.rs") .patch(Patch::new(257..257, "a3.")), ) .element(Level::NOTE.no_name().message("and 6 other candidates")), ]; let expected_ascii = str![[r#" error[E0599]: no method named `bar` found for struct `Thing` in the current scope --> $DIR/too-many-field-suggestions.rs:25:7 | 1 | struct Thing { | ------------ method `bar` not found for this struct ... 25 | t.bar(); | ^^^ method not found in `Thing` | help: some of the expressions' fields have a method of the same name | 25 | t.a0.bar(); | +++ 25 | t.a1.bar(); | +++ 25 | t.a2.bar(); | +++ 25 | t.a3.bar(); | +++ = and 6 other candidates "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0599]: no method named `bar` found for struct `Thing` in the current scope ╭▸ $DIR/too-many-field-suggestions.rs:25:7 │ 1 │ struct Thing { │ ──────────── method `bar` not found for this struct ┆ 25 │ t.bar(); │ ━━━ method not found in `Thing` ╰╴ help: some of the expressions' fields have a method of the same name ╭╴ 25 │ t.a0.bar(); ├╴ +++ 25 │ t.a1.bar(); ├╴ +++ 25 │ t.a2.bar(); ├╴ +++ 25 │ t.a3.bar(); │ +++ ╰ and 6 other candidates "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn invalid_arguments_unterminated() { // tests/ui/check-cfg/invalid-arguments.unterminated.rs let input = &[Level::ERROR .primary_title("invalid `--check-cfg` argument: `cfg(`") .element( Level::NOTE .message(r#"expected `cfg(name, values("value1", "value2", ... "valueN"))`"#), ) .element(Level::NOTE.message( "visit for more details", ))]; let expected_ascii = str![[r#" error: invalid `--check-cfg` argument: `cfg(` | = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` = note: visit for more details "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: invalid `--check-cfg` argument: `cfg(` │ ├ note: expected `cfg(name, values("value1", "value2", ... "valueN"))` ╰ note: visit for more details "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn timeout() { // tests/ui/consts/timeout.rs let source = r#"//! This test checks that external macros don't hide //! the const eval timeout lint and then subsequently //! ICE. //@ compile-flags: --crate-type=lib -Ztiny-const-eval-limit static ROOK_ATTACKS_TABLE: () = { 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); 0_u64.count_ones(); }; //~? ERROR constant evaluation is taking a long time "#; let title_0 = "this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint."; let title_1 = "this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info)"; let input = &[ Level::ERROR .primary_title("constant evaluation is taking a long time") .element( Origin::path("$SRC_DIR/core/src/num/mod.rs") .line(1151) .char_column(4), ) .element(Level::NOTE.message(title_0)), Level::HELP .secondary_title("the constant being evaluated") .element( Snippet::source(source) .path("$DIR/timeout.rs") .annotation(AnnotationKind::Primary.span(178..207)), ) .element(Level::NOTE.message("`#[deny(long_running_const_eval)]` on by default")) .element(Level::NOTE.message(title_1)), ]; let expected_ascii = str![[r#" error: constant evaluation is taking a long time --> $SRC_DIR/core/src/num/mod.rs:1151:4 = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated --> $DIR/timeout.rs:7:1 | 7 | static ROOK_ATTACKS_TABLE: () = { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default = note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info) "#]]; let renderer = Renderer::plain(); assert_data_eq!(renderer.render(input), expected_ascii); let expected_unicode = str![[r#" error: constant evaluation is taking a long time ╭▸ $SRC_DIR/core/src/num/mod.rs:1151:4 ╰ note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated ╭▸ $DIR/timeout.rs:7:1 │ 7 │ static ROOK_ATTACKS_TABLE: () = { │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ├ note: `#[deny(long_running_const_eval)]` on by default ╰ note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info) "#]]; let renderer = renderer.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer.render(input), expected_unicode); } #[test] fn emitter_overflow_bad_whitespace() { // tests/ui/errors/emitter-overflow-bad-whitespace.rs let source = r#"                                        fn main() { return; } "#; let title_0 = "Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not"; let report = &[ Group::with_title(Level::ERROR.primary_title("unknown start of token: \u{a0}")).element( Snippet::source(source) .path("$DIR/emitter-overflow-bad-whitespace.rs") .line_start(10) .annotation(AnnotationKind::Primary.span(0..2)), ), Group::with_title(Level::HELP.secondary_title(title_0)).element( Snippet::source(source) .path("$DIR/emitter-overflow-bad-whitespace.rs") .line_start(10) .patch(Patch::new(0..2, " ")), ), ]; let expected_ascii = str![[r#" error: unknown start of token:   --> $DIR/emitter-overflow-bad-whitespace.rs:10:1 | 10 |     ... | ^ | help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not | 10 |                                       fn main() { return; } | + "#]]; let renderer_ascii = Renderer::plain().term_width(1); assert_data_eq!(renderer_ascii.render(report), expected_ascii); let expected_unicode = str![[r#" error: unknown start of token:   ╭▸ $DIR/emitter-overflow-bad-whitespace.rs:10:1 │ 10 │       … │ ━ ╰╴ help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not ╭╴ 10 │                                       fn main() { return; } ╰╴+ "#]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(report), expected_unicode); } #[test] fn issue_109854() { // tests/ui/suggestions/issue-109854.rs let source_0 = r##" String::with_capacity( //~^ ERROR this function takes 1 argument but 3 arguments were supplied generate_setter, r#" pub(crate) struct Person {} "#, r#""#, "##; let source_1 = r#" generate_setter, "#; let title_0 = "expected type `usize` found fn item `fn() {generate_setter}`"; let source_2 = r##" generate_setter, r#" pub(crate) struct Person {} "#, r#""#, "##; let report = &[ Level::ERROR .primary_title("this function takes 1 argument but 3 arguments were supplied") .id("E0061") .element( Snippet::source(source_0) .path("$DIR/issue-109854.rs") .line_start(2) .annotation(AnnotationKind::Primary.span(4..25)) .annotation( AnnotationKind::Context .span(128..172) .label("unexpected argument #2 of type `&'static str`"), ) .annotation( AnnotationKind::Context .span(179..184) .label("unexpected argument #3 of type `&'static str`"), ), ), Level::NOTE .secondary_title("expected `usize`, found fn item") .element( Snippet::source(source_1) .path("$DIR/issue-109854.rs") .line_start(4) .annotation(AnnotationKind::Primary.span(4..19)), ) .element(Level::NOTE.message(title_0)), Level::NOTE .secondary_title("associated function defined here") .element( Origin::path("$SRC_DIR/alloc/src/string.rs") .line(480) .char_column(11), ), Level::HELP .secondary_title("remove the extra arguments") .element( Snippet::source(source_2) .path("$DIR/issue-109854.rs") .line_start(4) .patch(Patch::new(4..19, "/* usize */")) .patch(Patch::new(19..69, "")) .patch(Patch::new(69..81, "")), ), ]; let expected_ascii = str![[r##" error[E0061]: this function takes 1 argument but 3 arguments were supplied --> $DIR/issue-109854.rs:2:5 | 2 | String::with_capacity( | ^^^^^^^^^^^^^^^^^^^^^ ... 5 | / r#" 6 | | pub(crate) struct Person {} 7 | | "#, | |__- unexpected argument #2 of type `&'static str` 8 | r#""#, | ----- unexpected argument #3 of type `&'static str` | note: expected `usize`, found fn item --> $DIR/issue-109854.rs:4:5 | 4 | generate_setter, | ^^^^^^^^^^^^^^^ = note: expected type `usize` found fn item `fn() {generate_setter}` note: associated function defined here --> $SRC_DIR/alloc/src/string.rs:480:11 help: remove the extra arguments | 4 - generate_setter, 5 - r#" 6 - pub(crate) struct Person {} 7 - "#, 8 - r#""#, 4 + /* usize */, | "##]]; let renderer_ascii = Renderer::plain(); assert_data_eq!(renderer_ascii.render(report), expected_ascii); let expected_unicode = str![[r##" error[E0061]: this function takes 1 argument but 3 arguments were supplied ╭▸ $DIR/issue-109854.rs:2:5 │ 2 │ String::with_capacity( │ ━━━━━━━━━━━━━━━━━━━━━ ┆ 5 │ ┌ r#" 6 │ │ pub(crate) struct Person {} 7 │ │ "#, │ └──┘ unexpected argument #2 of type `&'static str` 8 │ r#""#, │ ───── unexpected argument #3 of type `&'static str` ╰╴ note: expected `usize`, found fn item ╭▸ $DIR/issue-109854.rs:4:5 │ 4 │ generate_setter, │ ━━━━━━━━━━━━━━━ ╰ note: expected type `usize` found fn item `fn() {generate_setter}` note: associated function defined here ─▸ $SRC_DIR/alloc/src/string.rs:480:11 help: remove the extra arguments ╭╴ 4 - generate_setter, 5 - r#" 6 - pub(crate) struct Person {} 7 - "#, 8 - r#""#, 4 + /* usize */, ╰╴ "##]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(report), expected_unicode); } #[test] fn match_same_arms() { // src/tools/clippy/tests/ui/match_same_arms.rs let source = r#" 2 => 'b', 3 => 'b', _ => 'b', "#; let report = &[ Level::ERROR .primary_title("these match arms have identical bodies") .element( Snippet::source(source) .path("tests/ui/match_same_arms.rs") .line_start(20) .annotation(AnnotationKind::Primary.span(8..16)) .annotation(AnnotationKind::Primary.span(26..34)) .annotation( AnnotationKind::Primary .span(44..52) .label("the wildcard arm"), ), ) .element( Level::HELP .message("if this is unintentional make the arms return different values"), ), Level::HELP .secondary_title("otherwise remove the non-wildcard arms") .element( Snippet::source(source) .path("tests/ui/match_same_arms.rs") .line_start(20) .patch(Patch::new(8..26, "")) .patch(Patch::new(26..44, "")), ), ]; let expected_ascii = str![[r#" error: these match arms have identical bodies --> tests/ui/match_same_arms.rs:20:9 | 20 | 2 => 'b', | ^^^^^^^^ 21 | 3 => 'b', | ^^^^^^^^ 22 | _ => 'b', | ^^^^^^^^ the wildcard arm | = help: if this is unintentional make the arms return different values help: otherwise remove the non-wildcard arms | 20 - 2 => 'b', 21 - 3 => 'b', | "#]]; let renderer_ascii = Renderer::plain(); assert_data_eq!(renderer_ascii.render(report), expected_ascii); let expected_unicode = str![[r#" error: these match arms have identical bodies ╭▸ tests/ui/match_same_arms.rs:20:9 │ 20 │ 2 => 'b', │ ━━━━━━━━ 21 │ 3 => 'b', │ ━━━━━━━━ 22 │ _ => 'b', │ ━━━━━━━━ the wildcard arm │ ╰ help: if this is unintentional make the arms return different values help: otherwise remove the non-wildcard arms ╭╴ 20 - 2 => 'b', 21 - 3 => 'b', ╰╴ "#]]; let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode); assert_data_eq!(renderer_unicode.render(report), expected_unicode); } ast_serialize-0.13.1/crates/ruff_cache/Cargo.toml000064400000000000000000000013131046102023000166400ustar00[package] name = "ruff_cache" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [dependencies] char_str = { workspace = true } filetime = { workspace = true } glob = { workspace = true } globset = { workspace = true } itertools = { workspace = true } regex = { workspace = true } seahash = { workspace = true } [dev-dependencies] ruff_macros = { workspace = true } [lints] workspace = true [lib] test = false ast_serialize-0.13.1/crates/ruff_cache/README.md000064400000000000000000000010221046102023000161640ustar00 # ruff_cache This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_cache). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_cache/src/cache_key.rs000064400000000000000000000262361046102023000177730ustar00use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::num::{ NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, }; use std::path::{Path, PathBuf}; use char_str::CharStr; use glob::Pattern; use itertools::Itertools; use regex::Regex; use seahash::SeaHasher; /// A type that be used as part of a cache key. /// /// A cache looks up artefacts by a cache key. Many cache keys are composed of sub-keys. For example, /// caching the lint results of a file depend at least on the file content, the user settings, and linter version. /// Types implementing the [`CacheKey`] trait can be used as part of a cache key by which artefacts are queried. /// /// ## Implementing `CacheKey` /// /// You can derive [`CacheKey`] with `#[derive(CacheKey)]` if all fields implement [`CacheKey`]. The resulting /// cache key will be the combination of the values from calling `cache_key` on each field. /// /// ``` /// # use ruff_macros::CacheKey; /// /// #[derive(CacheKey)] /// struct Test { /// name: String, /// version: u32, /// } /// ``` /// /// If you need more control over computing the cache key, you can of course implement the [`CacheKey]` yourself: /// /// ``` /// use ruff_cache::{CacheKey, CacheKeyHasher}; /// /// struct Test { /// name: String, /// version: u32, /// other: String /// } /// /// impl CacheKey for Test { /// fn cache_key(&self, state: &mut CacheKeyHasher) { /// self.name.cache_key(state); /// self.version.cache_key(state); /// } /// } /// ``` /// /// ## Portability /// /// Ideally, the cache key is portable across platforms but this is not yet a strict requirement. /// /// ## Using [`Hash`] /// /// You can defer to the [`Hash`] implementation for non-composite types. /// Be aware, that the [`Hash`] implementation may not be portable. /// /// ## Why a new trait rather than reusing [`Hash`]? /// The main reason is that hashes and cache keys have different constraints: /// /// * Cache keys are less performance sensitive: Hashes must be super fast to compute for performant hashed-collections. That's /// why some standard types don't implement [`Hash`] where it would be safe to implement [`CacheKey`], e.g. `HashSet` /// * Cache keys must be deterministic where hash keys do not have this constraint. That's why pointers don't implement [`CacheKey`] but they implement [`Hash`]. /// * Ideally, cache keys are portable /// /// [`Hash`](Hash) pub trait CacheKey { fn cache_key(&self, state: &mut CacheKeyHasher); fn cache_key_slice(data: &[Self], state: &mut CacheKeyHasher) where Self: Sized, { for piece in data { piece.cache_key(state); } } } impl CacheKey for bool { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u8(u8::from(*self)); } } impl CacheKey for char { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u32(*self as u32); } } impl CacheKey for usize { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(*self); } } impl CacheKey for u128 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u128(*self); } } impl CacheKey for u64 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u64(*self); } } impl CacheKey for u32 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u32(*self); } } impl CacheKey for u16 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u16(*self); } } impl CacheKey for u8 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u8(*self); } } impl CacheKey for isize { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_isize(*self); } } impl CacheKey for i128 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_i128(*self); } } impl CacheKey for i64 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_i64(*self); } } impl CacheKey for i32 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_i32(*self); } } impl CacheKey for i16 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_i16(*self); } } impl CacheKey for i8 { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_i8(*self); } } macro_rules! impl_cache_key_non_zero { ($name:ident) => { impl CacheKey for $name { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { self.get().cache_key(state) } } }; } impl_cache_key_non_zero!(NonZeroU8); impl_cache_key_non_zero!(NonZeroU16); impl_cache_key_non_zero!(NonZeroU32); impl_cache_key_non_zero!(NonZeroU64); impl_cache_key_non_zero!(NonZeroU128); impl_cache_key_non_zero!(NonZeroI8); impl_cache_key_non_zero!(NonZeroI16); impl_cache_key_non_zero!(NonZeroI32); impl_cache_key_non_zero!(NonZeroI64); impl_cache_key_non_zero!(NonZeroI128); macro_rules! impl_cache_key_tuple { () => ( impl CacheKey for () { #[inline] fn cache_key(&self, _state: &mut CacheKeyHasher) {} } ); ( $($name:ident)+) => ( impl<$($name: CacheKey),+> CacheKey for ($($name,)+) where last_type!($($name,)+): ?Sized { #[expect(non_snake_case)] #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { let ($(ref $name,)+) = *self; $($name.cache_key(state);)+ } } ); } macro_rules! last_type { ($a:ident,) => { $a }; ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; } impl_cache_key_tuple! {} impl_cache_key_tuple! { T } impl_cache_key_tuple! { T B } impl_cache_key_tuple! { T B C } impl_cache_key_tuple! { T B C D } impl_cache_key_tuple! { T B C D E } impl_cache_key_tuple! { T B C D E F } impl_cache_key_tuple! { T B C D E F G } impl_cache_key_tuple! { T B C D E F G H } impl_cache_key_tuple! { T B C D E F G H I } impl_cache_key_tuple! { T B C D E F G H I J } impl_cache_key_tuple! { T B C D E F G H I J K } impl_cache_key_tuple! { T B C D E F G H I J K L } impl CacheKey for str { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { self.hash(&mut *state); } } impl CacheKey for String { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { self.hash(&mut *state); } } impl CacheKey for CharStr { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { self.as_str().cache_key(state); } } impl CacheKey for Option { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { match self { None => state.write_usize(0), Some(value) => { state.write_usize(1); value.cache_key(state); } } } } impl CacheKey for [T] { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); CacheKey::cache_key_slice(self, state); } } impl CacheKey for &T { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { (**self).cache_key(state); } } impl CacheKey for &mut T { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { (**self).cache_key(state); } } impl CacheKey for Vec where T: CacheKey, { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); CacheKey::cache_key_slice(self, state); } } impl CacheKey for HashMap where K: CacheKey + Ord, V: CacheKey, { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); for (key, value) in self .iter() .sorted_by(|(left, _), (right, _)| left.cmp(right)) { key.cache_key(state); value.cache_key(state); } } } impl CacheKey for HashSet { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); for value in self.iter().sorted() { value.cache_key(state); } } } impl CacheKey for BTreeSet { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); for item in self { item.cache_key(state); } } } impl CacheKey for BTreeMap { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_usize(self.len()); for (key, value) in self { key.cache_key(state); value.cache_key(state); } } } impl CacheKey for Path { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { for component in self.components() { component.hash(&mut *state); } } } impl CacheKey for PathBuf { #[inline] fn cache_key(&self, state: &mut CacheKeyHasher) { self.as_path().cache_key(state); } } impl CacheKey for Cow<'_, V> where V: CacheKey + ToOwned, { fn cache_key(&self, state: &mut CacheKeyHasher) { (**self).cache_key(state); } } impl CacheKey for Regex { fn cache_key(&self, state: &mut CacheKeyHasher) { self.as_str().cache_key(state); } } impl CacheKey for Pattern { fn cache_key(&self, state: &mut CacheKeyHasher) { self.as_str().cache_key(state); } } #[derive(Clone, Default)] pub struct CacheKeyHasher { inner: SeaHasher, } impl CacheKeyHasher { pub fn new() -> Self { Self { inner: SeaHasher::new(), } } } impl Hasher for CacheKeyHasher { #[inline] fn finish(&self) -> u64 { self.inner.finish() } #[inline] fn write(&mut self, bytes: &[u8]) { self.inner.write(bytes); } #[inline] fn write_u8(&mut self, i: u8) { self.inner.write_u8(i); } #[inline] fn write_u16(&mut self, i: u16) { self.inner.write_u16(i); } #[inline] fn write_u32(&mut self, i: u32) { self.inner.write_u32(i); } #[inline] fn write_u64(&mut self, i: u64) { self.inner.write_u64(i); } #[inline] fn write_u128(&mut self, i: u128) { self.inner.write_u128(i); } #[inline] fn write_usize(&mut self, i: usize) { self.inner.write_usize(i); } #[inline] fn write_i8(&mut self, i: i8) { self.inner.write_i8(i); } #[inline] fn write_i16(&mut self, i: i16) { self.inner.write_i16(i); } #[inline] fn write_i32(&mut self, i: i32) { self.inner.write_i32(i); } #[inline] fn write_i64(&mut self, i: i64) { self.inner.write_i64(i); } #[inline] fn write_i128(&mut self, i: i128) { self.inner.write_i128(i); } #[inline] fn write_isize(&mut self, i: isize) { self.inner.write_isize(i); } } ast_serialize-0.13.1/crates/ruff_cache/src/filetime.rs000064400000000000000000000003221046102023000176420ustar00use std::hash::Hash; use filetime::FileTime; use crate::{CacheKey, CacheKeyHasher}; impl CacheKey for FileTime { fn cache_key(&self, state: &mut CacheKeyHasher) { self.hash(&mut *state); } } ast_serialize-0.13.1/crates/ruff_cache/src/globset.rs000064400000000000000000000005151046102023000175070ustar00use globset::{Glob, GlobMatcher}; use crate::{CacheKey, CacheKeyHasher}; impl CacheKey for GlobMatcher { fn cache_key(&self, state: &mut CacheKeyHasher) { self.glob().cache_key(state); } } impl CacheKey for Glob { fn cache_key(&self, state: &mut CacheKeyHasher) { self.glob().cache_key(state); } } ast_serialize-0.13.1/crates/ruff_cache/src/lib.rs000064400000000000000000000005111046102023000166120ustar00use std::path::{Path, PathBuf}; pub use cache_key::{CacheKey, CacheKeyHasher}; mod cache_key; pub mod filetime; pub mod globset; pub const CACHE_DIR_NAME: &str = ".ruff_cache"; /// Return the cache directory for a given project root. pub fn cache_dir(project_root: &Path) -> PathBuf { project_root.join(CACHE_DIR_NAME) } ast_serialize-0.13.1/crates/ruff_cache/tests/cache_key.rs000064400000000000000000000056011046102023000203370ustar00use std::hash::{Hash, Hasher}; use ruff_cache::{CacheKey, CacheKeyHasher}; use ruff_macros::CacheKey; #[test] fn unit_struct_cache_key() { #[derive(CacheKey, Hash)] struct UnitStruct; let mut key = CacheKeyHasher::new(); UnitStruct.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); UnitStruct.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[test] fn named_field_struct() { #[derive(CacheKey, Hash)] struct NamedFieldsStruct { a: String, b: String, } let mut key = CacheKeyHasher::new(); let named_fields = NamedFieldsStruct { a: "Hello".into(), b: "World".into(), }; named_fields.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); named_fields.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[test] fn struct_ignored_fields() { #[derive(CacheKey)] struct NamedFieldsStruct { a: String, #[cache_key(ignore)] #[expect(unused)] b: String, } impl Hash for NamedFieldsStruct { fn hash(&self, state: &mut H) { self.a.hash(state); } } let mut key = CacheKeyHasher::new(); let named_fields = NamedFieldsStruct { a: "Hello".into(), b: "World".into(), }; named_fields.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); named_fields.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[test] fn unnamed_field_struct() { #[derive(CacheKey, Hash)] struct UnnamedFieldsStruct(String, String); let mut key = CacheKeyHasher::new(); let unnamed_fields = UnnamedFieldsStruct("Hello".into(), "World".into()); unnamed_fields.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); unnamed_fields.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[derive(CacheKey, Hash)] enum Enum { Unit, UnnamedFields(String, String), NamedFields { a: String, b: String }, } #[test] fn enum_unit_variant() { let mut key = CacheKeyHasher::new(); let variant = Enum::Unit; variant.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); variant.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[test] fn enum_named_fields_variant() { let mut key = CacheKeyHasher::new(); let variant = Enum::NamedFields { a: "Hello".to_string(), b: "World".to_string(), }; variant.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); variant.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } #[test] fn enum_unnamed_fields_variant() { let mut key = CacheKeyHasher::new(); let variant = Enum::UnnamedFields("Hello".to_string(), "World".to_string()); variant.cache_key(&mut key); let mut hash = CacheKeyHasher::new(); variant.hash(&mut hash); assert_eq!(hash.finish(), key.finish()); } ast_serialize-0.13.1/crates/ruff_macros/Cargo.toml000064400000000000000000000013711046102023000170650ustar00[package] name = "ruff_macros" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [lib] proc-macro = true doctest = false test = false [dependencies] ruff_python_trivia = { workspace = true } heck = { workspace = true } itertools = { workspace = true } proc-macro2 = { workspace = true } quote = { workspace = true } regex = { workspace = true } syn = { workspace = true, features = ["derive", "parsing", "extra-traits", "full"] } [lints] workspace = true ast_serialize-0.13.1/crates/ruff_macros/README.md000064400000000000000000000010241046102023000164070ustar00 # ruff_macros This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_macros). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_macros/src/cache_key.rs000064400000000000000000000116121046102023000202040ustar00use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; use syn::{Data, DeriveInput, Error, Field, Fields, Token}; pub(crate) fn derive_cache_key(item: &DeriveInput) -> syn::Result { let fields = match &item.data { Data::Enum(item_enum) => { let arms = item_enum.variants.iter().enumerate().map(|(i, variant)| { let variant_name = &variant.ident; match &variant.fields { Fields::Named(fields) => { let field_names: Vec<_> = fields .named .iter() .map(|field| field.ident.clone().unwrap()) .collect(); let fields_code = field_names .iter() .map(|field| quote!(#field.cache_key(key);)); quote! { Self::#variant_name{#(#field_names),*} => { key.write_usize(#i); #(#fields_code)* } } } Fields::Unnamed(fields) => { let field_names: Vec<_> = fields .unnamed .iter() .enumerate() .map(|(i, _)| format_ident!("field_{i}")) .collect(); let fields_code = field_names .iter() .map(|field| quote!(#field.cache_key(key);)); quote! { Self::#variant_name(#(#field_names),*) => { key.write_usize(#i); #(#fields_code)* } } } Fields::Unit => { quote! { Self::#variant_name => { key.write_usize(#i); } } } } }); quote! { match self { #(#arms)* } } } Data::Struct(item_struct) => { let mut fields = Vec::with_capacity(item_struct.fields.len()); for (i, field) in item_struct.fields.iter().enumerate() { if let Some(cache_field_attribute) = cache_key_field_attribute(field)? { if cache_field_attribute.ignore { continue; } } let field_attr = if let Some(ident) = &field.ident { quote!(self.#ident) } else { let index = syn::Index::from(i); quote!(self.#index) }; fields.push(quote!(#field_attr.cache_key(key);)); } quote! {#(#fields)*} } Data::Union(_) => { return Err(Error::new( item.span(), "CacheKey does not support unions. Only structs and enums are supported", )); } }; let name = &item.ident; let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl(); Ok(quote!( #[automatically_derived] impl #impl_generics ruff_cache::CacheKey for #name #ty_generics #where_clause { fn cache_key(&self, key: &mut ruff_cache::CacheKeyHasher) { use std::hash::Hasher; use ruff_cache::CacheKey; #fields } } )) } fn cache_key_field_attribute(field: &Field) -> syn::Result> { if let Some(attribute) = field .attrs .iter() .find(|attribute| attribute.path().is_ident("cache_key")) { attribute.parse_args::().map(Some) } else { Ok(None) } } #[derive(Debug, Default)] struct CacheKeyFieldAttributes { ignore: bool, } impl Parse for CacheKeyFieldAttributes { fn parse(input: ParseStream) -> syn::Result { let mut attributes = CacheKeyFieldAttributes::default(); let args = input.parse_terminated(Ident::parse, Token![,])?; for arg in args { match arg.to_string().as_str() { "ignore" => { attributes.ignore = true; } name => { return Err(Error::new( arg.span(), format!("Unknown `cache_field` argument {name}"), )); } } } Ok(attributes) } } ast_serialize-0.13.1/crates/ruff_macros/src/combine.rs000064400000000000000000000021641046102023000177070ustar00use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::{Data, DataStruct, DeriveInput}; pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result { let DeriveInput { ident, data, .. } = input; match data { Data::Struct(DataStruct { fields, .. }) => { let output: Vec<_> = fields .members() .map(|member| { quote_spanned!( member.span() => ty_combine::Combine::combine_with(&mut self.#member, other.#member) ) }) .collect(); Ok(quote! { #[automatically_derived] impl ty_combine::Combine for #ident { #[allow(deprecated)] fn combine_with(&mut self, other: Self) { #( #output );* } } }) } _ => Err(syn::Error::new( ident.span(), "Can only derive Combine from structs.", )), } } ast_serialize-0.13.1/crates/ruff_macros/src/combine_options.rs000064400000000000000000000036421046102023000214640ustar00use quote::{quote, quote_spanned}; use syn::{Data, DataStruct, DeriveInput, Field, Fields, Path, PathSegment, Type, TypePath}; pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result { let DeriveInput { ident, data, .. } = input; match data { Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => { let output = fields .named .iter() .map(handle_field) .collect::, _>>()?; Ok(quote! { #[automatically_derived] impl crate::configuration::CombinePluginOptions for #ident { fn combine(self, other: Self) -> Self { #[expect(deprecated)] Self { #( #output ),* } } } }) } _ => Err(syn::Error::new( ident.span(), "Can only derive CombineOptions from structs with named fields.", )), } } fn handle_field(field: &Field) -> syn::Result { let ident = field .ident .as_ref() .expect("Expected to handle named fields"); match &field.ty { Type::Path(TypePath { path: Path { segments, .. }, .. }) => match segments.first() { Some(PathSegment { ident: type_ident, .. }) if type_ident == "Option" => Ok(quote_spanned!( ident.span() => #ident: self.#ident.or(other.#ident) )), _ => Err(syn::Error::new( ident.span(), "Expected `Option<_>` or `Vec<_>` as type.", )), }, _ => Err(syn::Error::new(ident.span(), "Expected type.")), } } ast_serialize-0.13.1/crates/ruff_macros/src/config.rs000064400000000000000000000263741046102023000175510ustar00use proc_macro2::{TokenStream, TokenTree}; use quote::{quote, quote_spanned}; use syn::meta::ParseNestedMeta; use syn::spanned::Spanned; use syn::{ AngleBracketedGenericArguments, Attribute, Data, DataStruct, DeriveInput, ExprLit, Field, Fields, Lit, LitStr, Meta, Path, PathArguments, PathSegment, Type, TypePath, }; use ruff_python_trivia::textwrap::dedent; pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result { let DeriveInput { ident, data, attrs: struct_attributes, .. } = input; match data { Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => { let mut output = vec![]; for field in &fields.named { if let Some(attr) = field .attrs .iter() .find(|attr| attr.path().is_ident("option")) { output.push(handle_option(field, attr)?); } else if field .attrs .iter() .any(|attr| attr.path().is_ident("option_group")) { output.push(handle_option_group(field)?); } else if let Some(serde) = field .attrs .iter() .find(|attr| attr.path().is_ident("serde")) { // If a field has the `serde(flatten)` attribute, flatten the options into the parent // by calling `Type::record` instead of `visitor.visit_set` if let (Type::Path(ty), Meta::List(list)) = (&field.ty, &serde.meta) { for token in list.tokens.clone() { if let TokenTree::Ident(ident) = token { if ident == "flatten" { output.push(quote_spanned!( ty.span() => (<#ty>::record(visit)) )); break; } } } } } } let docs = struct_attributes .iter() .filter(|attr| attr.path().is_ident("doc")); // Convert the list of `doc` attributes into a single string. let doc = dedent( &docs .map(parse_doc) .collect::>>()? .join("\n"), ) .trim_matches('\n') .to_string(); let documentation = if doc.is_empty() { None } else { Some(quote!( fn documentation() -> Option<&'static str> { Some(&#doc) } )) }; Ok(quote! { #[automatically_derived] impl ruff_options_metadata::OptionsMetadata for #ident { fn record(visit: &mut dyn ruff_options_metadata::Visit) { #(#output);* } #documentation } }) } _ => Err(syn::Error::new( ident.span(), "Can only derive ConfigurationOptions from structs with named fields.", )), } } /// For a field with type `Option` where `Foobar` itself is a struct /// deriving `ConfigurationOptions`, create code that calls retrieves options /// from that group: `Foobar::get_available_options()` fn handle_option_group(field: &Field) -> syn::Result { let ident = field .ident .as_ref() .expect("Expected to handle named fields"); match &field.ty { Type::Path(TypePath { path: Path { segments, .. }, .. }) => match segments.first() { Some(PathSegment { ident: type_ident, arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }), }) if type_ident == "Option" => { let path = &args[0]; let kebab_name = LitStr::new(&ident.to_string().replace('_', "-"), ident.span()); Ok(quote_spanned!( ident.span() => (visit.record_set(#kebab_name, ruff_options_metadata::OptionSet::of::<#path>())) )) } _ => Err(syn::Error::new( ident.span(), "Expected `Option<_>` as type.", )), }, _ => Err(syn::Error::new(ident.span(), "Expected type.")), } } /// Parse a `doc` attribute into it a string literal. fn parse_doc(doc: &Attribute) -> syn::Result { match &doc.meta { syn::Meta::NameValue(syn::MetaNameValue { value: syn::Expr::Lit(ExprLit { lit: Lit::Str(lit_str), .. }), .. }) => Ok(lit_str.value()), _ => Err(syn::Error::new(doc.span(), "Expected doc attribute.")), } } /// Parse an `#[option(doc="...", default="...", value_type="...", /// example="...")]` attribute and return data in the form of an `OptionField`. fn handle_option(field: &Field, attr: &Attribute) -> syn::Result { let docs: Vec<&Attribute> = field .attrs .iter() .filter(|attr| attr.path().is_ident("doc")) .collect(); if docs.is_empty() { return Err(syn::Error::new( field.span(), "Missing documentation for field", )); } // Convert the list of `doc` attributes into a single string. let doc = dedent( &docs .into_iter() .map(parse_doc) .collect::>>()? .join("\n"), ) .trim_matches('\n') .to_string(); let ident = field .ident .as_ref() .expect("Expected to handle named fields"); let FieldAttributes { default, value_type, example, scope, } = parse_field_attributes(attr)?; let kebab_name = LitStr::new(&ident.to_string().replace('_', "-"), ident.span()); let scope = if let Some(scope) = scope { quote!(Some(#scope)) } else { quote!(None) }; let deprecated = if let Some(deprecated) = field .attrs .iter() .find(|attr| attr.path().is_ident("deprecated")) { fn quote_option(option: Option) -> TokenStream { match option { None => quote!(None), Some(value) => quote!(Some(#value)), } } let deprecated = parse_deprecated_attribute(deprecated)?; let note = quote_option(deprecated.note); let since = quote_option(deprecated.since); quote!(Some(ruff_options_metadata::Deprecated { since: #since, message: #note })) } else { quote!(None) }; Ok(quote_spanned!( ident.span() => { visit.record_field(#kebab_name, ruff_options_metadata::OptionField{ doc: &#doc, default: &#default, value_type: &#value_type, example: &#example, scope: #scope, deprecated: #deprecated }) } )) } #[derive(Debug)] struct FieldAttributes { default: String, value_type: String, example: String, scope: Option, } fn parse_field_attributes(attribute: &Attribute) -> syn::Result { let mut default = None; let mut value_type = None; let mut example = None; let mut scope = None; attribute.parse_nested_meta(|meta| { if meta.path.is_ident("default") { default = Some(get_string_literal(&meta, "default", "option")?.value()); } else if meta.path.is_ident("value_type") { value_type = Some(get_string_literal(&meta, "value_type", "option")?.value()); } else if meta.path.is_ident("scope") { scope = Some(get_string_literal(&meta, "scope", "option")?.value()); } else if meta.path.is_ident("example") { let example_text = get_string_literal(&meta, "value_type", "option")?.value(); example = Some(dedent(&example_text).trim_matches('\n').to_string()); } else { return Err(syn::Error::new( meta.path.span(), format!( "Deprecated meta {:?} is not supported by ruff's option macro.", meta.path.get_ident() ), )); } Ok(()) })?; let Some(default) = default else { return Err(syn::Error::new( attribute.span(), "Mandatory `default` field is missing in `#[option]` attribute. Specify the default using `#[option(default=\"..\")]`.", )); }; let Some(value_type) = value_type else { return Err(syn::Error::new( attribute.span(), "Mandatory `value_type` field is missing in `#[option]` attribute. Specify the value type using `#[option(value_type=\"..\")]`.", )); }; let Some(example) = example else { return Err(syn::Error::new( attribute.span(), "Mandatory `example` field is missing in `#[option]` attribute. Add an example using `#[option(example=\"..\")]`.", )); }; Ok(FieldAttributes { default, value_type, example, scope, }) } fn parse_deprecated_attribute(attribute: &Attribute) -> syn::Result { let mut deprecated = DeprecatedAttribute::default(); attribute.parse_nested_meta(|meta| { if meta.path.is_ident("note") { deprecated.note = Some(get_string_literal(&meta, "note", "deprecated")?.value()); } else if meta.path.is_ident("since") { deprecated.since = Some(get_string_literal(&meta, "since", "deprecated")?.value()); } else { return Err(syn::Error::new( meta.path.span(), format!( "Deprecated meta {:?} is not supported by ruff's option macro.", meta.path.get_ident() ), )); } Ok(()) })?; Ok(deprecated) } fn get_string_literal( meta: &ParseNestedMeta, meta_name: &str, attribute_name: &str, ) -> syn::Result { let expr: syn::Expr = meta.value()?.parse()?; let mut value = &expr; while let syn::Expr::Group(e) = value { value = &e.expr; } if let syn::Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) = value { let suffix = lit.suffix(); if !suffix.is_empty() { return Err(syn::Error::new( lit.span(), format!("unexpected suffix `{suffix}` on string literal"), )); } Ok(lit.clone()) } else { Err(syn::Error::new( expr.span(), format!("expected {attribute_name} attribute to be a string: `{meta_name} = \"...\"`"), )) } } #[derive(Default, Debug)] struct DeprecatedAttribute { since: Option, note: Option, } ast_serialize-0.13.1/crates/ruff_macros/src/derive_message_formats.rs000064400000000000000000000071111046102023000230050ustar00use proc_macro2::TokenStream; use quote::{ToTokens, quote, quote_spanned}; use syn::spanned::Spanned; use syn::token::{Dot, Paren}; use syn::{Block, Expr, ExprLit, ExprMethodCall, ItemFn, Lit, Stmt}; pub(crate) fn derive_message_formats(func: &ItemFn) -> TokenStream { let mut strings = quote!(); if let Err(err) = parse_block(&func.block, &mut strings) { return err; } quote! { #func fn message_formats() -> &'static [&'static str] { &[#strings] } } } fn parse_block(block: &Block, strings: &mut TokenStream) -> Result<(), TokenStream> { let Some(Stmt::Expr(last, _)) = block.stmts.last() else { panic!("expected last statement in block to be an expression") }; parse_expr(last, strings)?; Ok(()) } fn parse_expr(expr: &Expr, strings: &mut TokenStream) -> Result<(), TokenStream> { match expr { Expr::Macro(mac) if mac.mac.path.is_ident("format") => { let mut tokens = mac.mac.tokens.to_token_stream().into_iter(); let Some(first_token) = tokens.next() else { return Err( quote_spanned!(expr.span() => compile_error!("expected `format!` to have an argument")), ); }; // do not throw an error if the `format!` argument contains a formatting argument if !first_token.to_string().contains('{') { // comma and string if tokens.next().is_none() || tokens.next().is_none() { return Err( quote_spanned!(expr.span() => compile_error!("prefer `String::to_string` over `format!` without arguments")), ); } } strings.extend(quote! {#first_token,}); Ok(()) } Expr::Block(block) => parse_block(&block.block, strings), Expr::If(expr) => { parse_block(&expr.then_branch, strings)?; if let Some((_, then)) = &expr.else_branch { parse_expr(then, strings)?; } Ok(()) } Expr::MethodCall(method_call) => match method_call { ExprMethodCall { method, receiver, attrs, dot_token, turbofish: None, paren_token, args, } if *method == *"to_string" && attrs.is_empty() && args.is_empty() && *paren_token == Paren::default() && *dot_token == Dot::default() => { let Expr::Lit(ExprLit { lit: Lit::Str(ref literal_string), .. }) = **receiver else { return Err( quote_spanned!(expr.span() => compile_error!("expected `String::to_string` method on str literal")), ); }; let str_token = literal_string.token(); strings.extend(quote! {#str_token,}); Ok(()) } _ => Err( quote_spanned!(expr.span() => compile_error!("expected `String::to_string` method on str literal")), ), }, Expr::Match(block) => { for arm in &block.arms { parse_expr(&arm.body, strings)?; } Ok(()) } _ => Err(quote_spanned!( expr.span() => compile_error!("expected last expression to be a `format!` macro, a static String or a match block") )), } } ast_serialize-0.13.1/crates/ruff_macros/src/env_vars.rs000064400000000000000000000056041046102023000201200ustar00use proc_macro2::TokenStream; use quote::quote; use syn::{ImplItem, ItemImpl}; pub(crate) fn attribute_env_vars_metadata(mut input: ItemImpl) -> TokenStream { // Verify that this is an impl for EnvVars let impl_type = &input.self_ty; let mut env_var_entries = Vec::new(); let mut hidden_vars = Vec::new(); // Process each item in the impl block for item in &mut input.items { if let ImplItem::Const(const_item) = item { // Extract the const name and value let const_name = &const_item.ident; let const_expr = &const_item.expr; // Check if the const has the #[attr_hidden] attribute let is_hidden = const_item .attrs .iter() .any(|attr| attr.path().is_ident("attr_hidden")); // Remove our custom attributes const_item.attrs.retain(|attr| { !attr.path().is_ident("attr_hidden") && !attr.path().is_ident("attr_env_var_pattern") }); if is_hidden { hidden_vars.push(const_name.clone()); } else { // Extract documentation from doc comments let doc_attrs: Vec<_> = const_item .attrs .iter() .filter(|attr| attr.path().is_ident("doc")) .collect(); if !doc_attrs.is_empty() { // Convert doc attributes to a single string let doc_string = extract_doc_string(&doc_attrs); env_var_entries.push((const_name.clone(), const_expr.clone(), doc_string)); } } } } // Generate the metadata method. let metadata_entries: Vec<_> = env_var_entries .iter() .map(|(_name, expr, doc)| { quote! { (#expr, #doc) } }) .collect(); let metadata_impl = quote! { impl #impl_type { /// Returns metadata for all non-hidden environment variables. pub fn metadata() -> Vec<(&'static str, &'static str)> { vec![ #(#metadata_entries),* ] } } }; quote! { #input #metadata_impl } } /// Extract documentation from doc attributes into a single string fn extract_doc_string(attrs: &[&syn::Attribute]) -> String { attrs .iter() .filter_map(|attr| { if let syn::Meta::NameValue(meta) = &attr.meta { if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }) = &meta.value { return Some(lit_str.value().trim().to_string()); } } None }) .collect::>() .join("\n") } ast_serialize-0.13.1/crates/ruff_macros/src/kebab_case.rs000064400000000000000000000004071046102023000203300ustar00use heck::ToKebabCase; use proc_macro2::TokenStream; pub(crate) fn kebab_case(input: &syn::Ident) -> TokenStream { let s = input.to_string(); let kebab_case_lit = syn::LitStr::new(&s.to_kebab_case(), input.span()); quote::quote!(#kebab_case_lit) } ast_serialize-0.13.1/crates/ruff_macros/src/lib.rs000064400000000000000000000117101046102023000170360ustar00//! This crate implements internal macros for the `ruff` and `ty` libraries. use crate::cache_key::derive_cache_key; use crate::newtype_index::generate_newtype_index; use crate::violation_metadata::violation_metadata; use proc_macro::TokenStream; use syn::{DeriveInput, Error, ItemFn, ItemStruct, parse_macro_input}; mod cache_key; mod combine; mod combine_options; mod config; mod derive_message_formats; mod env_vars; mod kebab_case; mod map_codes; mod newtype_index; mod rule_code_prefix; mod rule_namespace; mod rust_doc; mod violation_metadata; #[proc_macro_derive(OptionsMetadata, attributes(option, option_group))] pub fn derive_options_metadata(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); config::derive_impl(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(RustDoc)] pub fn derive_rust_doc(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); rust_doc::derive_impl(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(CombineOptions)] pub fn derive_combine_options(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); combine_options::derive_impl(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } /// Automatically derives a `ty_combine::Combine` implementation for the attributed type /// that calls `ty_combine::Combine::combine` for each field. /// /// The derive macro can only be used on structs. Enums aren't yet supported. #[proc_macro_derive(Combine)] pub fn derive_combine(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); combine::derive_impl(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } /// Converts an identifier to a kebab case string. #[proc_macro] pub fn kebab_case(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as syn::Ident); kebab_case::kebab_case(&input).into() } /// Generates a [`CacheKey`] implementation for the attributed type. /// /// Struct fields can be attributed with the `cache_key` field-attribute that supports: /// * `ignore`: Ignore the attributed field in the cache key #[proc_macro_derive(CacheKey, attributes(cache_key))] pub fn cache_key(input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as DeriveInput); let result = derive_cache_key(&item); let stream = result.unwrap_or_else(|err| err.to_compile_error()); TokenStream::from(stream) } #[proc_macro_derive(ViolationMetadata, attributes(violation_metadata))] pub fn derive_violation_metadata(item: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(item); violation_metadata(input) .unwrap_or_else(Error::into_compile_error) .into() } #[proc_macro_derive(RuleNamespace, attributes(prefix))] pub fn derive_rule_namespace(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); rule_namespace::derive_impl(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_attribute] pub fn map_codes(_attr: TokenStream, item: TokenStream) -> TokenStream { let func = parse_macro_input!(item as ItemFn); map_codes::map_codes(&func) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_attribute] pub fn derive_message_formats(_attr: TokenStream, item: TokenStream) -> TokenStream { let func = parse_macro_input!(item as ItemFn); derive_message_formats::derive_message_formats(&func).into() } /// Derives a newtype wrapper that can be used as an index. /// The wrapper can represent indices up to `u32::MAX - 1`. /// /// The `u32::MAX - 1` is an optimization so that `Option` has the same size as `Index`. /// /// Can store at most `u32::MAX - 1` values /// /// ## Warning /// /// Additional `derive` attributes must come AFTER this attribute: /// /// Good: /// /// ```ignore /// use ruff_macros::newtype_index; /// /// #[newtype_index] /// #[derive(Ord, PartialOrd)] /// struct MyIndex; /// ``` #[proc_macro_attribute] pub fn newtype_index(_metadata: TokenStream, input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as ItemStruct); let output = match generate_newtype_index(item) { Ok(output) => output, Err(err) => err.to_compile_error(), }; TokenStream::from(output) } /// Generates metadata for environment variables declared in the impl block. /// /// This attribute macro should be applied to an `impl EnvVars` block. /// It will generate a `metadata()` method that returns all non-hidden /// environment variables with their documentation. #[proc_macro_attribute] pub fn attribute_env_vars_metadata(_attr: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as syn::ItemImpl); env_vars::attribute_env_vars_metadata(input).into() } ast_serialize-0.13.1/crates/ruff_macros/src/map_codes.rs000064400000000000000000000420771046102023000202340ustar00use std::collections::{BTreeMap, HashMap}; use itertools::Itertools; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::{ Attribute, Error, Expr, ExprCall, ExprMatch, Ident, ItemFn, LitStr, Pat, Path, Stmt, Token, parenthesized, parse::Parse, spanned::Spanned, }; use crate::{ kebab_case::kebab_case, rule_code_prefix::{get_prefix_ident, intersection_all}, }; /// A rule entry in the big match statement such a /// `(Pycodestyle, "E112") => (RuleGroup::Preview, rules::pycodestyle::rules::logical_lines::NoIndentedBlock),` #[derive(Clone)] struct Rule { /// The actual name of the rule, e.g., `NoIndentedBlock`. name: Ident, /// The linter associated with the rule, e.g., `Pycodestyle`. linter: Ident, /// The code associated with the rule, e.g., `"E112"`. code: LitStr, /// The path to the struct implementing the rule, e.g. /// `rules::pycodestyle::rules::logical_lines::NoIndentedBlock` path: Path, /// The rule attributes, e.g. for feature gates attrs: Vec, } pub(crate) fn map_codes(func: &ItemFn) -> syn::Result { let Some(last_stmt) = func.block.stmts.last() else { return Err(Error::new( func.block.span(), "expected body to end in an expression", )); }; let Stmt::Expr( Expr::Call(ExprCall { args: some_args, .. }), _, ) = last_stmt else { return Err(Error::new( last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`", )); }; let mut some_args = some_args.into_iter(); let (Some(Expr::Match(ExprMatch { arms, .. })), None) = (some_args.next(), some_args.next()) else { return Err(Error::new( last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`", )); }; // Map from: linter (e.g., `Flake8Bugbear`) to rule code (e.g.,`"002"`) to rule data (e.g., // `(Rule::UnaryPrefixIncrement, RuleGroup::Stable, vec![])`). let mut linter_to_rules: BTreeMap> = BTreeMap::new(); for arm in arms { if matches!(arm.pat, Pat::Wild(..)) { break; } let rule = syn::parse::(arm.into_token_stream().into())?; linter_to_rules .entry(rule.linter.clone()) .or_default() .insert(rule.code.value(), rule); } let linter_idents: Vec<_> = linter_to_rules.keys().collect(); let all_rules = linter_to_rules.values().flat_map(BTreeMap::values); let mut output = register_rules(all_rules); output.extend(quote! { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum RuleCodePrefix { #(#linter_idents(#linter_idents),)* } impl RuleCodePrefix { pub fn linter(&self) -> &'static Linter { match self { #(Self::#linter_idents(..) => &Linter::#linter_idents,)* } } pub fn short_code(&self) -> &'static str { match self { #(Self::#linter_idents(code) => code.into(),)* } } } }); for (linter, rules) in &linter_to_rules { output.extend(super::rule_code_prefix::expand( linter, rules .iter() .map(|(code, Rule { attrs, .. })| (code.as_str(), attrs)), )); output.extend(quote! { impl From<#linter> for RuleCodePrefix { fn from(linter: #linter) -> Self { Self::#linter(linter) } } // Rust doesn't yet support `impl const From for RuleSelector` // See https://github.com/rust-lang/rust/issues/67792 impl From<#linter> for crate::rule_selector::RuleSelector { fn from(linter: #linter) -> Self { let prefix = RuleCodePrefix::#linter(linter); if let Some(rule) = prefix.as_rule() { Self::Rule { rule, redirected_from: None, } } else { Self::Prefix { prefix, redirected_from: None, } } } } }); } let mut all_codes = Vec::new(); for (linter, rules) in &linter_to_rules { let rules_by_prefix = rules_by_prefix(rules); for (prefix, rules) in &rules_by_prefix { let prefix_ident = get_prefix_ident(prefix); let attrs = intersection_all(rules.iter().map(|(.., attrs)| attrs.as_slice())); let attrs = if attrs.is_empty() { quote!() } else { quote!(#(#attrs)*) }; all_codes.push(quote! { #attrs Self::#linter(#linter::#prefix_ident) }); } let mut prefix_into_iter_match_arms = quote!(); for (prefix, rules) in rules_by_prefix { let rule_paths = rules.iter().map(|(path, .., attrs)| { let rule_name = path.segments.last().unwrap(); quote!(#(#attrs)* Rule::#rule_name) }); let prefix_ident = get_prefix_ident(&prefix); let attrs = intersection_all(rules.iter().map(|(.., attrs)| attrs.as_slice())); let attrs = if attrs.is_empty() { quote!() } else { quote!(#(#attrs)*) }; prefix_into_iter_match_arms.extend(quote! { #attrs #linter::#prefix_ident => vec![#(#rule_paths,)*].into_iter(), }); } output.extend(quote! { impl #linter { pub(crate) fn rules(&self) -> ::std::vec::IntoIter { match self { #prefix_into_iter_match_arms } } } }); } output.extend(quote! { impl RuleCodePrefix { pub(crate) fn parse(linter: &Linter, code: &str) -> Result { use std::str::FromStr; Ok(match linter { #(Linter::#linter_idents => RuleCodePrefix::#linter_idents(#linter_idents::from_str(code).map_err(|_| crate::registry::FromCodeError::Unknown)?),)* }) } pub(crate) fn rules(&self) -> ::std::vec::IntoIter { match self { #(RuleCodePrefix::#linter_idents(prefix) => prefix.clone().rules(),)* } } } }); let rule_to_code = generate_rule_to_code(&linter_to_rules); output.extend(rule_to_code); output.extend(generate_iter_impl(&linter_to_rules, &linter_idents)); Ok(output) } /// Group the rules by their common prefixes. fn rules_by_prefix( rules: &BTreeMap, ) -> BTreeMap)>> { // TODO(charlie): Why do we do this here _and_ in `rule_code_prefix::expand`? let mut rules_by_prefix = BTreeMap::new(); for code in rules.keys() { for i in 1..=code.len() { let prefix = code[..i].to_string(); let rules: Vec<_> = rules .iter() .filter_map(|(code, rule)| { if code.starts_with(&prefix) { Some((rule.path.clone(), rule.attrs.clone())) } else { None } }) .collect(); rules_by_prefix.insert(prefix, rules); } } rules_by_prefix } /// Map from rule to codes that can be used to select it. /// This abstraction exists to support a one-to-many mapping, whereby a single rule could map /// to multiple codes (e.g., if it existed in multiple linters, like Pylint and Flake8, under /// different codes). We haven't actually activated this functionality yet, but some work was /// done to support it, so the logic exists here. fn generate_rule_to_code(linter_to_rules: &BTreeMap>) -> TokenStream { let mut rule_to_codes: HashMap<&Path, Vec<&Rule>> = HashMap::new(); let mut linter_code_for_rule_match_arms = quote!(); for (linter, map) in linter_to_rules { for (code, rule) in map { let Rule { path, attrs, name, .. } = rule; rule_to_codes.entry(path).or_default().push(rule); linter_code_for_rule_match_arms.extend(quote! { #(#attrs)* (Self::#linter, Rule::#name) => Some(#code), }); } } let mut rule_noqa_code_match_arms = quote!(); // Keep the proc-macro output stable so unchanged code can be reused incrementally. for (rule, codes) in rule_to_codes .into_iter() .sorted_by_key(|(rule, _)| rule.to_token_stream().to_string()) { let rule_name = rule.segments.last().unwrap(); assert_eq!( codes.len(), 1, " {} is mapped to multiple codes. The mapping of multiple codes to one rule has been disabled due to UX concerns (it would be confusing if violations were reported under a different code than the code you selected). We firstly want to allow rules to be selected by their names (and report them by name), and before we can do that we have to rename all our rules to match our naming convention (see CONTRIBUTING.md) because after that change every rule rename will be a breaking change. See also https://github.com/astral-sh/ruff/issues/2186. ", rule_name.ident ); let Rule { linter, code, attrs, .. } = codes .iter() .sorted_by_key(|data| data.linter == "Pylint") .next() .unwrap(); rule_noqa_code_match_arms.extend(quote! { #(#attrs)* Rule::#rule_name => NoqaCode(crate::registry::Linter::#linter.common_prefix(), #code), }); } let rule_to_code = quote! { impl Rule { pub fn noqa_code(&self) -> NoqaCode { use crate::registry::RuleNamespace; match self { #rule_noqa_code_match_arms } } pub fn is_preview(&self) -> bool { matches!(self.group(), RuleGroup::Preview { .. }) } pub(crate) fn is_stable(&self) -> bool { matches!(self.group(), RuleGroup::Stable { .. }) } pub fn is_deprecated(&self) -> bool { matches!(self.group(), RuleGroup::Deprecated { .. }) } pub fn is_removed(&self) -> bool { matches!(self.group(), RuleGroup::Removed { .. }) } } impl Linter { pub fn code_for_rule(&self, rule: Rule) -> Option<&'static str> { match (self, rule) { #linter_code_for_rule_match_arms _ => None, } } } }; rule_to_code } /// Implement `impl IntoIterator for &Linter` and `RuleCodePrefix::iter()` fn generate_iter_impl( linter_to_rules: &BTreeMap>, linter_idents: &[&Ident], ) -> TokenStream { let mut linter_rules_match_arms = quote!(); let mut linter_all_rules_match_arms = quote!(); for (linter, map) in linter_to_rules { let rule_paths = map.values().map(|Rule { attrs, path, .. }| { let rule_name = path.segments.last().unwrap(); quote!(#(#attrs)* Rule::#rule_name) }); linter_rules_match_arms.extend(quote! { Linter::#linter => vec![#(#rule_paths,)*].into_iter(), }); let rule_paths = map.values().map(|Rule { attrs, path, .. }| { let rule_name = path.segments.last().unwrap(); quote!(#(#attrs)* Rule::#rule_name) }); linter_all_rules_match_arms.extend(quote! { Linter::#linter => vec![#(#rule_paths,)*].into_iter(), }); } quote! { impl Linter { /// Rules not in the preview. pub(crate) fn rules(self: &Linter) -> ::std::vec::IntoIter { match self { #linter_rules_match_arms } } /// All rules, including those in the preview. pub fn all_rules(self: &Linter) -> ::std::vec::IntoIter { match self { #linter_all_rules_match_arms } } } impl RuleCodePrefix { pub(crate) fn iter() -> impl Iterator { use strum::IntoEnumIterator; let mut prefixes = Vec::new(); #(prefixes.extend(#linter_idents::iter().map(|x| Self::#linter_idents(x)));)* prefixes.into_iter() } } } } /// Generate the `Rule` enum fn register_rules<'a>(input: impl Iterator) -> TokenStream { let mut rule_variants = quote!(); let mut rule_message_formats_match_arms = quote!(); let mut rule_fixable_match_arms = quote!(); let mut rule_explanation_match_arms = quote!(); let mut rule_group_match_arms = quote!(); let mut rule_file_match_arms = quote!(); let mut rule_line_match_arms = quote!(); let mut rule_parse_match_arms = quote!(); for Rule { name, attrs, path, .. } in input { let kebab_name = kebab_case(name); rule_variants.extend(quote! { #(#attrs)* #name, }); // Apply the `attrs` to each arm, like `[cfg(feature = "foo")]`. rule_message_formats_match_arms.extend( quote! {#(#attrs)* Self::#name => <#path as crate::Violation>::message_formats(),}, ); rule_fixable_match_arms.extend( quote! {#(#attrs)* Self::#name => <#path as crate::Violation>::FIX_AVAILABILITY,}, ); rule_explanation_match_arms.extend(quote! {#(#attrs)* Self::#name => #path::explain(),}); rule_group_match_arms.extend( quote! {#(#attrs)* Self::#name => <#path as crate::ViolationMetadata>::group(),}, ); rule_file_match_arms.extend( quote! {#(#attrs)* Self::#name => <#path as crate::ViolationMetadata>::file(),}, ); rule_line_match_arms.extend( quote! {#(#attrs)* Self::#name => <#path as crate::ViolationMetadata>::line(),}, ); rule_parse_match_arms.extend(quote! {#(#attrs)* #kebab_name => Ok(Self::#name),}); } quote! { use crate::Violation; #[derive( EnumIter, Debug, PartialEq, Eq, Copy, Clone, Hash, ::strum_macros::IntoStaticStr, )] #[repr(u16)] #[strum(serialize_all = "kebab-case")] pub enum Rule { #rule_variants } impl Rule { /// Returns the format strings used to report violations of this rule. pub fn message_formats(&self) -> &'static [&'static str] { match self { #rule_message_formats_match_arms } } /// Returns the documentation for this rule. pub fn explanation(&self) -> Option<&'static str> { use crate::ViolationMetadata; match self { #rule_explanation_match_arms } } /// Returns the fix status of this rule. pub const fn fixable(&self) -> crate::FixAvailability { match self { #rule_fixable_match_arms } } pub fn group(&self) -> crate::codes::RuleGroup { match self { #rule_group_match_arms } } pub fn file(&self) -> &'static str { match self { #rule_file_match_arms } } pub fn line(&self) -> u32 { match self { #rule_line_match_arms } } /// Try to parse a kebab-case rule name into a `Rule`. pub fn from_name(name: &str) -> Result { match name { #rule_parse_match_arms _ => Err(FromNameError::Unknown), } } } } } impl Parse for Rule { /// Parses a match arm such as `(Pycodestyle, "E112") => rules::pycodestyle::rules::logical_lines::NoIndentedBlock,` fn parse(input: syn::parse::ParseStream) -> syn::Result { let attrs = Attribute::parse_outer(input)?; let pat_tuple; parenthesized!(pat_tuple in input); let linter: Ident = pat_tuple.parse()?; let _: Token!(,) = pat_tuple.parse()?; let code: LitStr = pat_tuple.parse()?; let _: Token!(=>) = input.parse()?; let rule_path: Path = input.parse()?; let _: Token!(,) = input.parse()?; let rule_name = rule_path.segments.last().unwrap().ident.clone(); Ok(Rule { name: rule_name, linter, code, path: rule_path, attrs, }) } } ast_serialize-0.13.1/crates/ruff_macros/src/newtype_index.rs000064400000000000000000000074051046102023000211600ustar00use quote::quote; use syn::spanned::Spanned; use syn::{Error, ItemStruct}; pub(super) fn generate_newtype_index(item: ItemStruct) -> syn::Result { if !item.fields.is_empty() { return Err(Error::new( item.span(), "A new type index cannot have any fields.", )); } if !item.generics.params.is_empty() { return Err(Error::new( item.span(), "A new type index cannot be generic.", )); } let ItemStruct { attrs, vis, struct_token, ident, generics: _, fields: _, semi_token, } = item; let debug_name = ident.to_string(); let semi_token = semi_token.unwrap_or_default(); let output = quote! { #(#attrs)* #[derive(Copy, Clone, Eq, PartialEq, Hash)] #vis #struct_token #ident(std::num::NonZeroU32)#semi_token impl #ident { const MAX_VALUE: u32 = u32::MAX - 1; const MAX: Self = Self::from_u32(Self::MAX_VALUE); #vis const fn from_usize(value: usize) -> Self { assert!(value <= Self::MAX_VALUE as usize); // SAFETY: // * The `value < u32::MAX` guarantees that the add doesn't overflow. // * The `+ 1` guarantees that the index is not zero Self(std::num::NonZeroU32::new((value as u32) + 1).unwrap()) } #vis const fn from_u32(value: u32) -> Self { assert!(value <= Self::MAX_VALUE); // SAFETY: // * The `value < u32::MAX` guarantees that the add doesn't overflow. // * The `+ 1` guarantees that the index is larger than zero. Self(std::num::NonZeroU32::new(value + 1).unwrap()) } /// Returns the index as a `u32` value #[inline] #vis const fn as_u32(self) -> u32 { self.0.get() - 1 } /// Returns the index as a `usize` value #[inline] #vis const fn as_usize(self) -> usize { self.as_u32() as usize } #[inline] #vis const fn index(self) -> usize { self.as_usize() } } impl std::ops::Add for #ident { type Output = #ident; fn add(self, rhs: usize) -> Self::Output { #ident::from_usize(self.index() + rhs) } } impl std::ops::Add for #ident { type Output = #ident; fn add(self, rhs: Self) -> Self::Output { #ident::from_usize(self.index() + rhs.index()) } } impl std::fmt::Debug for #ident { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple(#debug_name).field(&self.index()).finish() } } impl ruff_index::Idx for #ident { #[inline] fn new(value: usize) -> Self { #ident::from_usize(value) } #[inline] fn index(self) -> usize { self.index() } } impl From for #ident { fn from(value: usize) -> Self { #ident::from_usize(value) } } impl From for #ident { fn from(value: u32) -> Self { #ident::from_u32(value) } } impl From<#ident> for usize { fn from(value: #ident) -> Self { value.as_usize() } } impl From<#ident> for u32 { fn from(value: #ident) -> Self { value.as_u32() } } }; Ok(output) } ast_serialize-0.13.1/crates/ruff_macros/src/rule_code_prefix.rs000064400000000000000000000074151046102023000216150ustar00use std::collections::{BTreeMap, BTreeSet}; use proc_macro2::Span; use quote::quote; use syn::{Attribute, Ident}; pub(crate) fn expand<'a>( prefix_ident: &Ident, variants: impl Iterator)>, ) -> proc_macro2::TokenStream { // Build up a map from prefix to matching RuleCodes. let mut prefix_to_codes: BTreeMap> = BTreeMap::default(); let mut code_to_attributes: BTreeMap = BTreeMap::default(); for (variant, .., attr) in variants { let code_str = variant.to_string(); for i in 1..=code_str.len() { let prefix = code_str[..i].to_string(); prefix_to_codes .entry(prefix) .or_default() .insert(code_str.clone()); } code_to_attributes.insert(code_str, attr); } let variant_strs: Vec<_> = prefix_to_codes.keys().collect(); let variant_idents: Vec<_> = prefix_to_codes .keys() .map(|prefix| { let ident = get_prefix_ident(prefix); quote! { #ident } }) .collect(); let attributes: Vec<_> = prefix_to_codes .values() .map(|codes| attributes_for_prefix(codes, &code_to_attributes)) .collect(); quote! { #[derive( ::strum_macros::EnumIter, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, )] pub enum #prefix_ident { #(#attributes #variant_idents,)* } impl std::str::FromStr for #prefix_ident { type Err = crate::registry::FromCodeError; fn from_str(code: &str) -> Result { match code { #(#attributes #variant_strs => Ok(Self::#variant_idents),)* _ => Err(crate::registry::FromCodeError::Unknown) } } } impl From<&#prefix_ident> for &'static str { fn from(code: &#prefix_ident) -> Self { match code { #(#attributes #prefix_ident::#variant_idents => #variant_strs,)* } } } impl AsRef for #prefix_ident { fn as_ref(&self) -> &str { match self { #(#attributes Self::#variant_idents => #variant_strs,)* } } } } } fn attributes_for_prefix( codes: &BTreeSet, attributes: &BTreeMap, ) -> proc_macro2::TokenStream { let attrs = intersection_all(codes.iter().map(|code| attributes[code])); if attrs.is_empty() { quote!() } else { quote!(#(#attrs)*) } } /// Collect all the items from an iterable of slices that are present in all slices. pub(crate) fn intersection_all<'a, T: PartialEq>( mut slices: impl Iterator, ) -> Vec<&'a T> { if let Some(slice) = slices.next() { // Collect all the items in the first slice let mut intersection = Vec::with_capacity(slice.len()); for item in slice { intersection.push(item); } // Then only keep items that are present in each of the remaining slices for slice in slices { intersection.retain(|item| slice.contains(item)); } intersection } else { Vec::new() } } /// Returns an identifier for the given prefix. pub(crate) fn get_prefix_ident(prefix: &str) -> Ident { let prefix = if prefix.as_bytes()[0].is_ascii_digit() { // Identifiers in Rust may not start with a number. format!("_{prefix}") } else { prefix.to_string() }; Ident::new(&prefix, Span::call_site()) } ast_serialize-0.13.1/crates/ruff_macros/src/rule_namespace.rs000064400000000000000000000145631046102023000212640ustar00use std::cmp::Reverse; use std::collections::HashSet; use quote::quote; use syn::spanned::Spanned; use syn::{Attribute, Data, DataEnum, DeriveInput, Error, ExprLit, Lit, Meta, MetaNameValue}; pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result { let DeriveInput { ident, data: Data::Enum(DataEnum { variants, .. }), .. } = input else { return Err(Error::new( input.ident.span(), "only named fields are supported", )); }; let mut parsed = Vec::new(); let mut common_prefix_match_arms = quote!(); let mut name_match_arms = quote!(Self::Ruff => "Ruff-specific rules", Self::Numpy => "NumPy-specific rules", ); let mut url_match_arms = quote!(Self::Ruff => None, Self::Numpy => None, ); let mut all_prefixes = HashSet::new(); for variant in variants { let mut first_chars = HashSet::new(); let prefixes: Result, _> = variant .attrs .iter() .filter(|attr| attr.path().is_ident("prefix")) .map(|attr| { let Meta::NameValue(MetaNameValue { value: syn::Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }), .. }) = &attr.meta else { return Err(Error::new( attr.span(), r#"expected attribute to be in the form of [#prefix = "..."]"#, )); }; let str = lit.value(); match str.chars().next() { None => { return Err(Error::new( lit.span(), "expected prefix string to be non-empty", )); } Some(c) => { if !first_chars.insert(c) { return Err(Error::new( lit.span(), format!( "this variant already has another prefix \ starting with the character '{c}'" ), )); } } } if !all_prefixes.insert(str.clone()) { return Err(Error::new( lit.span(), "prefix has already been defined before", )); } Ok(str) }) .collect(); let prefixes = prefixes?; if prefixes.is_empty() { return Err(Error::new( variant.span(), r#"Missing #[prefix = "..."] attribute"#, )); } let Some(doc_attr) = variant .attrs .iter() .find(|attr| attr.path().is_ident("doc")) else { return Err(Error::new(variant.span(), "expected a doc comment")); }; let variant_ident = variant.ident; if variant_ident != "Ruff" && variant_ident != "Numpy" { let (name, url) = parse_doc_attr(doc_attr)?; name_match_arms.extend(quote! {Self::#variant_ident => #name,}); url_match_arms.extend(quote! {Self::#variant_ident => Some(#url),}); } for lit in &prefixes { parsed.push(( lit.clone(), variant_ident.clone(), match prefixes.len() { 1 => ParseStrategy::SinglePrefix, _ => ParseStrategy::MultiplePrefixes, }, )); } if let [prefix] = &prefixes[..] { common_prefix_match_arms.extend(quote! { Self::#variant_ident => #prefix, }); } else { // There is more than one prefix. We already previously asserted // that prefixes of the same variant don't start with the same character // so the common prefix for this variant is the empty string. common_prefix_match_arms.extend(quote! { Self::#variant_ident => "", }); } } parsed.sort_by_key(|(prefix, ..)| Reverse(prefix.len())); let mut if_statements = quote!(); for (prefix, field, strategy) in parsed { let ret_str = match strategy { ParseStrategy::SinglePrefix => quote!(rest), ParseStrategy::MultiplePrefixes => quote!(code), }; if_statements.extend(quote! {if let Some(rest) = code.strip_prefix(#prefix) { return Some((#ident::#field, #ret_str)); }}); } Ok(quote! { #[automatically_derived] impl crate::registry::RuleNamespace for #ident { fn parse_code(code: &str) -> Option<(Self, &str)> { #if_statements None } fn common_prefix(&self) -> &'static str { match self { #common_prefix_match_arms } } fn name(&self) -> &'static str { match self { #name_match_arms } } fn url(&self) -> Option<&'static str> { match self { #url_match_arms } } } }) } /// Parses an attribute in the form of `#[doc = " [name](https://example.com/)"]` /// into a tuple of link label and URL. fn parse_doc_attr(doc_attr: &Attribute) -> syn::Result<(String, String)> { let Meta::NameValue(MetaNameValue { value: syn::Expr::Lit(ExprLit { lit: Lit::Str(doc_lit), .. }), .. }) = &doc_attr.meta else { return Err(Error::new( doc_attr.span(), r#"expected doc attribute to be in the form of #[doc = "..."]"#, )); }; parse_markdown_link(doc_lit.value().trim()) .map(|(name, url)| (name.to_string(), url.to_string())) .ok_or_else(|| { Error::new( doc_lit.span(), "expected doc comment to be in the form of \ `/// [name](https://example.com/)`", ) }) } fn parse_markdown_link(link: &str) -> Option<(&str, &str)> { link.strip_prefix('[')?.strip_suffix(')')?.split_once("](") } enum ParseStrategy { SinglePrefix, MultiplePrefixes, } ast_serialize-0.13.1/crates/ruff_macros/src/rust_doc.rs000064400000000000000000000034131046102023000201130ustar00use proc_macro2::TokenStream; use quote::quote; use syn::{Attribute, DeriveInput, Error, Lit, LitStr, Meta}; pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result { let docs = get_docs(&input.attrs)?; let name = input.ident; let (impl_generics, ty_generics, where_clause) = &input.generics.split_for_impl(); Ok(quote! { #[automatically_derived] impl #impl_generics ruff_db::RustDoc for #name #ty_generics #where_clause { fn rust_doc() -> &'static str { #docs } } }) } /// Collect all doc comment attributes into a string fn get_docs(attrs: &[Attribute]) -> syn::Result { let mut explanation = String::new(); for attr in attrs { if attr.path().is_ident("doc") { if let Some(lit) = parse_attr(["doc"], attr) { let value = lit.value(); // `/// ` adds let line = value.strip_prefix(' ').unwrap_or(&value); explanation.push_str(line); explanation.push('\n'); } else { return Err(Error::new_spanned(attr, "unimplemented doc comment style")); } } } Ok(explanation) } fn parse_attr<'a, const LEN: usize>( path: [&'static str; LEN], attr: &'a Attribute, ) -> Option<&'a LitStr> { if let Meta::NameValue(name_value) = &attr.meta { let path_idents = name_value .path .segments .iter() .map(|segment| &segment.ident); if path_idents.eq(path) { if let syn::Expr::Lit(syn::ExprLit { lit: Lit::Str(lit), .. }) = &name_value.value { return Some(lit); } } } None } ast_serialize-0.13.1/crates/ruff_macros/src/violation_metadata.rs000064400000000000000000000115251046102023000221400ustar00use std::sync::LazyLock; use proc_macro2::TokenStream; use quote::quote; use regex::Regex; use syn::{Attribute, DeriveInput, Error, Lit, LitStr, Meta, meta::ParseNestedMeta}; pub(crate) fn violation_metadata(input: DeriveInput) -> syn::Result { let docs = get_docs(&input.attrs)?; let Some(group) = get_rule_status(&input.attrs)? else { return Err(Error::new_spanned( input, "Missing required rule group metadata", )); }; let name = input.ident; let (impl_generics, ty_generics, where_clause) = &input.generics.split_for_impl(); Ok(quote! { #[automatically_derived] #[expect(deprecated)] impl #impl_generics crate::ViolationMetadata for #name #ty_generics #where_clause { fn rule() -> crate::registry::Rule { crate::registry::Rule::#name } fn explain() -> Option<&'static str> { Some(#docs) } fn group() -> crate::codes::RuleGroup { crate::codes::#group } fn file() -> &'static str { file!() } fn line() -> u32 { line!() } } }) } /// Collect all doc comment attributes into a string fn get_docs(attrs: &[Attribute]) -> syn::Result { let mut explanation = String::new(); for attr in attrs { if attr.path().is_ident("doc") { if let Some(lit) = parse_attr(["doc"], attr) { let value = lit.value(); // `/// ` adds let line = value.strip_prefix(' ').unwrap_or(&value); explanation.push_str(line); explanation.push('\n'); } else { return Err(Error::new_spanned(attr, "unimplemented doc comment style")); } } } Ok(explanation) } /// Extract the rule status attribute. /// /// These attributes look like: /// /// ```ignore /// #[violation_metadata(stable_since = "1.2.3")] /// struct MyRule; /// ``` /// /// The result is returned as a `TokenStream` so that the version string literal can be combined /// with the proper `RuleGroup` variant, e.g. `RuleGroup::Stable` for `stable_since` above. fn get_rule_status(attrs: &[Attribute]) -> syn::Result> { let mut group = None; for attr in attrs { if attr.path().is_ident("violation_metadata") { attr.parse_nested_meta(|meta| { if meta.path.is_ident("stable_since") { let lit: LitStr = parse_version(&meta)?; group = Some(quote!(RuleGroup::Stable { since: #lit })); return Ok(()); } else if meta.path.is_ident("preview_since") { let lit: LitStr = parse_version(&meta)?; group = Some(quote!(RuleGroup::Preview { since: #lit })); return Ok(()); } else if meta.path.is_ident("deprecated_since") { let lit: LitStr = parse_version(&meta)?; group = Some(quote!(RuleGroup::Deprecated { since: #lit })); return Ok(()); } else if meta.path.is_ident("removed_since") { let lit: LitStr = parse_version(&meta)?; group = Some(quote!(RuleGroup::Removed { since: #lit })); return Ok(()); } Err(Error::new_spanned( attr, "unimplemented violation metadata option", )) })?; } } Ok(group) } fn parse_attr<'a, const LEN: usize>( path: [&'static str; LEN], attr: &'a Attribute, ) -> Option<&'a LitStr> { if let Meta::NameValue(name_value) = &attr.meta { let path_idents = name_value .path .segments .iter() .map(|segment| &segment.ident); if itertools::equal(path_idents, path) { if let syn::Expr::Lit(syn::ExprLit { lit: Lit::Str(lit), .. }) = &name_value.value { return Some(lit); } } } None } fn parse_version(meta: &ParseNestedMeta) -> syn::Result { /// Match either a semantic version with an optional `v` prefix for versions before 0.5.0 /// (`v0.2.3`, `0.12.34`) or the special `NEXT_RUFF_VERSION` placeholder that is updated by /// rooster in releases. static VERSION: LazyLock = LazyLock::new(|| Regex::new(r"^(v0.[0-4].\d+|\d+\.\d+\.\d+|NEXT_RUFF_VERSION)$").unwrap()); let lit: LitStr = meta.value()?.parse()?; let value = lit.value(); if VERSION.is_match(&value) { Ok(lit) } else { Err(Error::new_spanned( lit, format_args!("Unknown version specifier `{value}`"), )) } } ast_serialize-0.13.1/crates/ruff_python_ast/Cargo.toml000064400000000000000000000032151046102023000177700ustar00[package] name = "ruff_python_ast" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [package.metadata.cargo-shear] # Used via `CacheKey` macro expansion. ignored = ["ruff_cache"] [lib] [dependencies] ruff_cache = { workspace = true, optional = true } ruff_macros = { workspace = true, optional = true } ruff_python_trivia = { workspace = true } ruff_source_file = { workspace = true } ruff_text_size = { workspace = true } aho-corasick = { workspace = true } arrayvec = { workspace = true } bitflags = { workspace = true } char_str = { workspace = true } compact_str = { workspace = true } get-size2 = { workspace = true, optional = true } is-macro = { workspace = true } memchr = { workspace = true } rustc-hash = { workspace = true } salsa = { workspace = true, optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } thiserror = { workspace = true } thin-vec = { workspace = true } [features] schemars = ["dep:schemars", "dep:serde_json"] cache = ["dep:ruff_cache", "dep:ruff_macros"] serde = [ "dep:serde", "ruff_text_size/serde", "dep:ruff_cache", "char_str/serde", "compact_str/serde", "thin-vec/serde", ] get-size = ["dep:get-size2", "char_str/get-size", "ruff_text_size/get-size"] salsa = ["dep:salsa"] [lints] workspace = true ast_serialize-0.13.1/crates/ruff_python_ast/README.md000064400000000000000000000010341046102023000173140ustar00 # ruff_python_ast This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_python_ast). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_python_ast/ast.toml000064400000000000000000000553421046102023000175340ustar00# This file is used by generate.py to autogenerate our Python AST data model. # # We have defined a Rust struct for each syntax node in `src/nodes.rs`. Many of # these nodes belong to groups. For instance, there is a `Stmt` group # consisting of all of the syntax nodes that represent valid Python statements. # # There is a special group named `ungrouped` that contains syntax nodes that do # not belong to any group. # # Each group is defined by two sections below. The `[GROUP]` section defines # options that control the auto-generation for that group. The `[GROUP.nodes]` # section defines which syntax nodes belong to that group. The name of each # entry in the nodes section must match the name of the corresponding Rust # struct. The value of each entry defines options that control the # auto-generation for that syntax node. # # The following group options are available: # # add_suffix_to_is_methods: [true/false] # Controls the name of the is_foo methods of the group's enums. If false (the # default), these methods will use the variant name in snake_case. If true, # then the group prefix will be moved to the end before snake_casing. (That # is, `StmtIf` will become `if_stmt`.) # # anynode_is_label: foo_bar # Controls the name of the AnyNodeRef::is_foo_bar method. The default is the # group name in snake_case. # # doc: # A doc comment that is added to the group's enums. # # The following syntax node options are available: # # doc: # A doc comment that is added to the syntax node struct. # # derives: # List of derives to add to the syntax node struct. Clone, Debug, PartialEq are added by default. # # custom_source_order: # A boolean that specifies if this node has a custom source order visitor implementation. # generation of visit_source_order will be skipped for this node. # # fields: # List of fields in the syntax node struct. Each field is a table with the # following keys: # * name - The name of the field. # * type - The type of the field. This can be a simple type name, or a type # type field uses a special syntax to describe the rust type: # * `Expr` - A single expression. # * `Expr?` - Option type. # * `Expr*` - A vector of Expr, shorthand for `Vec`. # * `Vec` - A vector of Expr. # * `Box<[Expr]>` - A boxed slice of Expr. # * `ThinVec` - A thin vector of Expr. # These properties cannot be nested, for example we cannot create a vector of option types. # * is_annotation - If this field is a type annotation. # # source_order: # Defines in what order the fields appear in source # # variant: # The name of the enum variant for this syntax node. Defaults to the node # name with the group prefix removed. (That is, `StmtIf` becomes `If`.) [Mod] anynode_is_label = "module" doc = "See also [mod](https://docs.python.org/3/library/ast.html#ast.mod)" [Mod.nodes.ModModule] doc = "See also [Module](https://docs.python.org/3/library/ast.html#ast.Module)" fields = [{ name = "body", type = "ThinVec" }] [Mod.nodes.ModExpression] doc = "See also [Module](https://docs.python.org/3/library/ast.html#ast.Module)" fields = [{ name = "body", type = "Box" }] [Stmt] add_suffix_to_is_methods = true anynode_is_label = "statement" doc = "See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt)" [Stmt.nodes.StmtFunctionDef] doc = """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.""" fields = [ { name = "is_async", type = "bool" }, { name = "decorator_list", type = "ThinVec" }, { name = "name", type = "Identifier" }, { name = "type_params", type = "Box?" }, { name = "parameters", type = "Box" }, { name = "returns", type = "Expr?", is_annotation = true }, { name = "body", type = "ThinVec" }, ] [Stmt.nodes.StmtClassDef] doc = "See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef)" fields = [ { name = "decorator_list", type = "ThinVec" }, { name = "name", type = "Identifier" }, { name = "type_params", type = "Box?" }, { name = "arguments", type = "Box?" }, { name = "body", type = "ThinVec" }, ] [Stmt.nodes.StmtReturn] doc = "See also [Return](https://docs.python.org/3/library/ast.html#ast.Return)" fields = [{ name = "value", type = "Expr?" }] [Stmt.nodes.StmtDelete] doc = "See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete)" fields = [{ name = "targets", type = "Expr*" }] [Stmt.nodes.StmtTypeAlias] doc = "See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias)" fields = [ { name = "name", type = "Expr" }, { name = "type_params", type = "Box?" }, { name = "value", type = "Expr" }, ] [Stmt.nodes.StmtAssign] doc = "See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign)" fields = [ { name = "targets", type = "Expr*" }, { name = "value", type = "Expr" }, ] [Stmt.nodes.StmtAugAssign] doc = "See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign)" fields = [ { name = "target", type = "Expr" }, { name = "op", type = "Operator" }, { name = "value", type = "Expr" }, ] [Stmt.nodes.StmtAnnAssign] doc = "See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign)" fields = [ { name = "target", type = "Expr" }, { name = "annotation", type = "Expr", is_annotation = true }, { name = "value", type = "Expr?" }, { name = "simple", type = "bool" }, ] [Stmt.nodes.StmtFor] doc = """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.""" fields = [ { name = "is_async", type = "bool" }, { name = "target", type = "Expr" }, { name = "iter", type = "Expr" }, { name = "body", type = "ThinVec" }, { name = "orelse", type = "ThinVec" }, ] [Stmt.nodes.StmtWhile] doc = """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).""" fields = [ { name = "test", type = "Expr" }, { name = "body", type = "ThinVec" }, { name = "orelse", type = "ThinVec" }, ] [Stmt.nodes.StmtIf] doc = "See also [If](https://docs.python.org/3/library/ast.html#ast.If)" fields = [ { name = "test", type = "Expr" }, { name = "body", type = "ThinVec" }, { name = "elif_else_clauses", type = "ElifElseClause*" }, ] [Stmt.nodes.StmtWith] doc = """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.""" fields = [ { name = "is_async", type = "bool" }, { name = "items", type = "WithItem*" }, { name = "body", type = "ThinVec" }, ] [Stmt.nodes.StmtMatch] doc = "See also [Match](https://docs.python.org/3/library/ast.html#ast.Match)" fields = [ { name = "subject", type = "Expr" }, { name = "cases", type = "MatchCase*" }, ] [Stmt.nodes.StmtRaise] doc = "See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise)" fields = [{ name = "exc", type = "Expr?" }, { name = "cause", type = "Expr?" }] [Stmt.nodes.StmtTry] doc = """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)""" fields = [ { name = "body", type = "ThinVec" }, { name = "handlers", type = "ExceptHandler*" }, { name = "orelse", type = "ThinVec" }, { name = "finalbody", type = "ThinVec" }, { name = "is_star", type = "bool" }, ] [Stmt.nodes.StmtAssert] doc = "See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert)" fields = [{ name = "test", type = "Expr" }, { name = "msg", type = "Expr?" }] [Stmt.nodes.StmtImport] doc = "See also [Import](https://docs.python.org/3/library/ast.html#ast.Import)" fields = [ { name = "names", type = "Alias*" }, { name = "is_lazy", type = "bool" }, ] [Stmt.nodes.StmtImportFrom] doc = "See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom)" fields = [ { name = "module", type = "Identifier?" }, { name = "names", type = "Alias*" }, { name = "level", type = "u32" }, { name = "is_lazy", type = "bool" }, ] [Stmt.nodes.StmtGlobal] doc = "See also [Global](https://docs.python.org/3/library/ast.html#ast.Global)" fields = [{ name = "names", type = "Identifier*" }] [Stmt.nodes.StmtNonlocal] doc = "See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal)" fields = [{ name = "names", type = "Identifier*" }] [Stmt.nodes.StmtExpr] doc = "See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr)" fields = [{ name = "value", type = "Expr" }] [Stmt.nodes.StmtPass] doc = "See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass)" fields = [] [Stmt.nodes.StmtBreak] doc = "See also [Break](https://docs.python.org/3/library/ast.html#ast.Break)" fields = [] [Stmt.nodes.StmtContinue] doc = "See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue)" fields = [] [Stmt.nodes.StmtIpyEscapeCommand] # TODO: remove crate:: prefix from IpyEscapeKind after it's auto generated doc = """An AST node used to represent a IPython escape command at the statement level. For example, ```python %matplotlib inline ``` ## Terminology Escape commands are special IPython syntax which starts with a token to identify the escape kind followed by the command value itself. [Escape kind] are the kind of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`, `?`, `??`, `/`, `;`, and `,`. Help command (or Dynamic Object Introspection as it's called) are the escape commands of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset of Help command where the token can be at the end of the line i.e., after the value. For example, `str.replace?`. Here's where things get tricky. I'll divide the help end command into two types for better understanding: 1. Strict version: The token is _only_ at the end of the line. For example, `str.replace?` or `str.replace??`. 2. Combined version: Along with the `?` or `??` token, which are at the end of the line, there are other escape kind tokens that are present at the start as well. For example, `%matplotlib?` or `%%timeit?`. Priority comes into picture for the "Combined version" mentioned above. How do we determine the escape kind if there are tokens on both side of the value, i.e., which token to choose? The Help end command always takes priority over any other token which means that if there is `?`/`??` at the end then that is used to determine the kind. For example, in `%matplotlib?` the escape kind is determined using the `?` token instead of `%` token. ## Syntax `` The simplest form is an escape kind token followed by the command value. For example, `%matplotlib inline`, `/foo`, `!pwd`, etc. `` The help end escape command would be the reverse of the above syntax. Here, the escape kind token can only be either `?` or `??` and it is at the end of the line. For example, `str.replace?`, `math.pi??`, etc. `` The final syntax is the combined version of the above two. For example, `%matplotlib?`, `%%timeit??`, etc. [Escape kind]: crate::IpyEscapeKind """ fields = [ { name = "kind", type = "IpyEscapeKind" }, { name = "value", type = "Box" }, ] [Expr] add_suffix_to_is_methods = true anynode_is_label = "expression" doc = "See also [expr](https://docs.python.org/3/library/ast.html#ast.expr)" [Expr.nodes.ExprBoolOp] doc = "See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp)" fields = [{ name = "op", type = "BoolOp" }, { name = "values", type = "Expr*" }] custom_source_order = true [Expr.nodes.ExprNamed] doc = "See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr)" fields = [{ name = "target", type = "Expr" }, { name = "value", type = "Expr" }] [Expr.nodes.ExprBinOp] doc = "See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp)" fields = [ { name = "left", type = "Expr" }, { name = "op", type = "Operator" }, { name = "right", type = "Expr" }, ] [Expr.nodes.ExprUnaryOp] doc = "See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp)" fields = [ { name = "op", type = "UnaryOp" }, { name = "operand", type = "Expr" }, ] [Expr.nodes.ExprLambda] doc = "See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda)" fields = [ { name = "parameters", type = "Box?" }, { name = "body", type = "Expr" }, ] [Expr.nodes.ExprIf] doc = "See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp)" fields = [ { name = "test", type = "Expr" }, { name = "body", type = "Expr" }, { name = "orelse", type = "Expr" }, ] source_order = ["body", "test", "orelse"] [Expr.nodes.ExprDict] doc = "See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict)" fields = [{ name = "items", type = "DictItem*" }] custom_source_order = true [Expr.nodes.ExprSet] doc = "See also [Set](https://docs.python.org/3/library/ast.html#ast.Set)" fields = [{ name = "elts", type = "Expr*" }] [Expr.nodes.ExprListComp] doc = "See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp)" fields = [ { name = "elt", type = "Expr" }, { name = "generators", type = "Comprehension*" }, ] [Expr.nodes.ExprSetComp] doc = "See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp)" fields = [ { name = "elt", type = "Expr" }, { name = "generators", type = "Comprehension*" }, ] [Expr.nodes.ExprDictComp] doc = "See also [DictComp](https://docs.python.org/3/library/ast.html#ast.DictComp)" fields = [ { name = "key", type = "Expr?" }, { name = "value", type = "Expr" }, { name = "generators", type = "Comprehension*" }, ] [Expr.nodes.ExprGenerator] doc = "See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.GeneratorExp)" fields = [ { name = "elt", type = "Expr" }, { name = "generators", type = "Comprehension*" }, { name = "parenthesized", type = "bool" }, ] [Expr.nodes.ExprAwait] doc = "See also [Await](https://docs.python.org/3/library/ast.html#ast.Await)" fields = [{ name = "value", type = "Expr" }] [Expr.nodes.ExprYield] doc = "See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield)" fields = [{ name = "value", type = "Expr?" }] [Expr.nodes.ExprYieldFrom] doc = "See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom)" fields = [{ name = "value", type = "Expr" }] [Expr.nodes.ExprCompare] doc = "See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare)" fields = [ { name = "left", type = "Expr" }, { name = "ops", type = "Box<[CmpOp]>" }, { name = "comparators", type = "Box<[Expr]>" }, ] # The fields must be visited simultaneously custom_source_order = true [Expr.nodes.ExprCall] doc = """A call expression whose end offset is derived from its arguments. The parser and error-recovery code must ensure that the call and its arguments end at the same offset. See also [Call](https://docs.python.org/3/library/ast.html#ast.Call)""" custom_debug = true custom_range = true fields = [ { name = "range_start", type = "ruff_text_size::TextSize", skip_visit = true }, { name = "func", type = "Expr" }, { name = "arguments", type = "Arguments" }, ] [Expr.nodes.ExprFString] doc = """An AST node that represents either a single-part f-string literal or an implicitly concatenated f-string literal. This type differs from the original Python AST `JoinedStr` in that it doesn't join the implicitly concatenated parts into a single string. Instead, it keeps them separate and provide various methods to access the parts. See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr)""" fields = [{ name = "value", type = "FStringValue" }] custom_source_order = true [Expr.nodes.ExprTString] doc = """An AST node that represents either a single-part t-string literal or an implicitly concatenated t-string literal. This type differs from the original Python AST `TemplateStr` in that it doesn't join the implicitly concatenated parts into a single string. Instead, it keeps them separate and provide various methods to access the parts. See also [TemplateStr](https://docs.python.org/3/library/ast.html#ast.TemplateStr)""" fields = [{ name = "value", type = "TStringValue" }] custom_source_order = true [Expr.nodes.ExprStringLiteral] doc = """An AST node that represents either a single-part string literal or an implicitly concatenated string literal.""" fields = [{ name = "value", type = "StringLiteralValue" }] # Because StringLiteralValue type is an iterator and it's not clear from the type custom_source_order = true [Expr.nodes.ExprBytesLiteral] doc = """An AST node that represents either a single-part bytestring literal or an implicitly concatenated bytestring literal.""" fields = [{ name = "value", type = "BytesLiteralValue" }] # Because BytesLiteralValue type is an iterator and it's not clear from the type custom_source_order = true [Expr.nodes.ExprNumberLiteral] fields = [{ name = "value", type = "Number" }] [Expr.nodes.ExprBooleanLiteral] fields = [{ name = "value", type = "bool" }] derives = ["Default"] [Expr.nodes.ExprNoneLiteral] fields = [] derives = ["Default"] [Expr.nodes.ExprEllipsisLiteral] fields = [] derives = ["Default"] [Expr.nodes.ExprAttribute] doc = "See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attribute)" fields = [ { name = "value", type = "Expr" }, { name = "attr", type = "Identifier" }, { name = "ctx", type = "ExprContext" }, ] [Expr.nodes.ExprSubscript] doc = "See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subscript)" fields = [ { name = "value", type = "Expr" }, { name = "slice", type = "Expr" }, { name = "ctx", type = "ExprContext" }, ] [Expr.nodes.ExprStarred] doc = "See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred)" fields = [ { name = "value", type = "Expr" }, { name = "ctx", type = "ExprContext" }, ] [Expr.nodes.ExprName] doc = "See also [Name](https://docs.python.org/3/library/ast.html#ast.Name)" fields = [ { name = "id", type = "Name" }, { name = "ctx", type = "ExprContext" }, ] [Expr.nodes.ExprList] doc = "See also [List](https://docs.python.org/3/library/ast.html#ast.List)" fields = [ { name = "elts", type = "Expr*" }, { name = "ctx", type = "ExprContext" }, ] [Expr.nodes.ExprTuple] doc = "See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple)" fields = [ { name = "elts", type = "Expr*" }, { name = "ctx", type = "ExprContext" }, { name = "parenthesized", type = "bool" }, ] [Expr.nodes.ExprSlice] doc = "See also [Slice](https://docs.python.org/3/library/ast.html#ast.Slice)" fields = [ { name = "lower", type = "Expr?" }, { name = "upper", type = "Expr?" }, { name = "step", type = "Expr?" }, ] [Expr.nodes.ExprIpyEscapeCommand] doc = """An AST node used to represent a IPython escape command at the expression level. For example, ```python dir = !pwd ``` Here, the escape kind can only be `!` or `%` otherwise it is a syntax error. For more information related to terminology and syntax of escape commands, see [`StmtIpyEscapeCommand`].""" fields = [ { name = "kind", type = "IpyEscapeKind" }, { name = "value", type = "Box" }, ] [ExceptHandler] doc = "See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler)" [ExceptHandler.nodes] ExceptHandlerExceptHandler = {} [InterpolatedStringElement.nodes] InterpolatedElement = { variant = "Interpolation" } InterpolatedStringLiteralElement = { variant = "Literal" } [Pattern] doc = "See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern)" [Pattern.nodes.PatternMatchValue] doc = "See also [MatchValue](https://docs.python.org/3/library/ast.html#ast.MatchValue)" fields = [{ name = "value", type = "Box" }] [Pattern.nodes.PatternMatchSingleton] doc = "See also [MatchSingleton](https://docs.python.org/3/library/ast.html#ast.MatchSingleton)" fields = [{ name = "value", type = "Singleton" }] [Pattern.nodes.PatternMatchSequence] doc = "See also [MatchSequence](https://docs.python.org/3/library/ast.html#ast.MatchSequence)" fields = [{ name = "patterns", type = "Pattern*" }] [Pattern.nodes.PatternMatchMapping] doc = "See also [MatchMapping](https://docs.python.org/3/library/ast.html#ast.MatchMapping)" fields = [ { name = "keys", type = "ThinVec" }, { name = "patterns", type = "ThinVec" }, { name = "rest", type = "Identifier?" }, ] custom_source_order = true [Pattern.nodes.PatternMatchClass] doc = "See also [MatchClass](https://docs.python.org/3/library/ast.html#ast.MatchClass)" fields = [ { name = "cls", type = "Box" }, { name = "arguments", type = "PatternArguments" }, ] [Pattern.nodes.PatternMatchStar] doc = "See also [MatchStar](https://docs.python.org/3/library/ast.html#ast.MatchStar)" fields = [{ name = "name", type = "Identifier?" }] [Pattern.nodes.PatternMatchAs] doc = "See also [MatchAs](https://docs.python.org/3/library/ast.html#ast.MatchAs)" fields = [ { name = "pattern", type = "Box?" }, { name = "name", type = "Identifier?" }, ] [Pattern.nodes.PatternMatchOr] doc = "See also [MatchOr](https://docs.python.org/3/library/ast.html#ast.MatchOr)" fields = [{ name = "patterns", type = "Pattern*" }] [TypeParam] doc = "See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param)" [TypeParam.nodes.TypeParamTypeVar] doc = "See also [TypeVar](https://docs.python.org/3/library/ast.html#ast.TypeVar)" fields = [ { name = "name", type = "Identifier" }, { name = "bound", type = "Box?" }, { name = "default", type = "Box?" }, ] [TypeParam.nodes.TypeParamTypeVarTuple] doc = "See also [TypeVarTuple](https://docs.python.org/3/library/ast.html#ast.TypeVarTuple)" fields = [ { name = "name", type = "Identifier" }, { name = "default", type = "Box?" }, ] [TypeParam.nodes.TypeParamParamSpec] doc = "See also [ParamSpec](https://docs.python.org/3/library/ast.html#ast.ParamSpec)" fields = [ { name = "name", type = "Identifier" }, { name = "default", type = "Box?" }, ] [ungrouped.nodes] InterpolatedStringFormatSpec = {} PatternArguments = {} PatternKeyword = {} Comprehension = {} Arguments = {} Parameters = {} Parameter = {} ParameterWithDefault = {} Keyword = {} Alias = {} WithItem = {} MatchCase = {} Decorator = {} ElifElseClause = {} TypeParams = {} FString = {} TString = {} StringLiteral = {} BytesLiteral = {} Identifier = {} ast_serialize-0.13.1/crates/ruff_python_ast/generate.py000064400000000000000000001114451046102023000202110ustar00#!/usr/bin/python # /// script # requires-python = ">=3.11" # dependencies = [] # /// from __future__ import annotations import re from dataclasses import dataclass from enum import Enum from pathlib import Path from subprocess import check_output from typing import Any import tomllib # Types that require `crate::`. We can slowly remove these types as we move them to generate scripts. types_requiring_crate_prefix = { "IpyEscapeKind", "ExprContext", "Identifier", "Number", "BytesLiteralValue", "StringLiteralValue", "FStringValue", "TStringValue", "Arguments", "CmpOp", "Comprehension", "DictItem", "UnaryOp", "BoolOp", "Operator", "Decorator", "TypeParams", "Parameters", "ElifElseClause", "WithItem", "MatchCase", "Alias", "Singleton", "PatternArguments", } @dataclass class VisitorInfo: name: str accepts_sequence: bool = False # Map of AST node types to their corresponding visitor information. # Only visitors that are different from the default `visit_*` method are included. # These visitors either have a different name or accept a sequence of items. type_to_visitor_function: dict[str, VisitorInfo] = { "TypeParams": VisitorInfo("visit_type_params", True), "Parameters": VisitorInfo("visit_parameters", True), "Stmt": VisitorInfo("visit_body", True), "Arguments": VisitorInfo("visit_arguments", True), } def rustfmt(code: str) -> str: return check_output(["rustfmt", "--emit=stdout"], input=code, text=True) def to_snake_case(node: str) -> str: """Converts CamelCase to snake_case""" return re.sub("([A-Z])", r"_\1", node).lower().lstrip("_") def write_rustdoc(out: list[str], doc: str) -> None: for line in doc.split("\n"): out.append(f"/// {line}") # ------------------------------------------------------------------------------ # Read AST description def load_ast(root: Path) -> Ast: ast_path = root.joinpath("crates", "ruff_python_ast", "ast.toml") with ast_path.open("rb") as ast_file: ast = tomllib.load(ast_file) return Ast(ast) # ------------------------------------------------------------------------------ # Preprocess @dataclass class Ast: """ The parsed representation of the `ast.toml` file. Defines all of the Python AST syntax nodes, and which groups (`Stmt`, `Expr`, etc.) they belong to. """ groups: list[Group] ungrouped_nodes: list[Node] all_nodes: list[Node] def __init__(self, ast: dict[str, Any]) -> None: self.groups = [] self.ungrouped_nodes = [] self.all_nodes = [] for group_name, group in ast.items(): group = Group(group_name, group) self.all_nodes.extend(group.nodes) if group_name == "ungrouped": self.ungrouped_nodes = group.nodes else: self.groups.append(group) @dataclass class Group: name: str nodes: list[Node] owned_enum_ty: str add_suffix_to_is_methods: bool anynode_is_label: str doc: str | None def __init__(self, group_name: str, group: dict[str, Any]) -> None: self.name = group_name self.owned_enum_ty = group_name self.ref_enum_ty = group_name + "Ref" self.add_suffix_to_is_methods = group.get("add_suffix_to_is_methods", False) self.anynode_is_label = group.get("anynode_is_label", to_snake_case(group_name)) self.doc = group.get("doc") self.nodes = [ Node(self, node_name, node) for node_name, node in group["nodes"].items() ] @dataclass class Node: name: str variant: str ty: str doc: str | None fields: list[Field] | None derives: list[str] custom_debug: bool custom_source_order: bool custom_range: bool source_order: list[str] | None def __init__(self, group: Group, node_name: str, node: dict[str, Any]) -> None: self.name = node_name self.variant = node.get("variant", node_name.removeprefix(group.name)) self.ty = f"crate::{node_name}" self.fields = None fields = node.get("fields") if fields is not None: self.fields = [Field(f) for f in fields] self.custom_debug = node.get("custom_debug", False) self.custom_source_order = node.get("custom_source_order", False) self.custom_range = node.get("custom_range", False) self.derives = node.get("derives", []) self.doc = node.get("doc") self.source_order = node.get("source_order") def fields_in_source_order(self) -> list[Field]: if self.fields is None: return [] if self.source_order is None: return list(filter(lambda x: not x.skip_source_order(), self.fields)) fields = [] for field_name in self.source_order: field = None for field in self.fields: if field.skip_source_order(): continue if field.name == field_name: field = field break fields.append(field) return fields @dataclass class Field: name: str ty: str _skip_visit: bool is_annotation: bool parsed_ty: FieldType def __init__(self, field: dict[str, Any]) -> None: self.name = field["name"] self.ty = field["type"] self.parsed_ty = FieldType(self.ty) self._skip_visit = field.get("skip_visit", False) self.is_annotation = field.get("is_annotation", False) def skip_source_order(self) -> bool: return self._skip_visit or self.parsed_ty.inner in [ "str", "ExprContext", "Name", "u32", "bool", "Number", "IpyEscapeKind", ] # Extracts the type argument from a Rust type used in AST field syntax. # Box -> str # Box -> Expr # If the type does not have a type argument, it will return the string. # Does not support nested types def extract_type_argument(rust_type_str: str) -> str: open_bracket_index = rust_type_str.find("<") if open_bracket_index == -1: return rust_type_str close_bracket_index = rust_type_str.rfind(">") if close_bracket_index == -1 or close_bracket_index <= open_bracket_index: raise ValueError(f"Brackets are not balanced for type {rust_type_str}") inner_type = rust_type_str[open_bracket_index + 1 : close_bracket_index].strip() inner_type = inner_type.replace("crate::", "") return inner_type class SequenceKind(Enum): VEC = "vec" BOXED_SLICE = "boxed_slice" THIN_VEC = "thin_vec" def split_sequence_type(rule: str) -> tuple[SequenceKind | None, str]: if "&" in rule: raise ValueError(f"`&T*` is unsupported; use `Box<[T]>`: {rule}") if "*" in rule: if rule.endswith("*") and rule.count("*") == 1: return SequenceKind.VEC, rule[:-1] raise ValueError(f"`*` must be at the end: {rule}") for prefix, suffix, sequence_kind in ( ("Vec<", ">", SequenceKind.VEC), ("ThinVec<", ">", SequenceKind.THIN_VEC), ("Box<[", "]>", SequenceKind.BOXED_SLICE), ): if rule.startswith(prefix): if not rule.endswith(suffix): raise ValueError(f"Unclosed collection type: {rule}") return sequence_kind, rule[len(prefix) : -len(suffix)] return None, rule @dataclass class FieldType: rule: str name: str inner: str sequence_kind: SequenceKind | None = None optional: bool = False def __init__(self, rule: str) -> None: self.rule = rule self.optional = False if "?" in rule: if not rule.endswith("?") or rule.count("?") != 1: raise ValueError(f"`?` must be at the end: {rule}") self.optional = True rule = rule[:-1] self.sequence_kind, self.name = split_sequence_type(rule) if self.optional and self.sequence_kind is not None: raise ValueError(f"optional field cannot be sequence or slice: {self.rule}") if self.sequence_kind is not None and ( not self.name or any(ch in self.name for ch in "?*&[]<>") ): raise ValueError(f"Invalid collection element type: {rule}") self.inner = extract_type_argument(self.name) # ------------------------------------------------------------------------------ # Preamble def write_preamble(out: list[str]) -> None: out.append(""" // This is a generated file. Don't modify it by hand! // Run `crates/ruff_python_ast/generate.py` to re-generate the file. use crate::name::Name; use crate::visitor::source_order::SourceOrderVisitor; """) # ------------------------------------------------------------------------------ # Owned enum def write_owned_enum(out: list[str], ast: Ast) -> None: """ Create an enum for each group that contains an owned copy of a syntax node. ```rust pub enum TypeParam { TypeVar(TypeParamTypeVar), TypeVarTuple(TypeParamTypeVarTuple), ... } ``` Also creates: - `impl Ranged for TypeParam` - `impl HasNodeIndex for TypeParam` - `TypeParam::visit_source_order` - `impl From for TypeParam` - `impl Ranged for TypeParamTypeVar` - `impl HasNodeIndex for TypeParamTypeVar` - `fn TypeParam::is_type_var() -> bool` If the `add_suffix_to_is_methods` group option is true, then the `is_type_var` method will be named `is_type_var_type_param`. """ for group in ast.groups: out.append("") if group.doc is not None: write_rustdoc(out, group.doc) out.append("#[derive(Clone, Debug, PartialEq)]") out.append('#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]') out.append(f"pub enum {group.owned_enum_ty} {{") for node in group.nodes: out.append(f"{node.variant}({node.ty}),") out.append("}") for node in group.nodes: out.append(f""" impl From<{node.ty}> for {group.owned_enum_ty} {{ fn from(node: {node.ty}) -> Self {{ Self::{node.variant}(node) }} }} """) out.append(f""" impl ruff_text_size::Ranged for {group.owned_enum_ty} {{ fn range(&self) -> ruff_text_size::TextRange {{ match self {{ """) for node in group.nodes: out.append(f"Self::{node.variant}(node) => node.range(),") out.append(""" } } } """) out.append(f""" impl crate::HasNodeIndex for {group.owned_enum_ty} {{ fn node_index(&self) -> &crate::AtomicNodeIndex {{ match self {{ """) for node in group.nodes: out.append(f"Self::{node.variant}(node) => node.node_index(),") out.append(""" } } } """) out.append( "#[allow(dead_code, clippy::match_wildcard_for_single_variants)]" ) # Not all is_methods are used out.append(f"impl {group.name} {{") for node in group.nodes: is_name = to_snake_case(node.variant) variant_name = node.variant match_arm = f"Self::{variant_name}" if group.add_suffix_to_is_methods: is_name = to_snake_case(node.variant + group.name) if len(group.nodes) > 1: out.append(f""" #[inline] pub const fn is_{is_name}(&self) -> bool {{ matches!(self, {match_arm}(_)) }} #[inline] pub fn {is_name}(self) -> Option<{node.ty}> {{ match self {{ {match_arm}(val) => Some(val), _ => None, }} }} #[inline] pub fn expect_{is_name}(self) -> {node.ty} {{ match self {{ {match_arm}(val) => val, _ => panic!("called expect on {{self:?}}"), }} }} #[inline] pub fn as_{is_name}_mut(&mut self) -> Option<&mut {node.ty}> {{ match self {{ {match_arm}(val) => Some(val), _ => None, }} }} #[inline] pub fn as_{is_name}(&self) -> Option<&{node.ty}> {{ match self {{ {match_arm}(val) => Some(val), _ => None, }} }} """) elif len(group.nodes) == 1: out.append(f""" #[inline] pub const fn is_{is_name}(&self) -> bool {{ matches!(self, {match_arm}(_)) }} #[inline] pub fn {is_name}(self) -> Option<{node.ty}> {{ match self {{ {match_arm}(val) => Some(val), }} }} #[inline] pub fn expect_{is_name}(self) -> {node.ty} {{ match self {{ {match_arm}(val) => val, }} }} #[inline] pub fn as_{is_name}_mut(&mut self) -> Option<&mut {node.ty}> {{ match self {{ {match_arm}(val) => Some(val), }} }} #[inline] pub fn as_{is_name}(&self) -> Option<&{node.ty}> {{ match self {{ {match_arm}(val) => Some(val), }} }} """) out.append("}") for node in ast.all_nodes: if node.custom_range: continue out.append(f""" impl ruff_text_size::Ranged for {node.ty} {{ fn range(&self) -> ruff_text_size::TextRange {{ self.range }} }} """) for node in ast.all_nodes: out.append(f""" impl crate::HasNodeIndex for {node.ty} {{ fn node_index(&self) -> &crate::AtomicNodeIndex {{ &self.node_index }} }} """) for group in ast.groups: out.append(f""" impl {group.owned_enum_ty} {{ #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, {{ match self {{ """) for node in group.nodes: out.append( f"{group.owned_enum_ty}::{node.variant}(node) => node.visit_source_order(visitor)," ) out.append(""" } } } """) # ------------------------------------------------------------------------------ # Ref enum def write_ref_enum(out: list[str], ast: Ast) -> None: """ Create an enum for each group that contains a reference to a syntax node. ```rust pub enum TypeParamRef<'a> { TypeVar(&'a TypeParamTypeVar), TypeVarTuple(&'a TypeParamTypeVarTuple), ... } ``` Also creates: - `impl<'a> From<&'a TypeParam> for TypeParamRef<'a>` - `impl<'a> From<&'a TypeParamTypeVar> for TypeParamRef<'a>` - `impl Ranged for TypeParamRef<'_>` - `impl HasNodeIndex for TypeParamRef<'_>` - `fn TypeParamRef::is_type_var() -> bool` The name of each variant can be customized via the `variant` node option. If the `add_suffix_to_is_methods` group option is true, then the `is_type_var` method will be named `is_type_var_type_param`. """ for group in ast.groups: out.append("") if group.doc is not None: write_rustdoc(out, group.doc) out.append("""#[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)]""") out.append('#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]') out.append(f"""pub enum {group.ref_enum_ty}<'a> {{""") for node in group.nodes: if group.add_suffix_to_is_methods: is_name = to_snake_case(node.variant + group.name) out.append(f'#[is(name = "{is_name}")]') out.append(f"""{node.variant}(&'a {node.ty}),""") out.append("}") out.append(f""" impl<'a> From<&'a {group.owned_enum_ty}> for {group.ref_enum_ty}<'a> {{ fn from(node: &'a {group.owned_enum_ty}) -> Self {{ match node {{ """) for node in group.nodes: out.append( f"{group.owned_enum_ty}::{node.variant}(node) => {group.ref_enum_ty}::{node.variant}(node)," ) out.append(""" } } } """) for node in group.nodes: out.append(f""" impl<'a> From<&'a {node.ty}> for {group.ref_enum_ty}<'a> {{ fn from(node: &'a {node.ty}) -> Self {{ Self::{node.variant}(node) }} }} """) out.append(f""" impl ruff_text_size::Ranged for {group.ref_enum_ty}<'_> {{ fn range(&self) -> ruff_text_size::TextRange {{ match self {{ """) for node in group.nodes: out.append(f"Self::{node.variant}(node) => node.range(),") out.append(""" } } } """) out.append(f""" impl crate::HasNodeIndex for {group.ref_enum_ty}<'_> {{ fn node_index(&self) -> &crate::AtomicNodeIndex {{ match self {{ """) for node in group.nodes: out.append(f"Self::{node.variant}(node) => node.node_index(),") out.append(""" } } } """) # ------------------------------------------------------------------------------ # AnyNodeRef def write_anynoderef(out: list[str], ast: Ast) -> None: """ Create the AnyNodeRef type. ```rust pub enum AnyNodeRef<'a> { ... TypeParamTypeVar(&'a TypeParamTypeVar), TypeParamTypeVarTuple(&'a TypeParamTypeVarTuple), ... } ``` Also creates: - `impl<'a> From<&'a TypeParam> for AnyNodeRef<'a>` - `impl<'a> From> for AnyNodeRef<'a>` - `impl<'a> From<&'a TypeParamTypeVarTuple> for AnyNodeRef<'a>` - `impl Ranged for AnyNodeRef<'_>` - `impl HasNodeIndex for AnyNodeRef<'_>` - `fn AnyNodeRef::as_ptr(&self) -> std::ptr::NonNull<()>` - `fn AnyNodeRef::visit_source_order(self, visitor &mut impl SourceOrderVisitor)` """ out.append(""" /// A flattened enumeration of all AST nodes. #[derive(Copy, Clone, Debug, is_macro::Is, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum AnyNodeRef<'a> { """) for node in ast.all_nodes: out.append(f"""{node.name}(&'a {node.ty}),""") out.append(""" } """) for group in ast.groups: out.append(f""" impl<'a> From<&'a {group.owned_enum_ty}> for AnyNodeRef<'a> {{ fn from(node: &'a {group.owned_enum_ty}) -> AnyNodeRef<'a> {{ match node {{ """) for node in group.nodes: out.append( f"{group.owned_enum_ty}::{node.variant}(node) => AnyNodeRef::{node.name}(node)," ) out.append(""" } } } """) out.append(f""" impl<'a> From<{group.ref_enum_ty}<'a>> for AnyNodeRef<'a> {{ fn from(node: {group.ref_enum_ty}<'a>) -> AnyNodeRef<'a> {{ match node {{ """) for node in group.nodes: out.append( f"{group.ref_enum_ty}::{node.variant}(node) => AnyNodeRef::{node.name}(node)," ) out.append(""" } } } """) # `as_*` methods to convert from `AnyNodeRef` to e.g. `ExprRef` out.append(f""" impl<'a> AnyNodeRef<'a> {{ pub fn as_{to_snake_case(group.ref_enum_ty)}(self) -> Option<{group.ref_enum_ty}<'a>> {{ match self {{ """) for node in group.nodes: out.append( f"Self::{node.name}(node) => Some({group.ref_enum_ty}::{node.variant}(node))," ) out.append(""" _ => None, } } } """) for node in ast.all_nodes: out.append(f""" impl<'a> From<&'a {node.ty}> for AnyNodeRef<'a> {{ fn from(node: &'a {node.ty}) -> AnyNodeRef<'a> {{ AnyNodeRef::{node.name}(node) }} }} """) out.append(""" impl ruff_text_size::Ranged for AnyNodeRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { """) for node in ast.all_nodes: out.append(f"""AnyNodeRef::{node.name}(node) => node.range(),""") out.append(""" } } } """) out.append(""" impl crate::HasNodeIndex for AnyNodeRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { """) for node in ast.all_nodes: out.append(f"""AnyNodeRef::{node.name}(node) => node.node_index(),""") out.append(""" } } } """) out.append(""" impl AnyNodeRef<'_> { pub fn as_ptr(&self) -> std::ptr::NonNull<()> { match self { """) for node in ast.all_nodes: out.append( f"AnyNodeRef::{node.name}(node) => std::ptr::NonNull::from(*node).cast()," ) out.append(""" } } } """) out.append(""" impl<'a> AnyNodeRef<'a> { pub fn visit_source_order<'b, V>(self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'b> + ?Sized, 'a: 'b, { match self { """) for node in ast.all_nodes: out.append( f"AnyNodeRef::{node.name}(node) => node.visit_source_order(visitor)," ) out.append(""" } } } """) for group in ast.groups: out.append(f""" impl AnyNodeRef<'_> {{ pub const fn is_{group.anynode_is_label}(self) -> bool {{ matches!(self, """) for i, node in enumerate(group.nodes): if i > 0: out.append("|") out.append(f"""AnyNodeRef::{node.name}(_)""") out.append(""" ) } } """) # ------------------------------------------------------------------------------ # AnyRootNodeRef def write_root_anynoderef(out: list[str], ast: Ast) -> None: """ Create the AnyRootNodeRef type. ```rust pub enum AnyRootNodeRef<'a> { ... TypeParam(&'a TypeParam), ... } ``` Also creates: - `impl<'a> From<&'a TypeParam> for AnyRootNodeRef<'a>` - `impl<'a> TryFrom> for &'a TypeParam` - `impl<'a> TryFrom> for &'a TypeParamVarTuple` - `impl Ranged for AnyRootNodeRef<'_>` - `impl HasNodeIndex for AnyRootNodeRef<'_>` - `fn AnyRootNodeRef::visit_source_order(self, visitor &mut impl SourceOrderVisitor)` """ root_nodes = [(group.name, group.owned_enum_ty) for group in ast.groups] root_nodes.extend((node.name, node.ty) for node in ast.ungrouped_nodes) out.append(""" /// An enumeration of all AST nodes. /// /// Unlike `AnyNodeRef`, this type does not flatten nested enums, so its variants only /// consist of the "root" AST node types. This is useful as it exposes references to the /// original enums, not just references to their inner values. /// /// For example, `AnyRootNodeRef::Mod` contains a reference to the `Mod` enum, while /// `AnyNodeRef` has top-level `AnyNodeRef::ModModule` and `AnyNodeRef::ModExpression` /// variants. #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum AnyRootNodeRef<'a> { """) for name, ty in root_nodes: out.append(f"""{name}(&'a {ty}),""") out.append(""" } """) out.append(""" /// The unflattened enum or struct type stored by an [`AnyRootNodeRef`]. /// /// Unlike [`NodeKind`], this does not distinguish variants of root enums such as [`Stmt`] /// and [`Expr`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] #[repr(u8)] pub enum RootNodeKind { """) for name, _ in root_nodes: out.append(f"""{name},""") out.append(""" } impl RootNodeKind { /// All root node kinds in discriminant order. pub const ALL: &'static [Self] = &[ """) for name, _ in root_nodes: out.append(f"""Self::{name},""") out.append(""" ]; /// Returns the root node kind with the given discriminant. #[inline] pub fn from_u8(value: u8) -> Option { match value { """) for index, (name, _) in enumerate(root_nodes): out.append(f"""{index} => Some(Self::{name}),""") out.append(""" _ => None, } } } """) for group in ast.groups: out.append(f""" impl<'a> From<&'a {group.owned_enum_ty}> for AnyRootNodeRef<'a> {{ #[inline] fn from(node: &'a {group.owned_enum_ty}) -> AnyRootNodeRef<'a> {{ AnyRootNodeRef::{group.name}(node) }} }} """) out.append(f""" impl<'a> TryFrom> for &'a {group.owned_enum_ty} {{ type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a {group.owned_enum_ty}, ()> {{ match node {{ AnyRootNodeRef::{group.name}(node) => Ok(node), _ => Err(()) }} }} }} """) for node in group.nodes: out.append(f""" impl<'a> TryFrom> for &'a {node.ty} {{ type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a {node.ty}, ()> {{ match node {{ AnyRootNodeRef::{group.name}({group.owned_enum_ty}::{node.variant}(node)) => Ok(node), _ => Err(()) }} }} }} """) for node in ast.ungrouped_nodes: out.append(f""" impl<'a> From<&'a {node.ty}> for AnyRootNodeRef<'a> {{ #[inline] fn from(node: &'a {node.ty}) -> AnyRootNodeRef<'a> {{ AnyRootNodeRef::{node.name}(node) }} }} """) out.append(f""" impl<'a> TryFrom> for &'a {node.ty} {{ type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a {node.ty}, ()> {{ match node {{ AnyRootNodeRef::{node.name}(node) => Ok(node), _ => Err(()) }} }} }} """) out.append(""" impl ruff_text_size::Ranged for AnyRootNodeRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { """) for name, _ in root_nodes: out.append(f"""AnyRootNodeRef::{name}(node) => node.range(),""") out.append(""" } } } """) out.append(""" impl crate::HasNodeIndex for AnyRootNodeRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { """) for name, _ in root_nodes: out.append(f"""AnyRootNodeRef::{name}(node) => node.node_index(),""") out.append(""" } } } """) out.append(""" impl<'a> AnyRootNodeRef<'a> { /// Decomposes this reference into its root node kind and a type-erased pointer. #[inline] pub fn into_raw_parts(self) -> (RootNodeKind, std::ptr::NonNull<()>) { match self { """) for name, _ in root_nodes: out.append( f"""AnyRootNodeRef::{name}(node) => (RootNodeKind::{name}, std::ptr::NonNull::from(node).cast()),""" ) out.append(""" } } /// Reconstructs an AST reference from its root node kind and type-erased pointer. /// /// # Safety /// /// - `pointer` must be properly aligned for and point to the exact root node type /// represented by `kind`. /// - The pointer's provenance must permit reads of a complete, initialized, and valid /// value of that type. /// - The pointed-to value must not be moved, dropped, or accessed mutably for `'a`. #[inline] #[expect(unsafe_code, reason = "reconstructs a type-erased AST reference")] pub unsafe fn from_raw_parts(kind: RootNodeKind, pointer: std::ptr::NonNull<()>) -> Self { let pointer = pointer.as_ptr(); // SAFETY: The caller guarantees that `pointer` is readable as the exact root node // type selected by `kind` and remains valid and immutable for `'a`. unsafe { match kind { """) for name, ty in root_nodes: out.append( f"""RootNodeKind::{name} => AnyRootNodeRef::{name}(&*pointer.cast::<{ty}>()),""" ) out.append(""" }} } pub fn visit_source_order<'b, V>(self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'b> + ?Sized, 'a: 'b, { match self { """) for name, _ in root_nodes: out.append( f"""AnyRootNodeRef::{name}(node) => node.visit_source_order(visitor),""" ) out.append(""" } } } """) # ------------------------------------------------------------------------------ # NodeKind def write_nodekind(out: list[str], ast: Ast) -> None: """ Create the NodeKind type. ```rust pub enum NodeKind { ... TypeParamTypeVar, TypeParamTypeVarTuple, ... } Also creates: - `fn AnyNodeRef::kind(self) -> NodeKind` ``` """ out.append(""" #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum NodeKind { """) for node in ast.all_nodes: out.append(f"""{node.name},""") out.append(""" } """) out.append(""" impl AnyNodeRef<'_> { pub const fn kind(self) -> NodeKind { match self { """) for node in ast.all_nodes: out.append(f"""AnyNodeRef::{node.name}(_) => NodeKind::{node.name},""") out.append(""" } } } """) # ------------------------------------------------------------------------------ # Node structs def write_node(out: list[str], ast: Ast) -> None: group_names = [group.name for group in ast.groups] for group in ast.groups: for node in group.nodes: if node.fields is None: continue if node.doc is not None: write_rustdoc(out, node.doc) out.append( "#[derive(Clone" + ("" if node.custom_debug else ", Debug") + ", PartialEq" + "".join(f", {derive}" for derive in node.derives) + ")]" ) out.append('#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]') name = node.name out.append(f"pub struct {name} {{") out.append("pub node_index: crate::AtomicNodeIndex,") if not node.custom_range: out.append("pub range: ruff_text_size::TextRange,") for field in node.fields: field_str = f"pub {field.name}: " ty = field.parsed_ty rust_ty = f"{field.parsed_ty.name}" if ty.name in types_requiring_crate_prefix: rust_ty = f"crate::{rust_ty}" if ty.sequence_kind is SequenceKind.VEC: rust_ty = f"Vec<{rust_ty}>" elif ty.sequence_kind is SequenceKind.BOXED_SLICE: rust_ty = f"Box<[{rust_ty}]>" elif ty.sequence_kind is SequenceKind.THIN_VEC: rust_ty = f"thin_vec::ThinVec<{rust_ty}>" else: if ty.name in group_names: rust_ty = f"Box<{rust_ty}>" if ty.optional: rust_ty = f"Option<{rust_ty}>" field_str += rust_ty + "," out.append(field_str) out.append("}") out.append("") # ------------------------------------------------------------------------------ # Source order visitor def write_source_order(out: list[str], ast: Ast) -> None: for group in ast.groups: for node in group.nodes: if node.fields is None or node.custom_source_order: continue name = node.name fields_list = "" body = "" for field in node.fields: if field.skip_source_order(): fields_list += f"{field.name}: _,\n" else: fields_list += f"{field.name},\n" if not node.custom_range: fields_list += "range: _,\n" fields_list += "node_index: _,\n" for field in node.fields_in_source_order(): visitor_name = ( type_to_visitor_function.get( field.parsed_ty.inner, VisitorInfo("") ).name or f"visit_{to_snake_case(field.parsed_ty.inner)}" ) visits_sequence = type_to_visitor_function.get( field.parsed_ty.inner, VisitorInfo("") ).accepts_sequence if field.is_annotation: visitor_name = "visit_annotation" if field.parsed_ty.optional: body += f""" if let Some({field.name}) = {field.name} {{ visitor.{visitor_name}({field.name}); }}\n """ elif not visits_sequence and field.parsed_ty.sequence_kind is not None: body += f""" for elm in {field.name} {{ visitor.{visitor_name}(elm); }} """ else: body += f"visitor.{visitor_name}({field.name});\n" visitor_arg_name = "visitor" if len(node.fields_in_source_order()) == 0: visitor_arg_name = "_" out.append(f""" impl {name} {{ pub(crate) fn visit_source_order<'a, V>(&'a self, {visitor_arg_name}: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, {{ let {name} {{ {fields_list} }} = self; {body} }} }} """) # ------------------------------------------------------------------------------ # Format and write output def generate(ast: Ast) -> list[str]: out = [] write_preamble(out) write_owned_enum(out, ast) write_ref_enum(out, ast) write_anynoderef(out, ast) write_root_anynoderef(out, ast) write_nodekind(out, ast) write_node(out, ast) write_source_order(out, ast) return out def write_output(root: Path, out: list[str]) -> None: out_path = root.joinpath("crates", "ruff_python_ast", "src", "generated.rs") out_path.write_text(rustfmt("\n".join(out))) # ------------------------------------------------------------------------------ # Main def main() -> None: root = Path( check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip() ) ast = load_ast(root) out = generate(ast) write_output(root, out) if __name__ == "__main__": main() ast_serialize-0.13.1/crates/ruff_python_ast/src/comparable.rs000064400000000000000000002016151046102023000213060ustar00//! An equivalent object hierarchy to the `RustPython` AST hierarchy, but with the //! ability to compare expressions for equality (via [`Eq`] and [`Hash`]). //! //! Two [`ComparableExpr`]s are considered equal if the underlying AST nodes have the //! same shape, ignoring trivia (e.g., parentheses, comments, and whitespace), the //! location in the source code, and other contextual information (e.g., whether they //! represent reads or writes, which is typically encoded in the Python AST). //! //! For example, in `[(a, b) for a, b in c]`, the `(a, b)` and `a, b` expressions are //! considered equal, despite the former being parenthesized, and despite the former //! being a write ([`ast::ExprContext::Store`]) and the latter being a read //! ([`ast::ExprContext::Load`]). //! //! Similarly, `"a" "b"` and `"ab"` would be considered equal, despite the former being //! an implicit concatenation of string literals, as these expressions are considered to //! have the same shape in that they evaluate to the same value. use crate as ast; use crate::{Expr, Number}; use std::borrow::Cow; use std::hash::Hash; #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum ComparableBoolOp { And, Or, } impl From for ComparableBoolOp { fn from(op: ast::BoolOp) -> Self { match op { ast::BoolOp::And => Self::And, ast::BoolOp::Or => Self::Or, } } } #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum ComparableOperator { Add, Sub, Mult, MatMult, Div, Mod, Pow, LShift, RShift, BitOr, BitXor, BitAnd, FloorDiv, } impl From for ComparableOperator { fn from(op: ast::Operator) -> Self { match op { ast::Operator::Add => Self::Add, ast::Operator::Sub => Self::Sub, ast::Operator::Mult => Self::Mult, ast::Operator::MatMult => Self::MatMult, ast::Operator::Div => Self::Div, ast::Operator::Mod => Self::Mod, ast::Operator::Pow => Self::Pow, ast::Operator::LShift => Self::LShift, ast::Operator::RShift => Self::RShift, ast::Operator::BitOr => Self::BitOr, ast::Operator::BitXor => Self::BitXor, ast::Operator::BitAnd => Self::BitAnd, ast::Operator::FloorDiv => Self::FloorDiv, } } } #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum ComparableUnaryOp { Invert, Not, UAdd, USub, } impl From for ComparableUnaryOp { fn from(op: ast::UnaryOp) -> Self { match op { ast::UnaryOp::Invert => Self::Invert, ast::UnaryOp::Not => Self::Not, ast::UnaryOp::UAdd => Self::UAdd, ast::UnaryOp::USub => Self::USub, } } } #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum ComparableCmpOp { Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot, In, NotIn, } impl From for ComparableCmpOp { fn from(op: ast::CmpOp) -> Self { match op { ast::CmpOp::Eq => Self::Eq, ast::CmpOp::NotEq => Self::NotEq, ast::CmpOp::Lt => Self::Lt, ast::CmpOp::LtE => Self::LtE, ast::CmpOp::Gt => Self::Gt, ast::CmpOp::GtE => Self::GtE, ast::CmpOp::Is => Self::Is, ast::CmpOp::IsNot => Self::IsNot, ast::CmpOp::In => Self::In, ast::CmpOp::NotIn => Self::NotIn, } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableAlias<'a> { name: &'a str, asname: Option<&'a str>, } impl<'a> From<&'a ast::Alias> for ComparableAlias<'a> { fn from(alias: &'a ast::Alias) -> Self { Self { name: alias.name.as_str(), asname: alias.asname.as_deref(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableWithItem<'a> { context_expr: ComparableExpr<'a>, optional_vars: Option>, } impl<'a> From<&'a ast::WithItem> for ComparableWithItem<'a> { fn from(with_item: &'a ast::WithItem) -> Self { Self { context_expr: (&with_item.context_expr).into(), optional_vars: with_item.optional_vars.as_ref().map(Into::into), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparablePatternArguments<'a> { patterns: Vec>, keywords: Vec>, } impl<'a> From<&'a ast::PatternArguments> for ComparablePatternArguments<'a> { fn from(parameters: &'a ast::PatternArguments) -> Self { Self { patterns: parameters.patterns.iter().map(Into::into).collect(), keywords: parameters.keywords.iter().map(Into::into).collect(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparablePatternKeyword<'a> { attr: &'a str, pattern: ComparablePattern<'a>, } impl<'a> From<&'a ast::PatternKeyword> for ComparablePatternKeyword<'a> { fn from(keyword: &'a ast::PatternKeyword) -> Self { Self { attr: keyword.attr.as_str(), pattern: (&keyword.pattern).into(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchValue<'a> { value: ComparableExpr<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchSingleton { value: ComparableSingleton, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchSequence<'a> { patterns: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchMapping<'a> { keys: Vec>, patterns: Vec>, rest: Option<&'a str>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchClass<'a> { cls: ComparableExpr<'a>, arguments: ComparablePatternArguments<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchStar<'a> { name: Option<&'a str>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchAs<'a> { pattern: Option>>, name: Option<&'a str>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct PatternMatchOr<'a> { patterns: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparablePattern<'a> { MatchValue(PatternMatchValue<'a>), MatchSingleton(PatternMatchSingleton), MatchSequence(PatternMatchSequence<'a>), MatchMapping(PatternMatchMapping<'a>), MatchClass(PatternMatchClass<'a>), MatchStar(PatternMatchStar<'a>), MatchAs(PatternMatchAs<'a>), MatchOr(PatternMatchOr<'a>), } impl<'a> From<&'a ast::Pattern> for ComparablePattern<'a> { fn from(pattern: &'a ast::Pattern) -> Self { match pattern { ast::Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => { Self::MatchValue(PatternMatchValue { value: value.into(), }) } ast::Pattern::MatchSingleton(ast::PatternMatchSingleton { value, .. }) => { Self::MatchSingleton(PatternMatchSingleton { value: value.into(), }) } ast::Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { Self::MatchSequence(PatternMatchSequence { patterns: patterns.iter().map(Into::into).collect(), }) } ast::Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, rest, .. }) => Self::MatchMapping(PatternMatchMapping { keys: keys.iter().map(Into::into).collect(), patterns: patterns.iter().map(Into::into).collect(), rest: rest.as_deref(), }), ast::Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => { Self::MatchClass(PatternMatchClass { cls: cls.into(), arguments: arguments.into(), }) } ast::Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => { Self::MatchStar(PatternMatchStar { name: name.as_deref(), }) } ast::Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => { Self::MatchAs(PatternMatchAs { pattern: pattern.as_ref().map(Into::into), name: name.as_deref(), }) } ast::Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => { Self::MatchOr(PatternMatchOr { patterns: patterns.iter().map(Into::into).collect(), }) } } } } impl<'a> From<&'a Box> for Box> { fn from(pattern: &'a Box) -> Self { Box::new((pattern.as_ref()).into()) } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableMatchCase<'a> { pattern: ComparablePattern<'a>, guard: Option>, body: Vec>, } impl<'a> From<&'a ast::MatchCase> for ComparableMatchCase<'a> { fn from(match_case: &'a ast::MatchCase) -> Self { Self { pattern: (&match_case.pattern).into(), guard: match_case.guard.as_ref().map(Into::into), body: match_case.body.iter().map(Into::into).collect(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableDecorator<'a> { expression: ComparableExpr<'a>, } impl<'a> From<&'a ast::Decorator> for ComparableDecorator<'a> { fn from(decorator: &'a ast::Decorator) -> Self { Self { expression: (&decorator.expression).into(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableSingleton { None, True, False, } impl From<&ast::Singleton> for ComparableSingleton { fn from(singleton: &ast::Singleton) -> Self { match singleton { ast::Singleton::None => Self::None, ast::Singleton::True => Self::True, ast::Singleton::False => Self::False, } } } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableNumber<'a> { Int(&'a ast::Int), Float(u64), Complex { real: u64, imag: u64 }, } impl<'a> From<&'a ast::Number> for ComparableNumber<'a> { fn from(number: &'a ast::Number) -> Self { match number { ast::Number::Int(value) => Self::Int(value), ast::Number::Float(value) => Self::Float(value.to_bits()), ast::Number::Complex { real, imag } => Self::Complex { real: real.to_bits(), imag: imag.to_bits(), }, } } } #[derive(Debug, Default, PartialEq, Eq, Hash)] pub struct ComparableArguments<'a> { args: Vec>, keywords: Vec>, } impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> { fn from(arguments: &'a ast::Arguments) -> Self { Self { args: arguments.args.iter().map(Into::into).collect(), keywords: arguments.keywords.iter().map(Into::into).collect(), } } } impl<'a> From<&'a Box> for ComparableArguments<'a> { fn from(arguments: &'a Box) -> Self { (arguments.as_ref()).into() } } #[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 ComparableParameter<'a> { arg: &'a str, annotation: Option>>, } impl<'a> From<&'a ast::Parameter> for ComparableParameter<'a> { fn from(arg: &'a ast::Parameter) -> Self { Self { arg: arg.name.as_str(), annotation: arg.annotation.as_ref().map(Into::into), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableParameterWithDefault<'a> { def: ComparableParameter<'a>, default: Option>, } impl<'a> From<&'a ast::ParameterWithDefault> for ComparableParameterWithDefault<'a> { fn from(arg: &'a ast::ParameterWithDefault) -> Self { Self { def: (&arg.parameter).into(), default: arg.default.as_ref().map(Into::into), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableKeyword<'a> { arg: Option<&'a str>, value: ComparableExpr<'a>, } impl<'a> From<&'a ast::Keyword> for ComparableKeyword<'a> { fn from(keyword: &'a ast::Keyword) -> Self { Self { arg: keyword.arg.as_ref().map(ast::Identifier::as_str), value: (&keyword.value).into(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableComprehension<'a> { target: ComparableExpr<'a>, iter: ComparableExpr<'a>, ifs: Vec>, is_async: bool, } impl<'a> From<&'a ast::Comprehension> for ComparableComprehension<'a> { fn from(comprehension: &'a ast::Comprehension) -> Self { Self { target: (&comprehension.target).into(), iter: (&comprehension.iter).into(), ifs: comprehension.ifs.iter().map(Into::into).collect(), is_async: comprehension.is_async, } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExceptHandlerExceptHandler<'a> { type_: Option>>, name: Option<&'a str>, body: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableExceptHandler<'a> { ExceptHandler(ExceptHandlerExceptHandler<'a>), } impl<'a> From<&'a ast::ExceptHandler> for ComparableExceptHandler<'a> { fn from(except_handler: &'a ast::ExceptHandler) -> Self { let ast::ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, name, body, .. }) = except_handler; Self::ExceptHandler(ExceptHandlerExceptHandler { type_: type_.as_ref().map(Into::into), name: name.as_deref(), body: body.iter().map(Into::into).collect(), }) } } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableInterpolatedStringElement<'a> { Literal(Cow<'a, str>), InterpolatedElement(InterpolatedElement<'a>), } /// Comparable wrapper for [`ast::DebugText`]. /// /// Compares the full debug text (leading + expression source + trailing) rather than only the /// expression source, because whitespace is part of the f-string's runtime output: `f"{x =}"` /// produces `"x ="` while `f"{x=}"` produces `"x="`, making them distinct /// `Literal` types. #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableDebugText<'a> { text: Cow<'a, str>, } impl<'a> From<&'a ast::DebugText> for ComparableDebugText<'a> { fn from(debug_text: &'a ast::DebugText) -> Self { // Normalizing newlines is safe because Python normalizes `\r\n` and `\r` to `\n` // at compile time, so they produce identical runtime values. Self { text: normalize_newlines(debug_text.as_str()), } } } fn normalize_newlines(contents: &str) -> Cow<'_, str> { if contents.contains('\r') { Cow::Owned(contents.replace("\r\n", "\n").replace('\r', "\n")) } else { Cow::Borrowed(contents) } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct InterpolatedElement<'a> { expression: ComparableExpr<'a>, debug_text: Option>, conversion: ast::ConversionFlag, format_spec: Option>>, } impl<'a> From<&'a ast::InterpolatedStringElement> for ComparableInterpolatedStringElement<'a> { fn from(interpolated_string_element: &'a ast::InterpolatedStringElement) -> Self { match interpolated_string_element { ast::InterpolatedStringElement::Literal(ast::InterpolatedStringLiteralElement { value, .. }) => Self::Literal(value.as_ref().into()), ast::InterpolatedStringElement::Interpolation(formatted_value) => { formatted_value.into() } } } } impl<'a> From<&'a ast::InterpolatedElement> for InterpolatedElement<'a> { fn from(interpolated_element: &'a ast::InterpolatedElement) -> Self { let ast::InterpolatedElement { expression, debug_text, conversion, format_spec, range: _, node_index: _, } = interpolated_element; Self { expression: (expression).into(), debug_text: debug_text.as_ref().map(Into::into), conversion: *conversion, format_spec: format_spec .as_ref() .map(|spec| spec.elements.iter().map(Into::into).collect()), } } } impl<'a> From<&'a ast::InterpolatedElement> for ComparableInterpolatedStringElement<'a> { fn from(interpolated_element: &'a ast::InterpolatedElement) -> Self { Self::InterpolatedElement(interpolated_element.into()) } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableElifElseClause<'a> { test: Option>, body: Vec>, } impl<'a> From<&'a ast::ElifElseClause> for ComparableElifElseClause<'a> { fn from(elif_else_clause: &'a ast::ElifElseClause) -> Self { let ast::ElifElseClause { range: _, node_index: _, test, body, } = elif_else_clause; Self { test: test.as_ref().map(Into::into), body: body.iter().map(Into::into).collect(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableLiteral<'a> { None, Ellipsis, Bool(&'a bool), Str(Vec>), Bytes(Vec>), Number(ComparableNumber<'a>), } impl<'a> From> for ComparableLiteral<'a> { fn from(literal: ast::LiteralExpressionRef<'a>) -> Self { match literal { ast::LiteralExpressionRef::NoneLiteral(_) => Self::None, ast::LiteralExpressionRef::EllipsisLiteral(_) => Self::Ellipsis, ast::LiteralExpressionRef::BooleanLiteral(ast::ExprBooleanLiteral { value, .. }) => Self::Bool(value), ast::LiteralExpressionRef::StringLiteral(ast::ExprStringLiteral { value, .. }) => { Self::Str(value.iter().map(Into::into).collect()) } ast::LiteralExpressionRef::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => { Self::Bytes(value.iter().map(Into::into).collect()) } ast::LiteralExpressionRef::NumberLiteral(ast::ExprNumberLiteral { value, .. }) => { Self::Number(value.into()) } } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableFString<'a> { elements: Box<[ComparableInterpolatedStringElement<'a>]>, } impl<'a> From<&'a ast::FStringValue> for ComparableFString<'a> { // The approach below is somewhat complicated, so it may // require some justification. // // Suppose given an f-string of the form // `f"{foo!r} one" " and two " f" and three {bar!s}"` // This decomposes as: // - An `FStringPart::FString`, `f"{foo!r} one"` with elements // - `FStringElement::Expression` encoding `{foo!r}` // - `FStringElement::Literal` encoding " one" // - An `FStringPart::Literal` capturing `" and two "` // - An `FStringPart::FString`, `f" and three {bar!s}"` with elements // - `FStringElement::Literal` encoding " and three " // - `FStringElement::Expression` encoding `{bar!s}` // // We would like to extract from this a vector of (comparable) f-string // _elements_ which alternate between expression elements and literal // elements. In order to do so, we need to concatenate adjacent string // literals. String literals may be separated for two reasons: either // they appear in adjacent string literal parts, or else a string literal // part is adjacent to a string literal _element_ inside of an f-string part. fn from(value: &'a ast::FStringValue) -> Self { #[derive(Default)] struct Collector<'a> { elements: Vec>, } impl<'a> Collector<'a> { // The logic for concatenating adjacent string literals // occurs here, implicitly: when we encounter a sequence // of string literals, the first gets pushed to the // `elements` vector, while subsequent strings // are concatenated onto this top string. fn push_literal(&mut self, literal: &'a str) { if let Some(ComparableInterpolatedStringElement::Literal(existing_literal)) = self.elements.last_mut() { existing_literal.to_mut().push_str(literal); } else { self.elements .push(ComparableInterpolatedStringElement::Literal(literal.into())); } } fn push_expression(&mut self, expression: &'a ast::InterpolatedElement) { self.elements.push(expression.into()); } } let mut collector = Collector::default(); for part in value { match part { ast::FStringPart::Literal(string_literal) => { collector.push_literal(&string_literal.value); } ast::FStringPart::FString(fstring) => { for element in &fstring.elements { match element { ast::InterpolatedStringElement::Literal(literal) => { collector.push_literal(&literal.value); } ast::InterpolatedStringElement::Interpolation(expression) => { collector.push_expression(expression); } } } } } } Self { elements: collector.elements.into_boxed_slice(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableTString<'a> { strings: Box<[ComparableInterpolatedStringElement<'a>]>, interpolations: Box<[InterpolatedElement<'a>]>, } impl<'a> From<&'a ast::TStringValue> for ComparableTString<'a> { // We model a [`ComparableTString`] on the actual // [CPython implementation] of a `string.templatelib.Template` object. // // As in CPython, we must be careful to ensure that the length // of `strings` is always one more than the length of `interpolations` - // that way we can recover the original reading order by interleaving // starting with `strings`. This is how we can tell the // difference between, e.g. `t"{foo}bar"` and `t"bar{foo}"`. // // - [CPython implementation](https://github.com/python/cpython/blob/c91ad5da9d92eac4718e4da8d53689c3cc24535e/Python/codegen.c#L4052-L4103) fn from(value: &'a ast::TStringValue) -> Self { struct Collector<'a> { strings: Vec>, interpolations: Vec>, } impl Default for Collector<'_> { fn default() -> Self { Self { strings: vec![ComparableInterpolatedStringElement::Literal("".into())], interpolations: vec![], } } } impl<'a> Collector<'a> { // The logic for concatenating adjacent string literals // occurs here, implicitly: when we encounter a sequence // of string literals, the first gets pushed to the // `strings` vector, while subsequent strings // are concatenated onto this top string. fn push_literal(&mut self, literal: &'a str) { if let Some(ComparableInterpolatedStringElement::Literal(existing_literal)) = self.strings.last_mut() { existing_literal.to_mut().push_str(literal); } else { self.strings .push(ComparableInterpolatedStringElement::Literal(literal.into())); } } fn start_new_literal(&mut self) { self.strings .push(ComparableInterpolatedStringElement::Literal("".into())); } fn push_tstring_interpolation(&mut self, expression: &'a ast::InterpolatedElement) { self.interpolations.push(expression.into()); self.start_new_literal(); } } let mut collector = Collector::default(); for element in value.elements() { match element { ast::InterpolatedStringElement::Literal(literal) => { collector.push_literal(&literal.value); } ast::InterpolatedStringElement::Interpolation(interpolation) => { collector.push_tstring_interpolation(interpolation); } } } Self { strings: collector.strings.into_boxed_slice(), interpolations: collector.interpolations.into_boxed_slice(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableStringLiteral<'a> { value: &'a str, } impl<'a> From<&'a ast::StringLiteral> for ComparableStringLiteral<'a> { fn from(string_literal: &'a ast::StringLiteral) -> Self { Self { value: &string_literal.value, } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableBytesLiteral<'a> { value: Cow<'a, [u8]>, } impl<'a> From<&'a ast::BytesLiteral> for ComparableBytesLiteral<'a> { fn from(bytes_literal: &'a ast::BytesLiteral) -> Self { Self { value: Cow::Borrowed(&bytes_literal.value), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprBoolOp<'a> { op: ComparableBoolOp, values: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprNamed<'a> { target: Box>, value: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprBinOp<'a> { left: Box>, op: ComparableOperator, right: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprUnaryOp<'a> { op: ComparableUnaryOp, operand: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprLambda<'a> { parameters: Option>, body: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprIf<'a> { test: Box>, body: Box>, orelse: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableDictItem<'a> { key: Option>, value: ComparableExpr<'a>, } impl<'a> From<&'a ast::DictItem> for ComparableDictItem<'a> { fn from(ast::DictItem { key, value }: &'a ast::DictItem) -> Self { Self { key: key.as_ref().map(ComparableExpr::from), value: value.into(), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprDict<'a> { items: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprSet<'a> { elts: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprListComp<'a> { elt: Box>, generators: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprSetComp<'a> { elt: Box>, generators: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprDictComp<'a> { key: Option>>, value: Box>, generators: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprGenerator<'a> { elt: Box>, generators: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprAwait<'a> { value: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprYield<'a> { value: Option>>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprYieldFrom<'a> { value: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprCompare<'a> { left: Box>, ops: Vec, comparators: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprCall<'a> { func: Box>, arguments: ComparableArguments<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprInterpolatedElement<'a> { value: Box>, debug_text: Option>, conversion: ast::ConversionFlag, format_spec: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprFString<'a> { value: ComparableFString<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprTString<'a> { value: ComparableTString<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprStringLiteral<'a> { value: ComparableStringLiteral<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprBytesLiteral<'a> { value: ComparableBytesLiteral<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprNumberLiteral<'a> { value: ComparableNumber<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprBoolLiteral { value: bool, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprAttribute<'a> { value: Box>, attr: &'a str, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprSubscript<'a> { value: Box>, slice: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprStarred<'a> { value: Box>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprName<'a> { id: &'a str, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprList<'a> { elts: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprTuple<'a> { elts: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprSlice<'a> { lower: Option>>, upper: Option>>, step: Option>>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprIpyEscapeCommand<'a> { kind: ast::IpyEscapeKind, value: &'a str, } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableExpr<'a> { BoolOp(ExprBoolOp<'a>), NamedExpr(ExprNamed<'a>), BinOp(ExprBinOp<'a>), UnaryOp(ExprUnaryOp<'a>), Lambda(ExprLambda<'a>), IfExp(ExprIf<'a>), Dict(ExprDict<'a>), Set(ExprSet<'a>), ListComp(ExprListComp<'a>), SetComp(ExprSetComp<'a>), DictComp(ExprDictComp<'a>), GeneratorExp(ExprGenerator<'a>), Await(ExprAwait<'a>), Yield(ExprYield<'a>), YieldFrom(ExprYieldFrom<'a>), Compare(ExprCompare<'a>), Call(ExprCall<'a>), FStringExpressionElement(ExprInterpolatedElement<'a>), FString(ExprFString<'a>), TStringInterpolationElement(ExprInterpolatedElement<'a>), TString(ExprTString<'a>), StringLiteral(ExprStringLiteral<'a>), BytesLiteral(ExprBytesLiteral<'a>), NumberLiteral(ExprNumberLiteral<'a>), BoolLiteral(ExprBoolLiteral), NoneLiteral, EllipsisLiteral, Attribute(ExprAttribute<'a>), Subscript(ExprSubscript<'a>), Starred(ExprStarred<'a>), Name(ExprName<'a>), List(ExprList<'a>), Tuple(ExprTuple<'a>), Slice(ExprSlice<'a>), IpyEscapeCommand(ExprIpyEscapeCommand<'a>), } impl<'a> From<&'a Box> for Box> { fn from(expr: &'a Box) -> Self { Box::new((expr.as_ref()).into()) } } impl<'a> From<&'a Box> for ComparableExpr<'a> { fn from(expr: &'a Box) -> Self { (expr.as_ref()).into() } } impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { fn from(expr: &'a ast::Expr) -> Self { match expr { ast::Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, node_index: _, }) => Self::BoolOp(ExprBoolOp { op: (*op).into(), values: values.iter().map(Into::into).collect(), }), ast::Expr::Named(ast::ExprNamed { target, value, range: _, node_index: _, }) => Self::NamedExpr(ExprNamed { target: target.into(), value: value.into(), }), ast::Expr::BinOp(ast::ExprBinOp { left, op, right, range: _, node_index: _, }) => Self::BinOp(ExprBinOp { left: left.into(), op: (*op).into(), right: right.into(), }), ast::Expr::UnaryOp(ast::ExprUnaryOp { op, operand, range: _, node_index: _, }) => Self::UnaryOp(ExprUnaryOp { op: (*op).into(), operand: operand.into(), }), ast::Expr::Lambda(ast::ExprLambda { parameters, body, range: _, node_index: _, }) => Self::Lambda(ExprLambda { parameters: parameters.as_ref().map(Into::into), body: body.into(), }), ast::Expr::If(ast::ExprIf { test, body, orelse, range: _, node_index: _, }) => Self::IfExp(ExprIf { test: test.into(), body: body.into(), orelse: orelse.into(), }), ast::Expr::Dict(ast::ExprDict { items, range: _, node_index: _, }) => Self::Dict(ExprDict { items: items.iter().map(ComparableDictItem::from).collect(), }), ast::Expr::Set(ast::ExprSet { elts, range: _, node_index: _, }) => Self::Set(ExprSet { elts: elts.iter().map(Into::into).collect(), }), ast::Expr::ListComp(ast::ExprListComp { elt, generators, range: _, node_index: _, }) => Self::ListComp(ExprListComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }), ast::Expr::SetComp(ast::ExprSetComp { elt, generators, range: _, node_index: _, }) => Self::SetComp(ExprSetComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }), ast::Expr::DictComp(ast::ExprDictComp { key, value, generators, range: _, node_index: _, }) => Self::DictComp(ExprDictComp { key: key.as_ref().map(Into::into), value: value.into(), generators: generators.iter().map(Into::into).collect(), }), ast::Expr::Generator(ast::ExprGenerator { elt, generators, range: _, node_index: _, parenthesized: _, }) => Self::GeneratorExp(ExprGenerator { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }), ast::Expr::Await(ast::ExprAwait { value, range: _, node_index: _, }) => Self::Await(ExprAwait { value: value.into(), }), ast::Expr::Yield(ast::ExprYield { value, range: _, node_index: _, }) => Self::Yield(ExprYield { value: value.as_ref().map(Into::into), }), ast::Expr::YieldFrom(ast::ExprYieldFrom { value, range: _, node_index: _, }) => Self::YieldFrom(ExprYieldFrom { value: value.into(), }), ast::Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _, node_index: _, }) => Self::Compare(ExprCompare { left: left.into(), ops: ops.iter().copied().map(Into::into).collect(), comparators: comparators.iter().map(Into::into).collect(), }), ast::Expr::Call(ast::ExprCall { func, arguments, range_start: _, node_index: _, }) => Self::Call(ExprCall { func: func.into(), arguments: arguments.into(), }), ast::Expr::FString(ast::ExprFString { value, range: _, node_index: _, }) => Self::FString(ExprFString { value: value.into(), }), ast::Expr::TString(ast::ExprTString { value, range: _, node_index: _, }) => Self::TString(ExprTString { value: value.into(), }), ast::Expr::StringLiteral(ast::ExprStringLiteral { value, range: _, node_index: _, }) => Self::StringLiteral(ExprStringLiteral { value: ComparableStringLiteral { value: value.to_str(), }, }), ast::Expr::BytesLiteral(ast::ExprBytesLiteral { value, range: _, node_index: _, }) => Self::BytesLiteral(ExprBytesLiteral { value: ComparableBytesLiteral { value: Cow::from(value), }, }), ast::Expr::NumberLiteral(ast::ExprNumberLiteral { value, range: _, node_index: _, }) => Self::NumberLiteral(ExprNumberLiteral { value: value.into(), }), ast::Expr::BooleanLiteral(ast::ExprBooleanLiteral { value, range: _, node_index: _, }) => Self::BoolLiteral(ExprBoolLiteral { value: *value }), ast::Expr::NoneLiteral(_) => Self::NoneLiteral, ast::Expr::EllipsisLiteral(_) => Self::EllipsisLiteral, ast::Expr::Attribute(ast::ExprAttribute { value, attr, ctx: _, range: _, node_index: _, }) => Self::Attribute(ExprAttribute { value: value.into(), attr: attr.as_str(), }), ast::Expr::Subscript(ast::ExprSubscript { value, slice, ctx: _, range: _, node_index: _, }) => Self::Subscript(ExprSubscript { value: value.into(), slice: slice.into(), }), ast::Expr::Starred(ast::ExprStarred { value, ctx: _, range: _, node_index: _, }) => Self::Starred(ExprStarred { value: value.into(), }), ast::Expr::Name(name) => name.into(), ast::Expr::List(ast::ExprList { elts, ctx: _, range: _, node_index: _, }) => Self::List(ExprList { elts: elts.iter().map(Into::into).collect(), }), ast::Expr::Tuple(ast::ExprTuple { elts, ctx: _, range: _, node_index: _, parenthesized: _, }) => Self::Tuple(ExprTuple { elts: elts.iter().map(Into::into).collect(), }), ast::Expr::Slice(ast::ExprSlice { lower, upper, step, range: _, node_index: _, }) => 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::IpyEscapeCommand(ast::ExprIpyEscapeCommand { kind, value, range: _, node_index: _, }) => Self::IpyEscapeCommand(ExprIpyEscapeCommand { kind: *kind, value }), } } } impl<'a> From<&'a ast::ExprName> for ComparableExpr<'a> { fn from(expr: &'a ast::ExprName) -> Self { Self::Name(ExprName { id: expr.id.as_str(), }) } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtFunctionDef<'a> { is_async: bool, decorator_list: Vec>, name: &'a str, 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, type_params: Option>, arguments: ComparableArguments<'a>, body: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtReturn<'a> { value: Option>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtDelete<'a> { targets: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtTypeAlias<'a> { pub name: Box>, 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>), ParamSpec(TypeParamParamSpec<'a>), TypeVarTuple(TypeParamTypeVarTuple<'a>), } impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> { fn from(type_param: &'a ast::TypeParam) -> Self { match type_param { ast::TypeParam::TypeVar(ast::TypeParamTypeVar { name, bound, default, range: _, node_index: _, }) => Self::TypeVar(TypeParamTypeVar { name: name.as_str(), bound: bound.as_ref().map(Into::into), default: default.as_ref().map(Into::into), }), ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, default, range: _, node_index: _, }) => Self::TypeVarTuple(TypeParamTypeVarTuple { name: name.as_str(), default: default.as_ref().map(Into::into), }), ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, default, range: _, node_index: _, }) => Self::ParamSpec(TypeParamParamSpec { name: name.as_str(), default: default.as_ref().map(Into::into), }), } } } #[derive(Debug, PartialEq, Eq, Hash)] pub struct TypeParamTypeVar<'a> { pub name: &'a str, pub bound: Option>>, pub default: Option>>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct TypeParamParamSpec<'a> { pub name: &'a str, pub default: Option>>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct TypeParamTypeVarTuple<'a> { pub name: &'a str, pub default: Option>>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtAssign<'a> { targets: Vec>, value: ComparableExpr<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtAugAssign<'a> { target: ComparableExpr<'a>, op: ComparableOperator, value: ComparableExpr<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtAnnAssign<'a> { target: ComparableExpr<'a>, annotation: ComparableExpr<'a>, value: Option>, simple: bool, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtFor<'a> { is_async: bool, target: ComparableExpr<'a>, iter: ComparableExpr<'a>, body: Vec>, orelse: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtWhile<'a> { test: ComparableExpr<'a>, body: Vec>, orelse: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtIf<'a> { test: ComparableExpr<'a>, body: Vec>, elif_else_clauses: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtWith<'a> { is_async: bool, items: Vec>, body: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtMatch<'a> { subject: ComparableExpr<'a>, cases: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtRaise<'a> { exc: Option>, cause: Option>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtTry<'a> { body: Vec>, handlers: Vec>, orelse: Vec>, finalbody: Vec>, is_star: bool, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtAssert<'a> { test: ComparableExpr<'a>, msg: Option>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtImport<'a> { names: Vec>, is_lazy: bool, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtImportFrom<'a> { module: Option<&'a str>, names: Vec>, level: u32, is_lazy: bool, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtGlobal<'a> { names: Vec<&'a str>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtNonlocal<'a> { names: Vec<&'a str>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtExpr<'a> { value: ComparableExpr<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtIpyEscapeCommand<'a> { kind: ast::IpyEscapeKind, value: &'a str, } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableStmt<'a> { FunctionDef(StmtFunctionDef<'a>), ClassDef(StmtClassDef<'a>), Return(StmtReturn<'a>), Delete(StmtDelete<'a>), Assign(StmtAssign<'a>), AugAssign(StmtAugAssign<'a>), AnnAssign(StmtAnnAssign<'a>), For(StmtFor<'a>), While(StmtWhile<'a>), If(StmtIf<'a>), With(StmtWith<'a>), Match(StmtMatch<'a>), Raise(StmtRaise<'a>), Try(StmtTry<'a>), TypeAlias(StmtTypeAlias<'a>), Assert(StmtAssert<'a>), Import(StmtImport<'a>), ImportFrom(StmtImportFrom<'a>), Global(StmtGlobal<'a>), Nonlocal(StmtNonlocal<'a>), IpyEscapeCommand(StmtIpyEscapeCommand<'a>), Expr(StmtExpr<'a>), Pass, Break, Continue, } 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, parameters, body, decorator_list, returns, type_params, range: _, node_index: _, }) => Self::FunctionDef(StmtFunctionDef { is_async: *is_async, name: name.as_str(), 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.as_ref().map(Into::into), }), ast::Stmt::ClassDef(ast::StmtClassDef { name, arguments, body, decorator_list, type_params, range: _, node_index: _, }) => Self::ClassDef(StmtClassDef { name: name.as_str(), arguments: arguments.as_ref().map(Into::into).unwrap_or_default(), body: body.iter().map(Into::into).collect(), decorator_list: decorator_list.iter().map(Into::into).collect(), type_params: type_params.as_ref().map(Into::into), }), ast::Stmt::Return(ast::StmtReturn { value, range: _, node_index: _, }) => Self::Return(StmtReturn { value: value.as_ref().map(Into::into), }), ast::Stmt::Delete(ast::StmtDelete { targets, range: _, node_index: _, }) => Self::Delete(StmtDelete { targets: targets.iter().map(Into::into).collect(), }), ast::Stmt::TypeAlias(ast::StmtTypeAlias { range: _, node_index: _, name, type_params, value, }) => Self::TypeAlias(StmtTypeAlias { name: name.into(), type_params: type_params.as_ref().map(Into::into), value: value.into(), }), ast::Stmt::Assign(ast::StmtAssign { targets, value, range: _, node_index: _, }) => Self::Assign(StmtAssign { targets: targets.iter().map(Into::into).collect(), value: value.into(), }), ast::Stmt::AugAssign(ast::StmtAugAssign { target, op, value, range: _, node_index: _, }) => Self::AugAssign(StmtAugAssign { target: target.into(), op: (*op).into(), value: value.into(), }), ast::Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, simple, range: _, node_index: _, }) => Self::AnnAssign(StmtAnnAssign { target: target.into(), annotation: annotation.into(), value: value.as_ref().map(Into::into), simple: *simple, }), ast::Stmt::For(ast::StmtFor { is_async, target, iter, body, orelse, range: _, node_index: _, }) => Self::For(StmtFor { is_async: *is_async, target: target.into(), iter: iter.into(), body: body.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), }), ast::Stmt::While(ast::StmtWhile { test, body, orelse, range: _, node_index: _, }) => Self::While(StmtWhile { test: test.into(), body: body.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), }), ast::Stmt::If(ast::StmtIf { test, body, elif_else_clauses, range: _, node_index: _, }) => 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: _, node_index: _, }) => Self::With(StmtWith { 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: _, node_index: _, }) => Self::Match(StmtMatch { subject: subject.into(), cases: cases.iter().map(Into::into).collect(), }), ast::Stmt::Raise(ast::StmtRaise { exc, cause, range: _, node_index: _, }) => Self::Raise(StmtRaise { exc: exc.as_ref().map(Into::into), cause: cause.as_ref().map(Into::into), }), ast::Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, is_star, range: _, node_index: _, }) => 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(), is_star: *is_star, }), ast::Stmt::Assert(ast::StmtAssert { test, msg, range: _, node_index: _, }) => Self::Assert(StmtAssert { test: test.into(), msg: msg.as_ref().map(Into::into), }), ast::Stmt::Import(ast::StmtImport { names, is_lazy, range: _, node_index: _, }) => Self::Import(StmtImport { names: names.iter().map(Into::into).collect(), is_lazy: *is_lazy, }), ast::Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, is_lazy, range: _, node_index: _, }) => Self::ImportFrom(StmtImportFrom { module: module.as_deref(), names: names.iter().map(Into::into).collect(), level: *level, is_lazy: *is_lazy, }), ast::Stmt::Global(ast::StmtGlobal { names, range: _, node_index: _, }) => Self::Global(StmtGlobal { names: names.iter().map(ast::Identifier::as_str).collect(), }), ast::Stmt::Nonlocal(ast::StmtNonlocal { names, range: _, node_index: _, }) => Self::Nonlocal(StmtNonlocal { names: names.iter().map(ast::Identifier::as_str).collect(), }), ast::Stmt::IpyEscapeCommand(ast::StmtIpyEscapeCommand { kind, value, range: _, node_index: _, }) => Self::IpyEscapeCommand(StmtIpyEscapeCommand { kind: *kind, value }), ast::Stmt::Expr(ast::StmtExpr { value, range: _, node_index: _, }) => Self::Expr(StmtExpr { value: value.into(), }), ast::Stmt::Pass(_) => Self::Pass, ast::Stmt::Break(_) => Self::Break, ast::Stmt::Continue(_) => Self::Continue, } } } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableMod<'a> { Module(ComparableModModule<'a>), Expression(ComparableModExpression<'a>), } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableModModule<'a> { body: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableModExpression<'a> { body: Box>, } impl<'a> From<&'a ast::Mod> for ComparableMod<'a> { fn from(mod_: &'a ast::Mod) -> Self { match mod_ { ast::Mod::Module(module) => Self::Module(module.into()), ast::Mod::Expression(expr) => Self::Expression(expr.into()), } } } impl<'a> From<&'a ast::ModModule> for ComparableModModule<'a> { fn from(module: &'a ast::ModModule) -> Self { Self { body: module.body.iter().map(Into::into).collect(), } } } impl<'a> From<&'a ast::ModExpression> for ComparableModExpression<'a> { fn from(expr: &'a ast::ModExpression) -> Self { Self { body: (&expr.body).into(), } } } /// Wrapper around [`Expr`] that implements [`Hash`] and [`PartialEq`] according to Python /// semantics: /// /// > Values that compare equal (such as 1, 1.0, and True) can be used interchangeably to index the /// > same dictionary entry. /// /// For example, considers `True`, `1`, and `1.0` to be equal, as they hash to the same value /// in Python, along with `False`, `0`, and `0.0`. /// /// See: #[derive(Debug, PartialEq, Eq, Hash)] pub struct HashableExpr<'a>(HashableExprKind<'a>); #[derive(Debug, PartialEq, Eq, Hash)] enum HashableExprKind<'a> { Comparable(ComparableExpr<'a>), Number(HashableNumber), NamedExpr { target: ComparableExpr<'a>, value: Box>, }, Tuple(Vec>), } #[derive(Debug, PartialEq, Eq, Hash)] struct HashableNumber { real: HashableReal, imag: HashableReal, } impl HashableNumber { fn real(real: HashableReal) -> Self { Self { real, imag: HashableReal::Integer(0), } } fn complex(real: HashableReal, imag: HashableReal) -> Self { Self { real, imag } } fn negate(mut self) -> Self { self.real.negate(); self.imag.negate(); self } fn into_real(self) -> Option { self.imag.is_zero().then_some(self.real) } } #[derive(Debug, PartialEq, Eq, Hash)] enum HashableReal { Integer(i128), Float(u64), } impl HashableReal { fn from_int(value: &ast::Int) -> Option { value.as_u64().map(i128::from).map(Self::Integer) } #[expect( clippy::cast_possible_truncation, clippy::cast_precision_loss, clippy::float_cmp, reason = "the round-trip check guarantees that the float is exactly representable as an integer" )] fn from_float(value: f64) -> Self { if value.is_finite() && value.abs() < U64_EXCLUSIVE_UPPER_BOUND { let integer = value as i128; if integer as f64 == value { return Self::Integer(integer); } } Self::Float(value.to_bits()) } #[expect( clippy::cast_precision_loss, reason = "Python converts real components to floats before complex arithmetic" )] fn into_float(self) -> Self { match self { Self::Integer(integer) => Self::from_float(integer as f64), Self::Float(_) => self, } } fn is_zero(&self) -> bool { matches!(self, Self::Integer(0)) } fn negate(&mut self) { match self { Self::Integer(integer) => *integer = -*integer, Self::Float(bits) => *bits ^= 1 << 63, } } } // `2^64`, the exclusive upper bound for values representable as a `u64`. const U64_EXCLUSIVE_UPPER_BOUND: f64 = 18_446_744_073_709_551_616.0; impl<'a> From<&'a Expr> for HashableExpr<'a> { fn from(expr: &'a Expr) -> Self { /// Returns a version of the given expression that can be hashed and compared according to /// Python semantics. fn as_hashable(expr: &Expr) -> HashableExprKind<'_> { if let Some(constant) = as_hashable_constant(expr) { return constant; } match expr { Expr::Named(named) => HashableExprKind::NamedExpr { target: ComparableExpr::from(&named.target), value: Box::new(as_hashable(&named.value)), }, _ => HashableExprKind::Comparable(ComparableExpr::from(expr)), } } /// Returns a hashable representation if the expression's value is statically known. fn as_hashable_constant(expr: &Expr) -> Option> { if let Some(number) = as_number(expr) { return Some(HashableExprKind::Number(number)); } let kind = match expr { Expr::Tuple(tuple) => HashableExprKind::Tuple( tuple .iter() .map(as_hashable_constant) .collect::>()?, ), _ if expr.is_literal_expr() => { HashableExprKind::Comparable(ComparableExpr::from(expr)) } _ => return None, }; Some(kind) } fn as_number(expr: &Expr) -> Option { match expr { Expr::BooleanLiteral(boolean) => Some(HashableNumber::real(HashableReal::Integer( i128::from(u8::from(boolean.value)), ))), Expr::NumberLiteral(number) => match &number.value { Number::Int(int) => HashableReal::from_int(int).map(HashableNumber::real), Number::Float(float) => { Some(HashableNumber::real(HashableReal::from_float(*float))) } Number::Complex { real, imag } => Some(HashableNumber::complex( HashableReal::from_float(*real), HashableReal::from_float(*imag), )), }, Expr::UnaryOp(ast::ExprUnaryOp { op, operand, .. }) => match op { ast::UnaryOp::UAdd => as_number(operand), ast::UnaryOp::USub => as_number(operand).map(HashableNumber::negate), ast::UnaryOp::Invert | ast::UnaryOp::Not => None, }, Expr::BinOp(ast::ExprBinOp { left, op: op @ (ast::Operator::Add | ast::Operator::Sub), right, .. }) => { let real = as_number(left)?.into_real()?.into_float(); let Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Complex { real: complex_real, imag, }, .. }) = right.as_ref() else { return None; }; let complex_real = HashableReal::from_float(*complex_real); if !complex_real.is_zero() { return None; } let mut imag = HashableReal::from_float(*imag); if op.is_sub() { imag.negate(); } Some(HashableNumber::complex(real, imag)) } _ => None, } } Self(as_hashable(expr)) } } ast_serialize-0.13.1/crates/ruff_python_ast/src/docstrings.rs000064400000000000000000000014531046102023000213560ustar00//! Utilities for parsing Python docstrings. /// Extract the leading words from a line of text within a Python docstring. pub fn leading_words(line: &str) -> &str { let line = line.trim(); line.find(|char: char| !char.is_alphanumeric() && !char.is_whitespace()) .map_or(line, |index| &line[..index]) } /// Extract the leading whitespace from a line of text within a Python docstring. pub fn leading_space(line: &str) -> &str { line.find(|char: char| !char.is_whitespace()) .map_or(line, |index| &line[..index]) } /// Replace any non-whitespace characters from an indentation string within a Python docstring. pub fn clean_space(indentation: &str) -> String { indentation .chars() .map(|char| if char.is_whitespace() { char } else { ' ' }) .collect() } ast_serialize-0.13.1/crates/ruff_python_ast/src/expression.rs000064400000000000000000000323641046102023000214030ustar00use std::iter::FusedIterator; use ruff_text_size::{Ranged, TextRange}; use crate::{ self as ast, AnyNodeRef, AnyStringFlags, Expr, ExprBytesLiteral, ExprFString, ExprRef, ExprStringLiteral, ExprTString, StringFlags, }; impl<'a> From<&'a Box> for ExprRef<'a> { fn from(value: &'a Box) -> Self { ExprRef::from(value.as_ref()) } } /// Unowned pendant to all the literal variants of [`ast::Expr`] that stores a /// reference instead of an owned value. #[derive(Copy, Clone, Debug, PartialEq, is_macro::Is)] pub enum LiteralExpressionRef<'a> { StringLiteral(&'a ast::ExprStringLiteral), BytesLiteral(&'a ast::ExprBytesLiteral), NumberLiteral(&'a ast::ExprNumberLiteral), BooleanLiteral(&'a ast::ExprBooleanLiteral), NoneLiteral(&'a ast::ExprNoneLiteral), EllipsisLiteral(&'a ast::ExprEllipsisLiteral), } impl Ranged for LiteralExpressionRef<'_> { fn range(&self) -> TextRange { match self { LiteralExpressionRef::StringLiteral(expression) => expression.range(), LiteralExpressionRef::BytesLiteral(expression) => expression.range(), LiteralExpressionRef::NumberLiteral(expression) => expression.range(), LiteralExpressionRef::BooleanLiteral(expression) => expression.range(), LiteralExpressionRef::NoneLiteral(expression) => expression.range(), LiteralExpressionRef::EllipsisLiteral(expression) => expression.range(), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(value: LiteralExpressionRef<'a>) -> Self { match value { LiteralExpressionRef::StringLiteral(expression) => { AnyNodeRef::ExprStringLiteral(expression) } LiteralExpressionRef::BytesLiteral(expression) => { AnyNodeRef::ExprBytesLiteral(expression) } LiteralExpressionRef::NumberLiteral(expression) => { AnyNodeRef::ExprNumberLiteral(expression) } LiteralExpressionRef::BooleanLiteral(expression) => { AnyNodeRef::ExprBooleanLiteral(expression) } LiteralExpressionRef::NoneLiteral(expression) => { AnyNodeRef::ExprNoneLiteral(expression) } LiteralExpressionRef::EllipsisLiteral(expression) => { AnyNodeRef::ExprEllipsisLiteral(expression) } } } } impl LiteralExpressionRef<'_> { /// Returns `true` if the literal is either a string or bytes literal that /// is implicitly concatenated. pub fn is_implicit_concatenated(&self) -> bool { match self { LiteralExpressionRef::StringLiteral(expression) => { expression.value.is_implicit_concatenated() } LiteralExpressionRef::BytesLiteral(expression) => { expression.value.is_implicit_concatenated() } _ => false, } } } /// An enum that holds a reference to a string-like expression from the AST. This includes string /// literals, bytes literals, f-strings, and t-strings. #[derive(Copy, Clone, Debug, PartialEq)] pub enum StringLike<'a> { String(&'a ast::ExprStringLiteral), Bytes(&'a ast::ExprBytesLiteral), FString(&'a ast::ExprFString), TString(&'a ast::ExprTString), } impl<'a> StringLike<'a> { pub const fn is_interpolated_string(self) -> bool { matches!(self, Self::TString(_) | Self::FString(_)) } /// Returns an iterator over the [`StringLikePart`] contained in this string-like expression. pub fn parts(&self) -> StringLikePartIter<'a> { match self { StringLike::String(expr) => StringLikePartIter::String(expr.value.iter()), StringLike::Bytes(expr) => StringLikePartIter::Bytes(expr.value.iter()), StringLike::FString(expr) => StringLikePartIter::FString(expr.value.iter()), StringLike::TString(expr) => StringLikePartIter::TString(expr.value.iter()), } } /// Returns `true` if the string is implicitly concatenated. pub fn is_implicit_concatenated(self) -> bool { match self { Self::String(ExprStringLiteral { value, .. }) => value.is_implicit_concatenated(), Self::Bytes(ExprBytesLiteral { value, .. }) => value.is_implicit_concatenated(), Self::FString(ExprFString { value, .. }) => value.is_implicit_concatenated(), Self::TString(ExprTString { value, .. }) => value.is_implicit_concatenated(), } } pub const fn as_expression_ref(self) -> ExprRef<'a> { match self { StringLike::String(expr) => ExprRef::StringLiteral(expr), StringLike::Bytes(expr) => ExprRef::BytesLiteral(expr), StringLike::FString(expr) => ExprRef::FString(expr), StringLike::TString(expr) => ExprRef::TString(expr), } } } impl<'a> From<&'a ast::ExprStringLiteral> for StringLike<'a> { fn from(value: &'a ast::ExprStringLiteral) -> Self { StringLike::String(value) } } impl<'a> From<&'a ast::ExprBytesLiteral> for StringLike<'a> { fn from(value: &'a ast::ExprBytesLiteral) -> Self { StringLike::Bytes(value) } } impl<'a> From<&'a ast::ExprFString> for StringLike<'a> { fn from(value: &'a ast::ExprFString) -> Self { StringLike::FString(value) } } impl<'a> From<&'a ast::ExprTString> for StringLike<'a> { fn from(value: &'a ast::ExprTString) -> Self { StringLike::TString(value) } } impl<'a> From<&StringLike<'a>> for ExprRef<'a> { fn from(value: &StringLike<'a>) -> Self { match value { StringLike::String(expr) => ExprRef::StringLiteral(expr), StringLike::Bytes(expr) => ExprRef::BytesLiteral(expr), StringLike::FString(expr) => ExprRef::FString(expr), StringLike::TString(expr) => ExprRef::TString(expr), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(value: StringLike<'a>) -> Self { AnyNodeRef::from(&value) } } impl<'a> From<&StringLike<'a>> for AnyNodeRef<'a> { fn from(value: &StringLike<'a>) -> Self { match value { StringLike::String(expr) => AnyNodeRef::ExprStringLiteral(expr), StringLike::Bytes(expr) => AnyNodeRef::ExprBytesLiteral(expr), StringLike::FString(expr) => AnyNodeRef::ExprFString(expr), StringLike::TString(expr) => AnyNodeRef::ExprTString(expr), } } } impl<'a> TryFrom<&'a Expr> for StringLike<'a> { type Error = (); fn try_from(value: &'a Expr) -> Result { match value { Expr::StringLiteral(value) => Ok(Self::String(value)), Expr::BytesLiteral(value) => Ok(Self::Bytes(value)), Expr::FString(value) => Ok(Self::FString(value)), Expr::TString(value) => Ok(Self::TString(value)), _ => Err(()), } } } impl<'a> TryFrom> for StringLike<'a> { type Error = (); fn try_from(value: AnyNodeRef<'a>) -> Result { match value { AnyNodeRef::ExprStringLiteral(value) => Ok(Self::String(value)), AnyNodeRef::ExprBytesLiteral(value) => Ok(Self::Bytes(value)), AnyNodeRef::ExprFString(value) => Ok(Self::FString(value)), AnyNodeRef::ExprTString(value) => Ok(Self::TString(value)), _ => Err(()), } } } impl Ranged for StringLike<'_> { fn range(&self) -> TextRange { match self { StringLike::String(literal) => literal.range(), StringLike::Bytes(literal) => literal.range(), StringLike::FString(literal) => literal.range(), StringLike::TString(literal) => literal.range(), } } } /// An enum that holds a reference to an individual part of a string-like expression. #[derive(Copy, Clone, Debug, PartialEq)] pub enum StringLikePart<'a> { String(&'a ast::StringLiteral), Bytes(&'a ast::BytesLiteral), FString(&'a ast::FString), TString(&'a ast::TString), } impl<'a> StringLikePart<'a> { /// Returns the [`AnyStringFlags`] for the current string-like part. pub fn flags(&self) -> AnyStringFlags { match self { StringLikePart::String(string) => AnyStringFlags::from(string.flags), StringLikePart::Bytes(bytes) => AnyStringFlags::from(bytes.flags), StringLikePart::FString(f_string) => AnyStringFlags::from(f_string.flags), StringLikePart::TString(t_string) => AnyStringFlags::from(t_string.flags), } } /// Returns the range of the string's content in the source (minus prefix and quotes). pub fn content_range(self) -> TextRange { let kind = self.flags(); TextRange::new( self.start() + kind.opener_len(), self.end() - kind.closer_len(), ) } pub const fn is_string_literal(self) -> bool { matches!(self, Self::String(_)) } pub const fn as_string_literal(self) -> Option<&'a ast::StringLiteral> { match self { StringLikePart::String(value) => Some(value), _ => None, } } pub const fn is_interpolated_string(self) -> bool { matches!(self, Self::FString(_) | Self::TString(_)) } } impl<'a> From<&'a ast::StringLiteral> for StringLikePart<'a> { fn from(value: &'a ast::StringLiteral) -> Self { StringLikePart::String(value) } } impl<'a> From<&'a ast::BytesLiteral> for StringLikePart<'a> { fn from(value: &'a ast::BytesLiteral) -> Self { StringLikePart::Bytes(value) } } impl<'a> From<&'a ast::FString> for StringLikePart<'a> { fn from(value: &'a ast::FString) -> Self { StringLikePart::FString(value) } } impl<'a> From<&'a ast::TString> for StringLikePart<'a> { fn from(value: &'a ast::TString) -> Self { StringLikePart::TString(value) } } impl<'a> From<&StringLikePart<'a>> for AnyNodeRef<'a> { fn from(value: &StringLikePart<'a>) -> Self { AnyNodeRef::from(*value) } } impl<'a> From> for AnyNodeRef<'a> { fn from(value: StringLikePart<'a>) -> Self { match value { StringLikePart::String(part) => AnyNodeRef::StringLiteral(part), StringLikePart::Bytes(part) => AnyNodeRef::BytesLiteral(part), StringLikePart::FString(part) => AnyNodeRef::FString(part), StringLikePart::TString(part) => AnyNodeRef::TString(part), } } } impl Ranged for StringLikePart<'_> { fn range(&self) -> TextRange { match self { StringLikePart::String(part) => part.range(), StringLikePart::Bytes(part) => part.range(), StringLikePart::FString(part) => part.range(), StringLikePart::TString(part) => part.range(), } } } /// An iterator over all the [`StringLikePart`] of a string-like expression. /// /// This is created by the [`StringLike::parts`] method. #[derive(Clone)] pub enum StringLikePartIter<'a> { String(std::slice::Iter<'a, ast::StringLiteral>), Bytes(std::slice::Iter<'a, ast::BytesLiteral>), FString(std::slice::Iter<'a, ast::FStringPart>), TString(std::slice::Iter<'a, ast::TString>), } impl<'a> Iterator for StringLikePartIter<'a> { type Item = StringLikePart<'a>; fn next(&mut self) -> Option { let part = match self { StringLikePartIter::String(inner) => StringLikePart::String(inner.next()?), StringLikePartIter::Bytes(inner) => StringLikePart::Bytes(inner.next()?), StringLikePartIter::FString(inner) => { let part = inner.next()?; match part { ast::FStringPart::Literal(string_literal) => { StringLikePart::String(string_literal) } ast::FStringPart::FString(f_string) => StringLikePart::FString(f_string), } } StringLikePartIter::TString(inner) => StringLikePart::TString(inner.next()?), }; Some(part) } fn size_hint(&self) -> (usize, Option) { match self { StringLikePartIter::String(inner) => inner.size_hint(), StringLikePartIter::Bytes(inner) => inner.size_hint(), StringLikePartIter::FString(inner) => inner.size_hint(), StringLikePartIter::TString(inner) => inner.size_hint(), } } } impl DoubleEndedIterator for StringLikePartIter<'_> { fn next_back(&mut self) -> Option { let part = match self { StringLikePartIter::String(inner) => StringLikePart::String(inner.next_back()?), StringLikePartIter::Bytes(inner) => StringLikePart::Bytes(inner.next_back()?), StringLikePartIter::FString(inner) => { let part = inner.next_back()?; match part { ast::FStringPart::Literal(string_literal) => { StringLikePart::String(string_literal) } ast::FStringPart::FString(f_string) => StringLikePart::FString(f_string), } } StringLikePartIter::TString(inner) => StringLikePart::TString(inner.next_back()?), }; Some(part) } } impl FusedIterator for StringLikePartIter<'_> {} impl ExactSizeIterator for StringLikePartIter<'_> {} ast_serialize-0.13.1/crates/ruff_python_ast/src/find_node.rs000064400000000000000000000112241046102023000211210ustar00use crate::AnyNodeRef; use crate::visitor::source_order::{SourceOrderVisitor, TraversalSignal, walk_node}; use ruff_text_size::{Ranged, TextRange}; use std::fmt; use std::fmt::Formatter; /// Returns the node with a minimal range that fully contains `range`. /// /// If `range` is empty and falls within a parser *synthesized* node generated during error recovery, /// then the first node with the given range is returned. /// /// ## Panics /// Panics if `range` is not contained within `root`. pub fn covering_node(root: AnyNodeRef, range: TextRange) -> CoveringNode { struct Visitor<'a> { range: TextRange, found: bool, ancestors: Vec>, } impl<'a> SourceOrderVisitor<'a> for Visitor<'a> { fn enter_node(&mut self, node: AnyNodeRef<'a>) -> TraversalSignal { // If the node fully contains the range, than it is a possible match but traverse into its children // to see if there's a node with a narrower range. if !self.found && node.range().contains_range(self.range) { self.ancestors.push(node); TraversalSignal::Traverse } else { TraversalSignal::Skip } } fn leave_node(&mut self, node: AnyNodeRef<'a>) { if !self.found && self.ancestors.last() == Some(&node) { self.found = true; } } } assert!( root.range().contains_range(range), "Range is not contained within root" ); let mut visitor = Visitor { range, found: false, ancestors: Vec::new(), }; walk_node(&mut visitor, root); CoveringNode::from_ancestors(visitor.ancestors) } /// The node with a minimal range that fully contains the search range. pub struct CoveringNode<'a> { /// The covering node, along with all of its ancestors up to the /// root. The root is always the first element and the covering /// node found is always the last node. This sequence is guaranteed /// to be non-empty. nodes: Vec>, } impl<'a> CoveringNode<'a> { /// Creates a new `CoveringNode` from a list of ancestor nodes. /// The ancestors should be ordered from root to the covering node. pub fn from_ancestors(ancestors: Vec>) -> Self { Self { nodes: ancestors } } /// Returns the covering node found. pub fn node(&self) -> AnyNodeRef<'a> { *self .nodes .last() .expect("`CoveringNode::nodes` should always be non-empty") } /// Returns the node's parent. pub fn parent(&self) -> Option> { let penultimate = self.nodes.len().checked_sub(2)?; self.nodes.get(penultimate).copied() } /// Finds the first node that fully covers the range and fulfills /// the given predicate. /// /// The "first" here means that the node closest to a leaf is /// returned. pub fn find_first(mut self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Result { let Some(index) = self.find_first_index(f) else { return Err(self); }; self.nodes.truncate(index + 1); Ok(self) } /// Finds the last node that fully covers the range and fulfills /// the given predicate. /// /// The "last" here means that after finding the "first" such node, /// the highest ancestor found satisfying the given predicate is /// returned. Note that this is *not* the same as finding the node /// closest to the root that satisfies the given predicate. pub fn find_last(mut self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Result { let Some(mut index) = self.find_first_index(&f) else { return Err(self); }; while index > 0 && f(self.nodes[index - 1]) { index -= 1; } self.nodes.truncate(index + 1); Ok(self) } /// Returns an iterator over the ancestor nodes, starting with the node itself /// and walking towards the root. pub fn ancestors(&self) -> impl DoubleEndedIterator> + '_ { self.nodes.iter().copied().rev() } /// Finds the index of the node that fully covers the range and /// fulfills the given predicate. /// /// If there are no nodes matching the given predicate, then /// `None` is returned. fn find_first_index(&self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Option { self.nodes.iter().rposition(|node| f(*node)) } } impl fmt::Debug for CoveringNode<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("CoveringNode").field(&self.node()).finish() } } ast_serialize-0.13.1/crates/ruff_python_ast/src/generated.rs000064400000000000000000012445041046102023000211440ustar00// This is a generated file. Don't modify it by hand! // Run `crates/ruff_python_ast/generate.py` to re-generate the file. use crate::name::Name; use crate::visitor::source_order::SourceOrderVisitor; /// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Mod { Module(crate::ModModule), Expression(crate::ModExpression), } impl From for Mod { fn from(node: crate::ModModule) -> Self { Self::Module(node) } } impl From for Mod { fn from(node: crate::ModExpression) -> Self { Self::Expression(node) } } impl ruff_text_size::Ranged for Mod { fn range(&self) -> ruff_text_size::TextRange { match self { Self::Module(node) => node.range(), Self::Expression(node) => node.range(), } } } impl crate::HasNodeIndex for Mod { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::Module(node) => node.node_index(), Self::Expression(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl Mod { #[inline] pub const fn is_module(&self) -> bool { matches!(self, Self::Module(_)) } #[inline] pub fn module(self) -> Option { match self { Self::Module(val) => Some(val), _ => None, } } #[inline] pub fn expect_module(self) -> crate::ModModule { match self { Self::Module(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_module_mut(&mut self) -> Option<&mut crate::ModModule> { match self { Self::Module(val) => Some(val), _ => None, } } #[inline] pub fn as_module(&self) -> Option<&crate::ModModule> { match self { Self::Module(val) => Some(val), _ => None, } } #[inline] pub const fn is_expression(&self) -> bool { matches!(self, Self::Expression(_)) } #[inline] pub fn expression(self) -> Option { match self { Self::Expression(val) => Some(val), _ => None, } } #[inline] pub fn expect_expression(self) -> crate::ModExpression { match self { Self::Expression(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_expression_mut(&mut self) -> Option<&mut crate::ModExpression> { match self { Self::Expression(val) => Some(val), _ => None, } } #[inline] pub fn as_expression(&self) -> Option<&crate::ModExpression> { match self { Self::Expression(val) => Some(val), _ => None, } } } /// See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Stmt { FunctionDef(crate::StmtFunctionDef), ClassDef(crate::StmtClassDef), Return(crate::StmtReturn), Delete(crate::StmtDelete), TypeAlias(crate::StmtTypeAlias), Assign(crate::StmtAssign), AugAssign(crate::StmtAugAssign), AnnAssign(crate::StmtAnnAssign), For(crate::StmtFor), While(crate::StmtWhile), If(crate::StmtIf), With(crate::StmtWith), Match(crate::StmtMatch), Raise(crate::StmtRaise), Try(crate::StmtTry), Assert(crate::StmtAssert), Import(crate::StmtImport), ImportFrom(crate::StmtImportFrom), Global(crate::StmtGlobal), Nonlocal(crate::StmtNonlocal), Expr(crate::StmtExpr), Pass(crate::StmtPass), Break(crate::StmtBreak), Continue(crate::StmtContinue), IpyEscapeCommand(crate::StmtIpyEscapeCommand), } impl From for Stmt { fn from(node: crate::StmtFunctionDef) -> Self { Self::FunctionDef(node) } } impl From for Stmt { fn from(node: crate::StmtClassDef) -> Self { Self::ClassDef(node) } } impl From for Stmt { fn from(node: crate::StmtReturn) -> Self { Self::Return(node) } } impl From for Stmt { fn from(node: crate::StmtDelete) -> Self { Self::Delete(node) } } impl From for Stmt { fn from(node: crate::StmtTypeAlias) -> Self { Self::TypeAlias(node) } } impl From for Stmt { fn from(node: crate::StmtAssign) -> Self { Self::Assign(node) } } impl From for Stmt { fn from(node: crate::StmtAugAssign) -> Self { Self::AugAssign(node) } } impl From for Stmt { fn from(node: crate::StmtAnnAssign) -> Self { Self::AnnAssign(node) } } impl From for Stmt { fn from(node: crate::StmtFor) -> Self { Self::For(node) } } impl From for Stmt { fn from(node: crate::StmtWhile) -> Self { Self::While(node) } } impl From for Stmt { fn from(node: crate::StmtIf) -> Self { Self::If(node) } } impl From for Stmt { fn from(node: crate::StmtWith) -> Self { Self::With(node) } } impl From for Stmt { fn from(node: crate::StmtMatch) -> Self { Self::Match(node) } } impl From for Stmt { fn from(node: crate::StmtRaise) -> Self { Self::Raise(node) } } impl From for Stmt { fn from(node: crate::StmtTry) -> Self { Self::Try(node) } } impl From for Stmt { fn from(node: crate::StmtAssert) -> Self { Self::Assert(node) } } impl From for Stmt { fn from(node: crate::StmtImport) -> Self { Self::Import(node) } } impl From for Stmt { fn from(node: crate::StmtImportFrom) -> Self { Self::ImportFrom(node) } } impl From for Stmt { fn from(node: crate::StmtGlobal) -> Self { Self::Global(node) } } impl From for Stmt { fn from(node: crate::StmtNonlocal) -> Self { Self::Nonlocal(node) } } impl From for Stmt { fn from(node: crate::StmtExpr) -> Self { Self::Expr(node) } } impl From for Stmt { fn from(node: crate::StmtPass) -> Self { Self::Pass(node) } } impl From for Stmt { fn from(node: crate::StmtBreak) -> Self { Self::Break(node) } } impl From for Stmt { fn from(node: crate::StmtContinue) -> Self { Self::Continue(node) } } impl From for Stmt { fn from(node: crate::StmtIpyEscapeCommand) -> Self { Self::IpyEscapeCommand(node) } } impl ruff_text_size::Ranged for Stmt { fn range(&self) -> ruff_text_size::TextRange { match self { Self::FunctionDef(node) => node.range(), Self::ClassDef(node) => node.range(), Self::Return(node) => node.range(), Self::Delete(node) => node.range(), Self::TypeAlias(node) => node.range(), Self::Assign(node) => node.range(), Self::AugAssign(node) => node.range(), Self::AnnAssign(node) => node.range(), Self::For(node) => node.range(), Self::While(node) => node.range(), Self::If(node) => node.range(), Self::With(node) => node.range(), Self::Match(node) => node.range(), Self::Raise(node) => node.range(), Self::Try(node) => node.range(), Self::Assert(node) => node.range(), Self::Import(node) => node.range(), Self::ImportFrom(node) => node.range(), Self::Global(node) => node.range(), Self::Nonlocal(node) => node.range(), Self::Expr(node) => node.range(), Self::Pass(node) => node.range(), Self::Break(node) => node.range(), Self::Continue(node) => node.range(), Self::IpyEscapeCommand(node) => node.range(), } } } impl crate::HasNodeIndex for Stmt { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::FunctionDef(node) => node.node_index(), Self::ClassDef(node) => node.node_index(), Self::Return(node) => node.node_index(), Self::Delete(node) => node.node_index(), Self::TypeAlias(node) => node.node_index(), Self::Assign(node) => node.node_index(), Self::AugAssign(node) => node.node_index(), Self::AnnAssign(node) => node.node_index(), Self::For(node) => node.node_index(), Self::While(node) => node.node_index(), Self::If(node) => node.node_index(), Self::With(node) => node.node_index(), Self::Match(node) => node.node_index(), Self::Raise(node) => node.node_index(), Self::Try(node) => node.node_index(), Self::Assert(node) => node.node_index(), Self::Import(node) => node.node_index(), Self::ImportFrom(node) => node.node_index(), Self::Global(node) => node.node_index(), Self::Nonlocal(node) => node.node_index(), Self::Expr(node) => node.node_index(), Self::Pass(node) => node.node_index(), Self::Break(node) => node.node_index(), Self::Continue(node) => node.node_index(), Self::IpyEscapeCommand(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl Stmt { #[inline] pub const fn is_function_def_stmt(&self) -> bool { matches!(self, Self::FunctionDef(_)) } #[inline] pub fn function_def_stmt(self) -> Option { match self { Self::FunctionDef(val) => Some(val), _ => None, } } #[inline] pub fn expect_function_def_stmt(self) -> crate::StmtFunctionDef { match self { Self::FunctionDef(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_function_def_stmt_mut(&mut self) -> Option<&mut crate::StmtFunctionDef> { match self { Self::FunctionDef(val) => Some(val), _ => None, } } #[inline] pub fn as_function_def_stmt(&self) -> Option<&crate::StmtFunctionDef> { match self { Self::FunctionDef(val) => Some(val), _ => None, } } #[inline] pub const fn is_class_def_stmt(&self) -> bool { matches!(self, Self::ClassDef(_)) } #[inline] pub fn class_def_stmt(self) -> Option { match self { Self::ClassDef(val) => Some(val), _ => None, } } #[inline] pub fn expect_class_def_stmt(self) -> crate::StmtClassDef { match self { Self::ClassDef(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_class_def_stmt_mut(&mut self) -> Option<&mut crate::StmtClassDef> { match self { Self::ClassDef(val) => Some(val), _ => None, } } #[inline] pub fn as_class_def_stmt(&self) -> Option<&crate::StmtClassDef> { match self { Self::ClassDef(val) => Some(val), _ => None, } } #[inline] pub const fn is_return_stmt(&self) -> bool { matches!(self, Self::Return(_)) } #[inline] pub fn return_stmt(self) -> Option { match self { Self::Return(val) => Some(val), _ => None, } } #[inline] pub fn expect_return_stmt(self) -> crate::StmtReturn { match self { Self::Return(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_return_stmt_mut(&mut self) -> Option<&mut crate::StmtReturn> { match self { Self::Return(val) => Some(val), _ => None, } } #[inline] pub fn as_return_stmt(&self) -> Option<&crate::StmtReturn> { match self { Self::Return(val) => Some(val), _ => None, } } #[inline] pub const fn is_delete_stmt(&self) -> bool { matches!(self, Self::Delete(_)) } #[inline] pub fn delete_stmt(self) -> Option { match self { Self::Delete(val) => Some(val), _ => None, } } #[inline] pub fn expect_delete_stmt(self) -> crate::StmtDelete { match self { Self::Delete(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_delete_stmt_mut(&mut self) -> Option<&mut crate::StmtDelete> { match self { Self::Delete(val) => Some(val), _ => None, } } #[inline] pub fn as_delete_stmt(&self) -> Option<&crate::StmtDelete> { match self { Self::Delete(val) => Some(val), _ => None, } } #[inline] pub const fn is_type_alias_stmt(&self) -> bool { matches!(self, Self::TypeAlias(_)) } #[inline] pub fn type_alias_stmt(self) -> Option { match self { Self::TypeAlias(val) => Some(val), _ => None, } } #[inline] pub fn expect_type_alias_stmt(self) -> crate::StmtTypeAlias { match self { Self::TypeAlias(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_type_alias_stmt_mut(&mut self) -> Option<&mut crate::StmtTypeAlias> { match self { Self::TypeAlias(val) => Some(val), _ => None, } } #[inline] pub fn as_type_alias_stmt(&self) -> Option<&crate::StmtTypeAlias> { match self { Self::TypeAlias(val) => Some(val), _ => None, } } #[inline] pub const fn is_assign_stmt(&self) -> bool { matches!(self, Self::Assign(_)) } #[inline] pub fn assign_stmt(self) -> Option { match self { Self::Assign(val) => Some(val), _ => None, } } #[inline] pub fn expect_assign_stmt(self) -> crate::StmtAssign { match self { Self::Assign(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_assign_stmt_mut(&mut self) -> Option<&mut crate::StmtAssign> { match self { Self::Assign(val) => Some(val), _ => None, } } #[inline] pub fn as_assign_stmt(&self) -> Option<&crate::StmtAssign> { match self { Self::Assign(val) => Some(val), _ => None, } } #[inline] pub const fn is_aug_assign_stmt(&self) -> bool { matches!(self, Self::AugAssign(_)) } #[inline] pub fn aug_assign_stmt(self) -> Option { match self { Self::AugAssign(val) => Some(val), _ => None, } } #[inline] pub fn expect_aug_assign_stmt(self) -> crate::StmtAugAssign { match self { Self::AugAssign(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_aug_assign_stmt_mut(&mut self) -> Option<&mut crate::StmtAugAssign> { match self { Self::AugAssign(val) => Some(val), _ => None, } } #[inline] pub fn as_aug_assign_stmt(&self) -> Option<&crate::StmtAugAssign> { match self { Self::AugAssign(val) => Some(val), _ => None, } } #[inline] pub const fn is_ann_assign_stmt(&self) -> bool { matches!(self, Self::AnnAssign(_)) } #[inline] pub fn ann_assign_stmt(self) -> Option { match self { Self::AnnAssign(val) => Some(val), _ => None, } } #[inline] pub fn expect_ann_assign_stmt(self) -> crate::StmtAnnAssign { match self { Self::AnnAssign(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_ann_assign_stmt_mut(&mut self) -> Option<&mut crate::StmtAnnAssign> { match self { Self::AnnAssign(val) => Some(val), _ => None, } } #[inline] pub fn as_ann_assign_stmt(&self) -> Option<&crate::StmtAnnAssign> { match self { Self::AnnAssign(val) => Some(val), _ => None, } } #[inline] pub const fn is_for_stmt(&self) -> bool { matches!(self, Self::For(_)) } #[inline] pub fn for_stmt(self) -> Option { match self { Self::For(val) => Some(val), _ => None, } } #[inline] pub fn expect_for_stmt(self) -> crate::StmtFor { match self { Self::For(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_for_stmt_mut(&mut self) -> Option<&mut crate::StmtFor> { match self { Self::For(val) => Some(val), _ => None, } } #[inline] pub fn as_for_stmt(&self) -> Option<&crate::StmtFor> { match self { Self::For(val) => Some(val), _ => None, } } #[inline] pub const fn is_while_stmt(&self) -> bool { matches!(self, Self::While(_)) } #[inline] pub fn while_stmt(self) -> Option { match self { Self::While(val) => Some(val), _ => None, } } #[inline] pub fn expect_while_stmt(self) -> crate::StmtWhile { match self { Self::While(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_while_stmt_mut(&mut self) -> Option<&mut crate::StmtWhile> { match self { Self::While(val) => Some(val), _ => None, } } #[inline] pub fn as_while_stmt(&self) -> Option<&crate::StmtWhile> { match self { Self::While(val) => Some(val), _ => None, } } #[inline] pub const fn is_if_stmt(&self) -> bool { matches!(self, Self::If(_)) } #[inline] pub fn if_stmt(self) -> Option { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub fn expect_if_stmt(self) -> crate::StmtIf { match self { Self::If(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_if_stmt_mut(&mut self) -> Option<&mut crate::StmtIf> { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub fn as_if_stmt(&self) -> Option<&crate::StmtIf> { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub const fn is_with_stmt(&self) -> bool { matches!(self, Self::With(_)) } #[inline] pub fn with_stmt(self) -> Option { match self { Self::With(val) => Some(val), _ => None, } } #[inline] pub fn expect_with_stmt(self) -> crate::StmtWith { match self { Self::With(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_with_stmt_mut(&mut self) -> Option<&mut crate::StmtWith> { match self { Self::With(val) => Some(val), _ => None, } } #[inline] pub fn as_with_stmt(&self) -> Option<&crate::StmtWith> { match self { Self::With(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_stmt(&self) -> bool { matches!(self, Self::Match(_)) } #[inline] pub fn match_stmt(self) -> Option { match self { Self::Match(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_stmt(self) -> crate::StmtMatch { match self { Self::Match(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_stmt_mut(&mut self) -> Option<&mut crate::StmtMatch> { match self { Self::Match(val) => Some(val), _ => None, } } #[inline] pub fn as_match_stmt(&self) -> Option<&crate::StmtMatch> { match self { Self::Match(val) => Some(val), _ => None, } } #[inline] pub const fn is_raise_stmt(&self) -> bool { matches!(self, Self::Raise(_)) } #[inline] pub fn raise_stmt(self) -> Option { match self { Self::Raise(val) => Some(val), _ => None, } } #[inline] pub fn expect_raise_stmt(self) -> crate::StmtRaise { match self { Self::Raise(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_raise_stmt_mut(&mut self) -> Option<&mut crate::StmtRaise> { match self { Self::Raise(val) => Some(val), _ => None, } } #[inline] pub fn as_raise_stmt(&self) -> Option<&crate::StmtRaise> { match self { Self::Raise(val) => Some(val), _ => None, } } #[inline] pub const fn is_try_stmt(&self) -> bool { matches!(self, Self::Try(_)) } #[inline] pub fn try_stmt(self) -> Option { match self { Self::Try(val) => Some(val), _ => None, } } #[inline] pub fn expect_try_stmt(self) -> crate::StmtTry { match self { Self::Try(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_try_stmt_mut(&mut self) -> Option<&mut crate::StmtTry> { match self { Self::Try(val) => Some(val), _ => None, } } #[inline] pub fn as_try_stmt(&self) -> Option<&crate::StmtTry> { match self { Self::Try(val) => Some(val), _ => None, } } #[inline] pub const fn is_assert_stmt(&self) -> bool { matches!(self, Self::Assert(_)) } #[inline] pub fn assert_stmt(self) -> Option { match self { Self::Assert(val) => Some(val), _ => None, } } #[inline] pub fn expect_assert_stmt(self) -> crate::StmtAssert { match self { Self::Assert(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_assert_stmt_mut(&mut self) -> Option<&mut crate::StmtAssert> { match self { Self::Assert(val) => Some(val), _ => None, } } #[inline] pub fn as_assert_stmt(&self) -> Option<&crate::StmtAssert> { match self { Self::Assert(val) => Some(val), _ => None, } } #[inline] pub const fn is_import_stmt(&self) -> bool { matches!(self, Self::Import(_)) } #[inline] pub fn import_stmt(self) -> Option { match self { Self::Import(val) => Some(val), _ => None, } } #[inline] pub fn expect_import_stmt(self) -> crate::StmtImport { match self { Self::Import(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_import_stmt_mut(&mut self) -> Option<&mut crate::StmtImport> { match self { Self::Import(val) => Some(val), _ => None, } } #[inline] pub fn as_import_stmt(&self) -> Option<&crate::StmtImport> { match self { Self::Import(val) => Some(val), _ => None, } } #[inline] pub const fn is_import_from_stmt(&self) -> bool { matches!(self, Self::ImportFrom(_)) } #[inline] pub fn import_from_stmt(self) -> Option { match self { Self::ImportFrom(val) => Some(val), _ => None, } } #[inline] pub fn expect_import_from_stmt(self) -> crate::StmtImportFrom { match self { Self::ImportFrom(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_import_from_stmt_mut(&mut self) -> Option<&mut crate::StmtImportFrom> { match self { Self::ImportFrom(val) => Some(val), _ => None, } } #[inline] pub fn as_import_from_stmt(&self) -> Option<&crate::StmtImportFrom> { match self { Self::ImportFrom(val) => Some(val), _ => None, } } #[inline] pub const fn is_global_stmt(&self) -> bool { matches!(self, Self::Global(_)) } #[inline] pub fn global_stmt(self) -> Option { match self { Self::Global(val) => Some(val), _ => None, } } #[inline] pub fn expect_global_stmt(self) -> crate::StmtGlobal { match self { Self::Global(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_global_stmt_mut(&mut self) -> Option<&mut crate::StmtGlobal> { match self { Self::Global(val) => Some(val), _ => None, } } #[inline] pub fn as_global_stmt(&self) -> Option<&crate::StmtGlobal> { match self { Self::Global(val) => Some(val), _ => None, } } #[inline] pub const fn is_nonlocal_stmt(&self) -> bool { matches!(self, Self::Nonlocal(_)) } #[inline] pub fn nonlocal_stmt(self) -> Option { match self { Self::Nonlocal(val) => Some(val), _ => None, } } #[inline] pub fn expect_nonlocal_stmt(self) -> crate::StmtNonlocal { match self { Self::Nonlocal(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_nonlocal_stmt_mut(&mut self) -> Option<&mut crate::StmtNonlocal> { match self { Self::Nonlocal(val) => Some(val), _ => None, } } #[inline] pub fn as_nonlocal_stmt(&self) -> Option<&crate::StmtNonlocal> { match self { Self::Nonlocal(val) => Some(val), _ => None, } } #[inline] pub const fn is_expr_stmt(&self) -> bool { matches!(self, Self::Expr(_)) } #[inline] pub fn expr_stmt(self) -> Option { match self { Self::Expr(val) => Some(val), _ => None, } } #[inline] pub fn expect_expr_stmt(self) -> crate::StmtExpr { match self { Self::Expr(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_expr_stmt_mut(&mut self) -> Option<&mut crate::StmtExpr> { match self { Self::Expr(val) => Some(val), _ => None, } } #[inline] pub fn as_expr_stmt(&self) -> Option<&crate::StmtExpr> { match self { Self::Expr(val) => Some(val), _ => None, } } #[inline] pub const fn is_pass_stmt(&self) -> bool { matches!(self, Self::Pass(_)) } #[inline] pub fn pass_stmt(self) -> Option { match self { Self::Pass(val) => Some(val), _ => None, } } #[inline] pub fn expect_pass_stmt(self) -> crate::StmtPass { match self { Self::Pass(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_pass_stmt_mut(&mut self) -> Option<&mut crate::StmtPass> { match self { Self::Pass(val) => Some(val), _ => None, } } #[inline] pub fn as_pass_stmt(&self) -> Option<&crate::StmtPass> { match self { Self::Pass(val) => Some(val), _ => None, } } #[inline] pub const fn is_break_stmt(&self) -> bool { matches!(self, Self::Break(_)) } #[inline] pub fn break_stmt(self) -> Option { match self { Self::Break(val) => Some(val), _ => None, } } #[inline] pub fn expect_break_stmt(self) -> crate::StmtBreak { match self { Self::Break(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_break_stmt_mut(&mut self) -> Option<&mut crate::StmtBreak> { match self { Self::Break(val) => Some(val), _ => None, } } #[inline] pub fn as_break_stmt(&self) -> Option<&crate::StmtBreak> { match self { Self::Break(val) => Some(val), _ => None, } } #[inline] pub const fn is_continue_stmt(&self) -> bool { matches!(self, Self::Continue(_)) } #[inline] pub fn continue_stmt(self) -> Option { match self { Self::Continue(val) => Some(val), _ => None, } } #[inline] pub fn expect_continue_stmt(self) -> crate::StmtContinue { match self { Self::Continue(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_continue_stmt_mut(&mut self) -> Option<&mut crate::StmtContinue> { match self { Self::Continue(val) => Some(val), _ => None, } } #[inline] pub fn as_continue_stmt(&self) -> Option<&crate::StmtContinue> { match self { Self::Continue(val) => Some(val), _ => None, } } #[inline] pub const fn is_ipy_escape_command_stmt(&self) -> bool { matches!(self, Self::IpyEscapeCommand(_)) } #[inline] pub fn ipy_escape_command_stmt(self) -> Option { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } #[inline] pub fn expect_ipy_escape_command_stmt(self) -> crate::StmtIpyEscapeCommand { match self { Self::IpyEscapeCommand(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_ipy_escape_command_stmt_mut(&mut self) -> Option<&mut crate::StmtIpyEscapeCommand> { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } #[inline] pub fn as_ipy_escape_command_stmt(&self) -> Option<&crate::StmtIpyEscapeCommand> { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } } /// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Expr { BoolOp(crate::ExprBoolOp), Named(crate::ExprNamed), BinOp(crate::ExprBinOp), UnaryOp(crate::ExprUnaryOp), Lambda(crate::ExprLambda), If(crate::ExprIf), Dict(crate::ExprDict), Set(crate::ExprSet), ListComp(crate::ExprListComp), SetComp(crate::ExprSetComp), DictComp(crate::ExprDictComp), Generator(crate::ExprGenerator), Await(crate::ExprAwait), Yield(crate::ExprYield), YieldFrom(crate::ExprYieldFrom), Compare(crate::ExprCompare), Call(crate::ExprCall), FString(crate::ExprFString), TString(crate::ExprTString), StringLiteral(crate::ExprStringLiteral), BytesLiteral(crate::ExprBytesLiteral), NumberLiteral(crate::ExprNumberLiteral), BooleanLiteral(crate::ExprBooleanLiteral), NoneLiteral(crate::ExprNoneLiteral), EllipsisLiteral(crate::ExprEllipsisLiteral), Attribute(crate::ExprAttribute), Subscript(crate::ExprSubscript), Starred(crate::ExprStarred), Name(crate::ExprName), List(crate::ExprList), Tuple(crate::ExprTuple), Slice(crate::ExprSlice), IpyEscapeCommand(crate::ExprIpyEscapeCommand), } impl From for Expr { fn from(node: crate::ExprBoolOp) -> Self { Self::BoolOp(node) } } impl From for Expr { fn from(node: crate::ExprNamed) -> Self { Self::Named(node) } } impl From for Expr { fn from(node: crate::ExprBinOp) -> Self { Self::BinOp(node) } } impl From for Expr { fn from(node: crate::ExprUnaryOp) -> Self { Self::UnaryOp(node) } } impl From for Expr { fn from(node: crate::ExprLambda) -> Self { Self::Lambda(node) } } impl From for Expr { fn from(node: crate::ExprIf) -> Self { Self::If(node) } } impl From for Expr { fn from(node: crate::ExprDict) -> Self { Self::Dict(node) } } impl From for Expr { fn from(node: crate::ExprSet) -> Self { Self::Set(node) } } impl From for Expr { fn from(node: crate::ExprListComp) -> Self { Self::ListComp(node) } } impl From for Expr { fn from(node: crate::ExprSetComp) -> Self { Self::SetComp(node) } } impl From for Expr { fn from(node: crate::ExprDictComp) -> Self { Self::DictComp(node) } } impl From for Expr { fn from(node: crate::ExprGenerator) -> Self { Self::Generator(node) } } impl From for Expr { fn from(node: crate::ExprAwait) -> Self { Self::Await(node) } } impl From for Expr { fn from(node: crate::ExprYield) -> Self { Self::Yield(node) } } impl From for Expr { fn from(node: crate::ExprYieldFrom) -> Self { Self::YieldFrom(node) } } impl From for Expr { fn from(node: crate::ExprCompare) -> Self { Self::Compare(node) } } impl From for Expr { fn from(node: crate::ExprCall) -> Self { Self::Call(node) } } impl From for Expr { fn from(node: crate::ExprFString) -> Self { Self::FString(node) } } impl From for Expr { fn from(node: crate::ExprTString) -> Self { Self::TString(node) } } impl From for Expr { fn from(node: crate::ExprStringLiteral) -> Self { Self::StringLiteral(node) } } impl From for Expr { fn from(node: crate::ExprBytesLiteral) -> Self { Self::BytesLiteral(node) } } impl From for Expr { fn from(node: crate::ExprNumberLiteral) -> Self { Self::NumberLiteral(node) } } impl From for Expr { fn from(node: crate::ExprBooleanLiteral) -> Self { Self::BooleanLiteral(node) } } impl From for Expr { fn from(node: crate::ExprNoneLiteral) -> Self { Self::NoneLiteral(node) } } impl From for Expr { fn from(node: crate::ExprEllipsisLiteral) -> Self { Self::EllipsisLiteral(node) } } impl From for Expr { fn from(node: crate::ExprAttribute) -> Self { Self::Attribute(node) } } impl From for Expr { fn from(node: crate::ExprSubscript) -> Self { Self::Subscript(node) } } impl From for Expr { fn from(node: crate::ExprStarred) -> Self { Self::Starred(node) } } impl From for Expr { fn from(node: crate::ExprName) -> Self { Self::Name(node) } } impl From for Expr { fn from(node: crate::ExprList) -> Self { Self::List(node) } } impl From for Expr { fn from(node: crate::ExprTuple) -> Self { Self::Tuple(node) } } impl From for Expr { fn from(node: crate::ExprSlice) -> Self { Self::Slice(node) } } impl From for Expr { fn from(node: crate::ExprIpyEscapeCommand) -> Self { Self::IpyEscapeCommand(node) } } impl ruff_text_size::Ranged for Expr { fn range(&self) -> ruff_text_size::TextRange { match self { Self::BoolOp(node) => node.range(), Self::Named(node) => node.range(), Self::BinOp(node) => node.range(), Self::UnaryOp(node) => node.range(), Self::Lambda(node) => node.range(), Self::If(node) => node.range(), Self::Dict(node) => node.range(), Self::Set(node) => node.range(), Self::ListComp(node) => node.range(), Self::SetComp(node) => node.range(), Self::DictComp(node) => node.range(), Self::Generator(node) => node.range(), Self::Await(node) => node.range(), Self::Yield(node) => node.range(), Self::YieldFrom(node) => node.range(), Self::Compare(node) => node.range(), Self::Call(node) => node.range(), Self::FString(node) => node.range(), Self::TString(node) => node.range(), Self::StringLiteral(node) => node.range(), Self::BytesLiteral(node) => node.range(), Self::NumberLiteral(node) => node.range(), Self::BooleanLiteral(node) => node.range(), Self::NoneLiteral(node) => node.range(), Self::EllipsisLiteral(node) => node.range(), Self::Attribute(node) => node.range(), Self::Subscript(node) => node.range(), Self::Starred(node) => node.range(), Self::Name(node) => node.range(), Self::List(node) => node.range(), Self::Tuple(node) => node.range(), Self::Slice(node) => node.range(), Self::IpyEscapeCommand(node) => node.range(), } } } impl crate::HasNodeIndex for Expr { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::BoolOp(node) => node.node_index(), Self::Named(node) => node.node_index(), Self::BinOp(node) => node.node_index(), Self::UnaryOp(node) => node.node_index(), Self::Lambda(node) => node.node_index(), Self::If(node) => node.node_index(), Self::Dict(node) => node.node_index(), Self::Set(node) => node.node_index(), Self::ListComp(node) => node.node_index(), Self::SetComp(node) => node.node_index(), Self::DictComp(node) => node.node_index(), Self::Generator(node) => node.node_index(), Self::Await(node) => node.node_index(), Self::Yield(node) => node.node_index(), Self::YieldFrom(node) => node.node_index(), Self::Compare(node) => node.node_index(), Self::Call(node) => node.node_index(), Self::FString(node) => node.node_index(), Self::TString(node) => node.node_index(), Self::StringLiteral(node) => node.node_index(), Self::BytesLiteral(node) => node.node_index(), Self::NumberLiteral(node) => node.node_index(), Self::BooleanLiteral(node) => node.node_index(), Self::NoneLiteral(node) => node.node_index(), Self::EllipsisLiteral(node) => node.node_index(), Self::Attribute(node) => node.node_index(), Self::Subscript(node) => node.node_index(), Self::Starred(node) => node.node_index(), Self::Name(node) => node.node_index(), Self::List(node) => node.node_index(), Self::Tuple(node) => node.node_index(), Self::Slice(node) => node.node_index(), Self::IpyEscapeCommand(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl Expr { #[inline] pub const fn is_bool_op_expr(&self) -> bool { matches!(self, Self::BoolOp(_)) } #[inline] pub fn bool_op_expr(self) -> Option { match self { Self::BoolOp(val) => Some(val), _ => None, } } #[inline] pub fn expect_bool_op_expr(self) -> crate::ExprBoolOp { match self { Self::BoolOp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_bool_op_expr_mut(&mut self) -> Option<&mut crate::ExprBoolOp> { match self { Self::BoolOp(val) => Some(val), _ => None, } } #[inline] pub fn as_bool_op_expr(&self) -> Option<&crate::ExprBoolOp> { match self { Self::BoolOp(val) => Some(val), _ => None, } } #[inline] pub const fn is_named_expr(&self) -> bool { matches!(self, Self::Named(_)) } #[inline] pub fn named_expr(self) -> Option { match self { Self::Named(val) => Some(val), _ => None, } } #[inline] pub fn expect_named_expr(self) -> crate::ExprNamed { match self { Self::Named(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_named_expr_mut(&mut self) -> Option<&mut crate::ExprNamed> { match self { Self::Named(val) => Some(val), _ => None, } } #[inline] pub fn as_named_expr(&self) -> Option<&crate::ExprNamed> { match self { Self::Named(val) => Some(val), _ => None, } } #[inline] pub const fn is_bin_op_expr(&self) -> bool { matches!(self, Self::BinOp(_)) } #[inline] pub fn bin_op_expr(self) -> Option { match self { Self::BinOp(val) => Some(val), _ => None, } } #[inline] pub fn expect_bin_op_expr(self) -> crate::ExprBinOp { match self { Self::BinOp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_bin_op_expr_mut(&mut self) -> Option<&mut crate::ExprBinOp> { match self { Self::BinOp(val) => Some(val), _ => None, } } #[inline] pub fn as_bin_op_expr(&self) -> Option<&crate::ExprBinOp> { match self { Self::BinOp(val) => Some(val), _ => None, } } #[inline] pub const fn is_unary_op_expr(&self) -> bool { matches!(self, Self::UnaryOp(_)) } #[inline] pub fn unary_op_expr(self) -> Option { match self { Self::UnaryOp(val) => Some(val), _ => None, } } #[inline] pub fn expect_unary_op_expr(self) -> crate::ExprUnaryOp { match self { Self::UnaryOp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_unary_op_expr_mut(&mut self) -> Option<&mut crate::ExprUnaryOp> { match self { Self::UnaryOp(val) => Some(val), _ => None, } } #[inline] pub fn as_unary_op_expr(&self) -> Option<&crate::ExprUnaryOp> { match self { Self::UnaryOp(val) => Some(val), _ => None, } } #[inline] pub const fn is_lambda_expr(&self) -> bool { matches!(self, Self::Lambda(_)) } #[inline] pub fn lambda_expr(self) -> Option { match self { Self::Lambda(val) => Some(val), _ => None, } } #[inline] pub fn expect_lambda_expr(self) -> crate::ExprLambda { match self { Self::Lambda(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_lambda_expr_mut(&mut self) -> Option<&mut crate::ExprLambda> { match self { Self::Lambda(val) => Some(val), _ => None, } } #[inline] pub fn as_lambda_expr(&self) -> Option<&crate::ExprLambda> { match self { Self::Lambda(val) => Some(val), _ => None, } } #[inline] pub const fn is_if_expr(&self) -> bool { matches!(self, Self::If(_)) } #[inline] pub fn if_expr(self) -> Option { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub fn expect_if_expr(self) -> crate::ExprIf { match self { Self::If(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_if_expr_mut(&mut self) -> Option<&mut crate::ExprIf> { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub fn as_if_expr(&self) -> Option<&crate::ExprIf> { match self { Self::If(val) => Some(val), _ => None, } } #[inline] pub const fn is_dict_expr(&self) -> bool { matches!(self, Self::Dict(_)) } #[inline] pub fn dict_expr(self) -> Option { match self { Self::Dict(val) => Some(val), _ => None, } } #[inline] pub fn expect_dict_expr(self) -> crate::ExprDict { match self { Self::Dict(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_dict_expr_mut(&mut self) -> Option<&mut crate::ExprDict> { match self { Self::Dict(val) => Some(val), _ => None, } } #[inline] pub fn as_dict_expr(&self) -> Option<&crate::ExprDict> { match self { Self::Dict(val) => Some(val), _ => None, } } #[inline] pub const fn is_set_expr(&self) -> bool { matches!(self, Self::Set(_)) } #[inline] pub fn set_expr(self) -> Option { match self { Self::Set(val) => Some(val), _ => None, } } #[inline] pub fn expect_set_expr(self) -> crate::ExprSet { match self { Self::Set(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_set_expr_mut(&mut self) -> Option<&mut crate::ExprSet> { match self { Self::Set(val) => Some(val), _ => None, } } #[inline] pub fn as_set_expr(&self) -> Option<&crate::ExprSet> { match self { Self::Set(val) => Some(val), _ => None, } } #[inline] pub const fn is_list_comp_expr(&self) -> bool { matches!(self, Self::ListComp(_)) } #[inline] pub fn list_comp_expr(self) -> Option { match self { Self::ListComp(val) => Some(val), _ => None, } } #[inline] pub fn expect_list_comp_expr(self) -> crate::ExprListComp { match self { Self::ListComp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_list_comp_expr_mut(&mut self) -> Option<&mut crate::ExprListComp> { match self { Self::ListComp(val) => Some(val), _ => None, } } #[inline] pub fn as_list_comp_expr(&self) -> Option<&crate::ExprListComp> { match self { Self::ListComp(val) => Some(val), _ => None, } } #[inline] pub const fn is_set_comp_expr(&self) -> bool { matches!(self, Self::SetComp(_)) } #[inline] pub fn set_comp_expr(self) -> Option { match self { Self::SetComp(val) => Some(val), _ => None, } } #[inline] pub fn expect_set_comp_expr(self) -> crate::ExprSetComp { match self { Self::SetComp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_set_comp_expr_mut(&mut self) -> Option<&mut crate::ExprSetComp> { match self { Self::SetComp(val) => Some(val), _ => None, } } #[inline] pub fn as_set_comp_expr(&self) -> Option<&crate::ExprSetComp> { match self { Self::SetComp(val) => Some(val), _ => None, } } #[inline] pub const fn is_dict_comp_expr(&self) -> bool { matches!(self, Self::DictComp(_)) } #[inline] pub fn dict_comp_expr(self) -> Option { match self { Self::DictComp(val) => Some(val), _ => None, } } #[inline] pub fn expect_dict_comp_expr(self) -> crate::ExprDictComp { match self { Self::DictComp(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_dict_comp_expr_mut(&mut self) -> Option<&mut crate::ExprDictComp> { match self { Self::DictComp(val) => Some(val), _ => None, } } #[inline] pub fn as_dict_comp_expr(&self) -> Option<&crate::ExprDictComp> { match self { Self::DictComp(val) => Some(val), _ => None, } } #[inline] pub const fn is_generator_expr(&self) -> bool { matches!(self, Self::Generator(_)) } #[inline] pub fn generator_expr(self) -> Option { match self { Self::Generator(val) => Some(val), _ => None, } } #[inline] pub fn expect_generator_expr(self) -> crate::ExprGenerator { match self { Self::Generator(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_generator_expr_mut(&mut self) -> Option<&mut crate::ExprGenerator> { match self { Self::Generator(val) => Some(val), _ => None, } } #[inline] pub fn as_generator_expr(&self) -> Option<&crate::ExprGenerator> { match self { Self::Generator(val) => Some(val), _ => None, } } #[inline] pub const fn is_await_expr(&self) -> bool { matches!(self, Self::Await(_)) } #[inline] pub fn await_expr(self) -> Option { match self { Self::Await(val) => Some(val), _ => None, } } #[inline] pub fn expect_await_expr(self) -> crate::ExprAwait { match self { Self::Await(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_await_expr_mut(&mut self) -> Option<&mut crate::ExprAwait> { match self { Self::Await(val) => Some(val), _ => None, } } #[inline] pub fn as_await_expr(&self) -> Option<&crate::ExprAwait> { match self { Self::Await(val) => Some(val), _ => None, } } #[inline] pub const fn is_yield_expr(&self) -> bool { matches!(self, Self::Yield(_)) } #[inline] pub fn yield_expr(self) -> Option { match self { Self::Yield(val) => Some(val), _ => None, } } #[inline] pub fn expect_yield_expr(self) -> crate::ExprYield { match self { Self::Yield(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_yield_expr_mut(&mut self) -> Option<&mut crate::ExprYield> { match self { Self::Yield(val) => Some(val), _ => None, } } #[inline] pub fn as_yield_expr(&self) -> Option<&crate::ExprYield> { match self { Self::Yield(val) => Some(val), _ => None, } } #[inline] pub const fn is_yield_from_expr(&self) -> bool { matches!(self, Self::YieldFrom(_)) } #[inline] pub fn yield_from_expr(self) -> Option { match self { Self::YieldFrom(val) => Some(val), _ => None, } } #[inline] pub fn expect_yield_from_expr(self) -> crate::ExprYieldFrom { match self { Self::YieldFrom(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_yield_from_expr_mut(&mut self) -> Option<&mut crate::ExprYieldFrom> { match self { Self::YieldFrom(val) => Some(val), _ => None, } } #[inline] pub fn as_yield_from_expr(&self) -> Option<&crate::ExprYieldFrom> { match self { Self::YieldFrom(val) => Some(val), _ => None, } } #[inline] pub const fn is_compare_expr(&self) -> bool { matches!(self, Self::Compare(_)) } #[inline] pub fn compare_expr(self) -> Option { match self { Self::Compare(val) => Some(val), _ => None, } } #[inline] pub fn expect_compare_expr(self) -> crate::ExprCompare { match self { Self::Compare(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_compare_expr_mut(&mut self) -> Option<&mut crate::ExprCompare> { match self { Self::Compare(val) => Some(val), _ => None, } } #[inline] pub fn as_compare_expr(&self) -> Option<&crate::ExprCompare> { match self { Self::Compare(val) => Some(val), _ => None, } } #[inline] pub const fn is_call_expr(&self) -> bool { matches!(self, Self::Call(_)) } #[inline] pub fn call_expr(self) -> Option { match self { Self::Call(val) => Some(val), _ => None, } } #[inline] pub fn expect_call_expr(self) -> crate::ExprCall { match self { Self::Call(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_call_expr_mut(&mut self) -> Option<&mut crate::ExprCall> { match self { Self::Call(val) => Some(val), _ => None, } } #[inline] pub fn as_call_expr(&self) -> Option<&crate::ExprCall> { match self { Self::Call(val) => Some(val), _ => None, } } #[inline] pub const fn is_f_string_expr(&self) -> bool { matches!(self, Self::FString(_)) } #[inline] pub fn f_string_expr(self) -> Option { match self { Self::FString(val) => Some(val), _ => None, } } #[inline] pub fn expect_f_string_expr(self) -> crate::ExprFString { match self { Self::FString(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_f_string_expr_mut(&mut self) -> Option<&mut crate::ExprFString> { match self { Self::FString(val) => Some(val), _ => None, } } #[inline] pub fn as_f_string_expr(&self) -> Option<&crate::ExprFString> { match self { Self::FString(val) => Some(val), _ => None, } } #[inline] pub const fn is_t_string_expr(&self) -> bool { matches!(self, Self::TString(_)) } #[inline] pub fn t_string_expr(self) -> Option { match self { Self::TString(val) => Some(val), _ => None, } } #[inline] pub fn expect_t_string_expr(self) -> crate::ExprTString { match self { Self::TString(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_t_string_expr_mut(&mut self) -> Option<&mut crate::ExprTString> { match self { Self::TString(val) => Some(val), _ => None, } } #[inline] pub fn as_t_string_expr(&self) -> Option<&crate::ExprTString> { match self { Self::TString(val) => Some(val), _ => None, } } #[inline] pub const fn is_string_literal_expr(&self) -> bool { matches!(self, Self::StringLiteral(_)) } #[inline] pub fn string_literal_expr(self) -> Option { match self { Self::StringLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_string_literal_expr(self) -> crate::ExprStringLiteral { match self { Self::StringLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_string_literal_expr_mut(&mut self) -> Option<&mut crate::ExprStringLiteral> { match self { Self::StringLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_string_literal_expr(&self) -> Option<&crate::ExprStringLiteral> { match self { Self::StringLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_bytes_literal_expr(&self) -> bool { matches!(self, Self::BytesLiteral(_)) } #[inline] pub fn bytes_literal_expr(self) -> Option { match self { Self::BytesLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_bytes_literal_expr(self) -> crate::ExprBytesLiteral { match self { Self::BytesLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_bytes_literal_expr_mut(&mut self) -> Option<&mut crate::ExprBytesLiteral> { match self { Self::BytesLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_bytes_literal_expr(&self) -> Option<&crate::ExprBytesLiteral> { match self { Self::BytesLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_number_literal_expr(&self) -> bool { matches!(self, Self::NumberLiteral(_)) } #[inline] pub fn number_literal_expr(self) -> Option { match self { Self::NumberLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_number_literal_expr(self) -> crate::ExprNumberLiteral { match self { Self::NumberLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_number_literal_expr_mut(&mut self) -> Option<&mut crate::ExprNumberLiteral> { match self { Self::NumberLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_number_literal_expr(&self) -> Option<&crate::ExprNumberLiteral> { match self { Self::NumberLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_boolean_literal_expr(&self) -> bool { matches!(self, Self::BooleanLiteral(_)) } #[inline] pub fn boolean_literal_expr(self) -> Option { match self { Self::BooleanLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_boolean_literal_expr(self) -> crate::ExprBooleanLiteral { match self { Self::BooleanLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_boolean_literal_expr_mut(&mut self) -> Option<&mut crate::ExprBooleanLiteral> { match self { Self::BooleanLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_boolean_literal_expr(&self) -> Option<&crate::ExprBooleanLiteral> { match self { Self::BooleanLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_none_literal_expr(&self) -> bool { matches!(self, Self::NoneLiteral(_)) } #[inline] pub fn none_literal_expr(self) -> Option { match self { Self::NoneLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_none_literal_expr(self) -> crate::ExprNoneLiteral { match self { Self::NoneLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_none_literal_expr_mut(&mut self) -> Option<&mut crate::ExprNoneLiteral> { match self { Self::NoneLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_none_literal_expr(&self) -> Option<&crate::ExprNoneLiteral> { match self { Self::NoneLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_ellipsis_literal_expr(&self) -> bool { matches!(self, Self::EllipsisLiteral(_)) } #[inline] pub fn ellipsis_literal_expr(self) -> Option { match self { Self::EllipsisLiteral(val) => Some(val), _ => None, } } #[inline] pub fn expect_ellipsis_literal_expr(self) -> crate::ExprEllipsisLiteral { match self { Self::EllipsisLiteral(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_ellipsis_literal_expr_mut(&mut self) -> Option<&mut crate::ExprEllipsisLiteral> { match self { Self::EllipsisLiteral(val) => Some(val), _ => None, } } #[inline] pub fn as_ellipsis_literal_expr(&self) -> Option<&crate::ExprEllipsisLiteral> { match self { Self::EllipsisLiteral(val) => Some(val), _ => None, } } #[inline] pub const fn is_attribute_expr(&self) -> bool { matches!(self, Self::Attribute(_)) } #[inline] pub fn attribute_expr(self) -> Option { match self { Self::Attribute(val) => Some(val), _ => None, } } #[inline] pub fn expect_attribute_expr(self) -> crate::ExprAttribute { match self { Self::Attribute(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_attribute_expr_mut(&mut self) -> Option<&mut crate::ExprAttribute> { match self { Self::Attribute(val) => Some(val), _ => None, } } #[inline] pub fn as_attribute_expr(&self) -> Option<&crate::ExprAttribute> { match self { Self::Attribute(val) => Some(val), _ => None, } } #[inline] pub const fn is_subscript_expr(&self) -> bool { matches!(self, Self::Subscript(_)) } #[inline] pub fn subscript_expr(self) -> Option { match self { Self::Subscript(val) => Some(val), _ => None, } } #[inline] pub fn expect_subscript_expr(self) -> crate::ExprSubscript { match self { Self::Subscript(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_subscript_expr_mut(&mut self) -> Option<&mut crate::ExprSubscript> { match self { Self::Subscript(val) => Some(val), _ => None, } } #[inline] pub fn as_subscript_expr(&self) -> Option<&crate::ExprSubscript> { match self { Self::Subscript(val) => Some(val), _ => None, } } #[inline] pub const fn is_starred_expr(&self) -> bool { matches!(self, Self::Starred(_)) } #[inline] pub fn starred_expr(self) -> Option { match self { Self::Starred(val) => Some(val), _ => None, } } #[inline] pub fn expect_starred_expr(self) -> crate::ExprStarred { match self { Self::Starred(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_starred_expr_mut(&mut self) -> Option<&mut crate::ExprStarred> { match self { Self::Starred(val) => Some(val), _ => None, } } #[inline] pub fn as_starred_expr(&self) -> Option<&crate::ExprStarred> { match self { Self::Starred(val) => Some(val), _ => None, } } #[inline] pub const fn is_name_expr(&self) -> bool { matches!(self, Self::Name(_)) } #[inline] pub fn name_expr(self) -> Option { match self { Self::Name(val) => Some(val), _ => None, } } #[inline] pub fn expect_name_expr(self) -> crate::ExprName { match self { Self::Name(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_name_expr_mut(&mut self) -> Option<&mut crate::ExprName> { match self { Self::Name(val) => Some(val), _ => None, } } #[inline] pub fn as_name_expr(&self) -> Option<&crate::ExprName> { match self { Self::Name(val) => Some(val), _ => None, } } #[inline] pub const fn is_list_expr(&self) -> bool { matches!(self, Self::List(_)) } #[inline] pub fn list_expr(self) -> Option { match self { Self::List(val) => Some(val), _ => None, } } #[inline] pub fn expect_list_expr(self) -> crate::ExprList { match self { Self::List(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_list_expr_mut(&mut self) -> Option<&mut crate::ExprList> { match self { Self::List(val) => Some(val), _ => None, } } #[inline] pub fn as_list_expr(&self) -> Option<&crate::ExprList> { match self { Self::List(val) => Some(val), _ => None, } } #[inline] pub const fn is_tuple_expr(&self) -> bool { matches!(self, Self::Tuple(_)) } #[inline] pub fn tuple_expr(self) -> Option { match self { Self::Tuple(val) => Some(val), _ => None, } } #[inline] pub fn expect_tuple_expr(self) -> crate::ExprTuple { match self { Self::Tuple(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_tuple_expr_mut(&mut self) -> Option<&mut crate::ExprTuple> { match self { Self::Tuple(val) => Some(val), _ => None, } } #[inline] pub fn as_tuple_expr(&self) -> Option<&crate::ExprTuple> { match self { Self::Tuple(val) => Some(val), _ => None, } } #[inline] pub const fn is_slice_expr(&self) -> bool { matches!(self, Self::Slice(_)) } #[inline] pub fn slice_expr(self) -> Option { match self { Self::Slice(val) => Some(val), _ => None, } } #[inline] pub fn expect_slice_expr(self) -> crate::ExprSlice { match self { Self::Slice(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_slice_expr_mut(&mut self) -> Option<&mut crate::ExprSlice> { match self { Self::Slice(val) => Some(val), _ => None, } } #[inline] pub fn as_slice_expr(&self) -> Option<&crate::ExprSlice> { match self { Self::Slice(val) => Some(val), _ => None, } } #[inline] pub const fn is_ipy_escape_command_expr(&self) -> bool { matches!(self, Self::IpyEscapeCommand(_)) } #[inline] pub fn ipy_escape_command_expr(self) -> Option { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } #[inline] pub fn expect_ipy_escape_command_expr(self) -> crate::ExprIpyEscapeCommand { match self { Self::IpyEscapeCommand(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_ipy_escape_command_expr_mut(&mut self) -> Option<&mut crate::ExprIpyEscapeCommand> { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } #[inline] pub fn as_ipy_escape_command_expr(&self) -> Option<&crate::ExprIpyEscapeCommand> { match self { Self::IpyEscapeCommand(val) => Some(val), _ => None, } } } /// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum ExceptHandler { ExceptHandler(crate::ExceptHandlerExceptHandler), } impl From for ExceptHandler { fn from(node: crate::ExceptHandlerExceptHandler) -> Self { Self::ExceptHandler(node) } } impl ruff_text_size::Ranged for ExceptHandler { fn range(&self) -> ruff_text_size::TextRange { match self { Self::ExceptHandler(node) => node.range(), } } } impl crate::HasNodeIndex for ExceptHandler { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::ExceptHandler(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl ExceptHandler { #[inline] pub const fn is_except_handler(&self) -> bool { matches!(self, Self::ExceptHandler(_)) } #[inline] pub fn except_handler(self) -> Option { match self { Self::ExceptHandler(val) => Some(val), } } #[inline] pub fn expect_except_handler(self) -> crate::ExceptHandlerExceptHandler { match self { Self::ExceptHandler(val) => val, } } #[inline] pub fn as_except_handler_mut(&mut self) -> Option<&mut crate::ExceptHandlerExceptHandler> { match self { Self::ExceptHandler(val) => Some(val), } } #[inline] pub fn as_except_handler(&self) -> Option<&crate::ExceptHandlerExceptHandler> { match self { Self::ExceptHandler(val) => Some(val), } } } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum InterpolatedStringElement { Interpolation(crate::InterpolatedElement), Literal(crate::InterpolatedStringLiteralElement), } impl From for InterpolatedStringElement { fn from(node: crate::InterpolatedElement) -> Self { Self::Interpolation(node) } } impl From for InterpolatedStringElement { fn from(node: crate::InterpolatedStringLiteralElement) -> Self { Self::Literal(node) } } impl ruff_text_size::Ranged for InterpolatedStringElement { fn range(&self) -> ruff_text_size::TextRange { match self { Self::Interpolation(node) => node.range(), Self::Literal(node) => node.range(), } } } impl crate::HasNodeIndex for InterpolatedStringElement { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::Interpolation(node) => node.node_index(), Self::Literal(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl InterpolatedStringElement { #[inline] pub const fn is_interpolation(&self) -> bool { matches!(self, Self::Interpolation(_)) } #[inline] pub fn interpolation(self) -> Option { match self { Self::Interpolation(val) => Some(val), _ => None, } } #[inline] pub fn expect_interpolation(self) -> crate::InterpolatedElement { match self { Self::Interpolation(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_interpolation_mut(&mut self) -> Option<&mut crate::InterpolatedElement> { match self { Self::Interpolation(val) => Some(val), _ => None, } } #[inline] pub fn as_interpolation(&self) -> Option<&crate::InterpolatedElement> { match self { Self::Interpolation(val) => Some(val), _ => None, } } #[inline] pub const fn is_literal(&self) -> bool { matches!(self, Self::Literal(_)) } #[inline] pub fn literal(self) -> Option { match self { Self::Literal(val) => Some(val), _ => None, } } #[inline] pub fn expect_literal(self) -> crate::InterpolatedStringLiteralElement { match self { Self::Literal(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_literal_mut(&mut self) -> Option<&mut crate::InterpolatedStringLiteralElement> { match self { Self::Literal(val) => Some(val), _ => None, } } #[inline] pub fn as_literal(&self) -> Option<&crate::InterpolatedStringLiteralElement> { match self { Self::Literal(val) => Some(val), _ => None, } } } /// See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Pattern { MatchValue(crate::PatternMatchValue), MatchSingleton(crate::PatternMatchSingleton), MatchSequence(crate::PatternMatchSequence), MatchMapping(crate::PatternMatchMapping), MatchClass(crate::PatternMatchClass), MatchStar(crate::PatternMatchStar), MatchAs(crate::PatternMatchAs), MatchOr(crate::PatternMatchOr), } impl From for Pattern { fn from(node: crate::PatternMatchValue) -> Self { Self::MatchValue(node) } } impl From for Pattern { fn from(node: crate::PatternMatchSingleton) -> Self { Self::MatchSingleton(node) } } impl From for Pattern { fn from(node: crate::PatternMatchSequence) -> Self { Self::MatchSequence(node) } } impl From for Pattern { fn from(node: crate::PatternMatchMapping) -> Self { Self::MatchMapping(node) } } impl From for Pattern { fn from(node: crate::PatternMatchClass) -> Self { Self::MatchClass(node) } } impl From for Pattern { fn from(node: crate::PatternMatchStar) -> Self { Self::MatchStar(node) } } impl From for Pattern { fn from(node: crate::PatternMatchAs) -> Self { Self::MatchAs(node) } } impl From for Pattern { fn from(node: crate::PatternMatchOr) -> Self { Self::MatchOr(node) } } impl ruff_text_size::Ranged for Pattern { fn range(&self) -> ruff_text_size::TextRange { match self { Self::MatchValue(node) => node.range(), Self::MatchSingleton(node) => node.range(), Self::MatchSequence(node) => node.range(), Self::MatchMapping(node) => node.range(), Self::MatchClass(node) => node.range(), Self::MatchStar(node) => node.range(), Self::MatchAs(node) => node.range(), Self::MatchOr(node) => node.range(), } } } impl crate::HasNodeIndex for Pattern { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::MatchValue(node) => node.node_index(), Self::MatchSingleton(node) => node.node_index(), Self::MatchSequence(node) => node.node_index(), Self::MatchMapping(node) => node.node_index(), Self::MatchClass(node) => node.node_index(), Self::MatchStar(node) => node.node_index(), Self::MatchAs(node) => node.node_index(), Self::MatchOr(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl Pattern { #[inline] pub const fn is_match_value(&self) -> bool { matches!(self, Self::MatchValue(_)) } #[inline] pub fn match_value(self) -> Option { match self { Self::MatchValue(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_value(self) -> crate::PatternMatchValue { match self { Self::MatchValue(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_value_mut(&mut self) -> Option<&mut crate::PatternMatchValue> { match self { Self::MatchValue(val) => Some(val), _ => None, } } #[inline] pub fn as_match_value(&self) -> Option<&crate::PatternMatchValue> { match self { Self::MatchValue(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_singleton(&self) -> bool { matches!(self, Self::MatchSingleton(_)) } #[inline] pub fn match_singleton(self) -> Option { match self { Self::MatchSingleton(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_singleton(self) -> crate::PatternMatchSingleton { match self { Self::MatchSingleton(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_singleton_mut(&mut self) -> Option<&mut crate::PatternMatchSingleton> { match self { Self::MatchSingleton(val) => Some(val), _ => None, } } #[inline] pub fn as_match_singleton(&self) -> Option<&crate::PatternMatchSingleton> { match self { Self::MatchSingleton(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_sequence(&self) -> bool { matches!(self, Self::MatchSequence(_)) } #[inline] pub fn match_sequence(self) -> Option { match self { Self::MatchSequence(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_sequence(self) -> crate::PatternMatchSequence { match self { Self::MatchSequence(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_sequence_mut(&mut self) -> Option<&mut crate::PatternMatchSequence> { match self { Self::MatchSequence(val) => Some(val), _ => None, } } #[inline] pub fn as_match_sequence(&self) -> Option<&crate::PatternMatchSequence> { match self { Self::MatchSequence(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_mapping(&self) -> bool { matches!(self, Self::MatchMapping(_)) } #[inline] pub fn match_mapping(self) -> Option { match self { Self::MatchMapping(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_mapping(self) -> crate::PatternMatchMapping { match self { Self::MatchMapping(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_mapping_mut(&mut self) -> Option<&mut crate::PatternMatchMapping> { match self { Self::MatchMapping(val) => Some(val), _ => None, } } #[inline] pub fn as_match_mapping(&self) -> Option<&crate::PatternMatchMapping> { match self { Self::MatchMapping(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_class(&self) -> bool { matches!(self, Self::MatchClass(_)) } #[inline] pub fn match_class(self) -> Option { match self { Self::MatchClass(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_class(self) -> crate::PatternMatchClass { match self { Self::MatchClass(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_class_mut(&mut self) -> Option<&mut crate::PatternMatchClass> { match self { Self::MatchClass(val) => Some(val), _ => None, } } #[inline] pub fn as_match_class(&self) -> Option<&crate::PatternMatchClass> { match self { Self::MatchClass(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_star(&self) -> bool { matches!(self, Self::MatchStar(_)) } #[inline] pub fn match_star(self) -> Option { match self { Self::MatchStar(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_star(self) -> crate::PatternMatchStar { match self { Self::MatchStar(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_star_mut(&mut self) -> Option<&mut crate::PatternMatchStar> { match self { Self::MatchStar(val) => Some(val), _ => None, } } #[inline] pub fn as_match_star(&self) -> Option<&crate::PatternMatchStar> { match self { Self::MatchStar(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_as(&self) -> bool { matches!(self, Self::MatchAs(_)) } #[inline] pub fn match_as(self) -> Option { match self { Self::MatchAs(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_as(self) -> crate::PatternMatchAs { match self { Self::MatchAs(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_as_mut(&mut self) -> Option<&mut crate::PatternMatchAs> { match self { Self::MatchAs(val) => Some(val), _ => None, } } #[inline] pub fn as_match_as(&self) -> Option<&crate::PatternMatchAs> { match self { Self::MatchAs(val) => Some(val), _ => None, } } #[inline] pub const fn is_match_or(&self) -> bool { matches!(self, Self::MatchOr(_)) } #[inline] pub fn match_or(self) -> Option { match self { Self::MatchOr(val) => Some(val), _ => None, } } #[inline] pub fn expect_match_or(self) -> crate::PatternMatchOr { match self { Self::MatchOr(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_match_or_mut(&mut self) -> Option<&mut crate::PatternMatchOr> { match self { Self::MatchOr(val) => Some(val), _ => None, } } #[inline] pub fn as_match_or(&self) -> Option<&crate::PatternMatchOr> { match self { Self::MatchOr(val) => Some(val), _ => None, } } } /// See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum TypeParam { TypeVar(crate::TypeParamTypeVar), TypeVarTuple(crate::TypeParamTypeVarTuple), ParamSpec(crate::TypeParamParamSpec), } impl From for TypeParam { fn from(node: crate::TypeParamTypeVar) -> Self { Self::TypeVar(node) } } impl From for TypeParam { fn from(node: crate::TypeParamTypeVarTuple) -> Self { Self::TypeVarTuple(node) } } impl From for TypeParam { fn from(node: crate::TypeParamParamSpec) -> Self { Self::ParamSpec(node) } } impl ruff_text_size::Ranged for TypeParam { fn range(&self) -> ruff_text_size::TextRange { match self { Self::TypeVar(node) => node.range(), Self::TypeVarTuple(node) => node.range(), Self::ParamSpec(node) => node.range(), } } } impl crate::HasNodeIndex for TypeParam { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::TypeVar(node) => node.node_index(), Self::TypeVarTuple(node) => node.node_index(), Self::ParamSpec(node) => node.node_index(), } } } #[allow(dead_code, clippy::match_wildcard_for_single_variants)] impl TypeParam { #[inline] pub const fn is_type_var(&self) -> bool { matches!(self, Self::TypeVar(_)) } #[inline] pub fn type_var(self) -> Option { match self { Self::TypeVar(val) => Some(val), _ => None, } } #[inline] pub fn expect_type_var(self) -> crate::TypeParamTypeVar { match self { Self::TypeVar(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_type_var_mut(&mut self) -> Option<&mut crate::TypeParamTypeVar> { match self { Self::TypeVar(val) => Some(val), _ => None, } } #[inline] pub fn as_type_var(&self) -> Option<&crate::TypeParamTypeVar> { match self { Self::TypeVar(val) => Some(val), _ => None, } } #[inline] pub const fn is_type_var_tuple(&self) -> bool { matches!(self, Self::TypeVarTuple(_)) } #[inline] pub fn type_var_tuple(self) -> Option { match self { Self::TypeVarTuple(val) => Some(val), _ => None, } } #[inline] pub fn expect_type_var_tuple(self) -> crate::TypeParamTypeVarTuple { match self { Self::TypeVarTuple(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_type_var_tuple_mut(&mut self) -> Option<&mut crate::TypeParamTypeVarTuple> { match self { Self::TypeVarTuple(val) => Some(val), _ => None, } } #[inline] pub fn as_type_var_tuple(&self) -> Option<&crate::TypeParamTypeVarTuple> { match self { Self::TypeVarTuple(val) => Some(val), _ => None, } } #[inline] pub const fn is_param_spec(&self) -> bool { matches!(self, Self::ParamSpec(_)) } #[inline] pub fn param_spec(self) -> Option { match self { Self::ParamSpec(val) => Some(val), _ => None, } } #[inline] pub fn expect_param_spec(self) -> crate::TypeParamParamSpec { match self { Self::ParamSpec(val) => val, _ => panic!("called expect on {self:?}"), } } #[inline] pub fn as_param_spec_mut(&mut self) -> Option<&mut crate::TypeParamParamSpec> { match self { Self::ParamSpec(val) => Some(val), _ => None, } } #[inline] pub fn as_param_spec(&self) -> Option<&crate::TypeParamParamSpec> { match self { Self::ParamSpec(val) => Some(val), _ => None, } } } impl ruff_text_size::Ranged for crate::ModModule { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ModExpression { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtFunctionDef { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtClassDef { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtReturn { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtDelete { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtTypeAlias { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtAssign { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtAugAssign { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtAnnAssign { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtFor { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtWhile { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtIf { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtWith { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtMatch { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtRaise { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtTry { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtAssert { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtImport { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtImportFrom { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtGlobal { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtNonlocal { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtExpr { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtPass { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtBreak { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtContinue { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StmtIpyEscapeCommand { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprBoolOp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprNamed { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprBinOp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprUnaryOp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprLambda { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprIf { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprDict { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprSet { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprListComp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprSetComp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprDictComp { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprGenerator { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprAwait { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprYield { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprYieldFrom { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprCompare { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprFString { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprTString { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprStringLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprBytesLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprNumberLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprBooleanLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprNoneLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprEllipsisLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprAttribute { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprSubscript { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprStarred { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprName { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprList { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprTuple { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprSlice { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExprIpyEscapeCommand { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ExceptHandlerExceptHandler { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::InterpolatedElement { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::InterpolatedStringLiteralElement { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchValue { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchSingleton { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchSequence { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchMapping { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchClass { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchStar { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchAs { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternMatchOr { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::TypeParamTypeVar { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::TypeParamTypeVarTuple { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::TypeParamParamSpec { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::InterpolatedStringFormatSpec { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternArguments { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::PatternKeyword { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Comprehension { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Arguments { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Parameters { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Parameter { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ParameterWithDefault { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Keyword { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Alias { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::WithItem { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::MatchCase { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Decorator { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::ElifElseClause { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::TypeParams { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::FString { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::TString { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::StringLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::BytesLiteral { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl ruff_text_size::Ranged for crate::Identifier { fn range(&self) -> ruff_text_size::TextRange { self.range } } impl crate::HasNodeIndex for crate::ModModule { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ModExpression { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtFunctionDef { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtClassDef { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtReturn { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtDelete { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtTypeAlias { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtAssign { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtAugAssign { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtAnnAssign { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtFor { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtWhile { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtIf { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtWith { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtMatch { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtRaise { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtTry { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtAssert { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtImport { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtImportFrom { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtGlobal { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtNonlocal { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtExpr { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtPass { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtBreak { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtContinue { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StmtIpyEscapeCommand { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprBoolOp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprNamed { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprBinOp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprUnaryOp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprLambda { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprIf { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprDict { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprSet { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprListComp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprSetComp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprDictComp { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprGenerator { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprAwait { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprYield { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprYieldFrom { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprCompare { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprCall { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprFString { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprTString { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprStringLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprBytesLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprNumberLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprBooleanLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprNoneLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprEllipsisLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprAttribute { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprSubscript { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprStarred { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprName { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprList { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprTuple { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprSlice { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExprIpyEscapeCommand { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ExceptHandlerExceptHandler { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::InterpolatedElement { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::InterpolatedStringLiteralElement { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchValue { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchSingleton { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchSequence { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchMapping { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchClass { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchStar { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchAs { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternMatchOr { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::TypeParamTypeVar { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::TypeParamTypeVarTuple { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::TypeParamParamSpec { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::InterpolatedStringFormatSpec { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternArguments { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::PatternKeyword { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Comprehension { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Arguments { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Parameters { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Parameter { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ParameterWithDefault { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Keyword { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Alias { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::WithItem { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::MatchCase { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Decorator { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::ElifElseClause { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::TypeParams { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::FString { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::TString { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::StringLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::BytesLiteral { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl crate::HasNodeIndex for crate::Identifier { fn node_index(&self) -> &crate::AtomicNodeIndex { &self.node_index } } impl Mod { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { Mod::Module(node) => node.visit_source_order(visitor), Mod::Expression(node) => node.visit_source_order(visitor), } } } impl Stmt { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { Stmt::FunctionDef(node) => node.visit_source_order(visitor), Stmt::ClassDef(node) => node.visit_source_order(visitor), Stmt::Return(node) => node.visit_source_order(visitor), Stmt::Delete(node) => node.visit_source_order(visitor), Stmt::TypeAlias(node) => node.visit_source_order(visitor), Stmt::Assign(node) => node.visit_source_order(visitor), Stmt::AugAssign(node) => node.visit_source_order(visitor), Stmt::AnnAssign(node) => node.visit_source_order(visitor), Stmt::For(node) => node.visit_source_order(visitor), Stmt::While(node) => node.visit_source_order(visitor), Stmt::If(node) => node.visit_source_order(visitor), Stmt::With(node) => node.visit_source_order(visitor), Stmt::Match(node) => node.visit_source_order(visitor), Stmt::Raise(node) => node.visit_source_order(visitor), Stmt::Try(node) => node.visit_source_order(visitor), Stmt::Assert(node) => node.visit_source_order(visitor), Stmt::Import(node) => node.visit_source_order(visitor), Stmt::ImportFrom(node) => node.visit_source_order(visitor), Stmt::Global(node) => node.visit_source_order(visitor), Stmt::Nonlocal(node) => node.visit_source_order(visitor), Stmt::Expr(node) => node.visit_source_order(visitor), Stmt::Pass(node) => node.visit_source_order(visitor), Stmt::Break(node) => node.visit_source_order(visitor), Stmt::Continue(node) => node.visit_source_order(visitor), Stmt::IpyEscapeCommand(node) => node.visit_source_order(visitor), } } } impl Expr { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { Expr::BoolOp(node) => node.visit_source_order(visitor), Expr::Named(node) => node.visit_source_order(visitor), Expr::BinOp(node) => node.visit_source_order(visitor), Expr::UnaryOp(node) => node.visit_source_order(visitor), Expr::Lambda(node) => node.visit_source_order(visitor), Expr::If(node) => node.visit_source_order(visitor), Expr::Dict(node) => node.visit_source_order(visitor), Expr::Set(node) => node.visit_source_order(visitor), Expr::ListComp(node) => node.visit_source_order(visitor), Expr::SetComp(node) => node.visit_source_order(visitor), Expr::DictComp(node) => node.visit_source_order(visitor), Expr::Generator(node) => node.visit_source_order(visitor), Expr::Await(node) => node.visit_source_order(visitor), Expr::Yield(node) => node.visit_source_order(visitor), Expr::YieldFrom(node) => node.visit_source_order(visitor), Expr::Compare(node) => node.visit_source_order(visitor), Expr::Call(node) => node.visit_source_order(visitor), Expr::FString(node) => node.visit_source_order(visitor), Expr::TString(node) => node.visit_source_order(visitor), Expr::StringLiteral(node) => node.visit_source_order(visitor), Expr::BytesLiteral(node) => node.visit_source_order(visitor), Expr::NumberLiteral(node) => node.visit_source_order(visitor), Expr::BooleanLiteral(node) => node.visit_source_order(visitor), Expr::NoneLiteral(node) => node.visit_source_order(visitor), Expr::EllipsisLiteral(node) => node.visit_source_order(visitor), Expr::Attribute(node) => node.visit_source_order(visitor), Expr::Subscript(node) => node.visit_source_order(visitor), Expr::Starred(node) => node.visit_source_order(visitor), Expr::Name(node) => node.visit_source_order(visitor), Expr::List(node) => node.visit_source_order(visitor), Expr::Tuple(node) => node.visit_source_order(visitor), Expr::Slice(node) => node.visit_source_order(visitor), Expr::IpyEscapeCommand(node) => node.visit_source_order(visitor), } } } impl ExceptHandler { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { ExceptHandler::ExceptHandler(node) => node.visit_source_order(visitor), } } } impl InterpolatedStringElement { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { InterpolatedStringElement::Interpolation(node) => node.visit_source_order(visitor), InterpolatedStringElement::Literal(node) => node.visit_source_order(visitor), } } } impl Pattern { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { Pattern::MatchValue(node) => node.visit_source_order(visitor), Pattern::MatchSingleton(node) => node.visit_source_order(visitor), Pattern::MatchSequence(node) => node.visit_source_order(visitor), Pattern::MatchMapping(node) => node.visit_source_order(visitor), Pattern::MatchClass(node) => node.visit_source_order(visitor), Pattern::MatchStar(node) => node.visit_source_order(visitor), Pattern::MatchAs(node) => node.visit_source_order(visitor), Pattern::MatchOr(node) => node.visit_source_order(visitor), } } } impl TypeParam { #[allow(unused)] pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'a> + ?Sized, { match self { TypeParam::TypeVar(node) => node.visit_source_order(visitor), TypeParam::TypeVarTuple(node) => node.visit_source_order(visitor), TypeParam::ParamSpec(node) => node.visit_source_order(visitor), } } } /// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum ModRef<'a> { Module(&'a crate::ModModule), Expression(&'a crate::ModExpression), } impl<'a> From<&'a Mod> for ModRef<'a> { fn from(node: &'a Mod) -> Self { match node { Mod::Module(node) => ModRef::Module(node), Mod::Expression(node) => ModRef::Expression(node), } } } impl<'a> From<&'a crate::ModModule> for ModRef<'a> { fn from(node: &'a crate::ModModule) -> Self { Self::Module(node) } } impl<'a> From<&'a crate::ModExpression> for ModRef<'a> { fn from(node: &'a crate::ModExpression) -> Self { Self::Expression(node) } } impl ruff_text_size::Ranged for ModRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::Module(node) => node.range(), Self::Expression(node) => node.range(), } } } impl crate::HasNodeIndex for ModRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::Module(node) => node.node_index(), Self::Expression(node) => node.node_index(), } } } /// See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum StmtRef<'a> { #[is(name = "function_def_stmt")] FunctionDef(&'a crate::StmtFunctionDef), #[is(name = "class_def_stmt")] ClassDef(&'a crate::StmtClassDef), #[is(name = "return_stmt")] Return(&'a crate::StmtReturn), #[is(name = "delete_stmt")] Delete(&'a crate::StmtDelete), #[is(name = "type_alias_stmt")] TypeAlias(&'a crate::StmtTypeAlias), #[is(name = "assign_stmt")] Assign(&'a crate::StmtAssign), #[is(name = "aug_assign_stmt")] AugAssign(&'a crate::StmtAugAssign), #[is(name = "ann_assign_stmt")] AnnAssign(&'a crate::StmtAnnAssign), #[is(name = "for_stmt")] For(&'a crate::StmtFor), #[is(name = "while_stmt")] While(&'a crate::StmtWhile), #[is(name = "if_stmt")] If(&'a crate::StmtIf), #[is(name = "with_stmt")] With(&'a crate::StmtWith), #[is(name = "match_stmt")] Match(&'a crate::StmtMatch), #[is(name = "raise_stmt")] Raise(&'a crate::StmtRaise), #[is(name = "try_stmt")] Try(&'a crate::StmtTry), #[is(name = "assert_stmt")] Assert(&'a crate::StmtAssert), #[is(name = "import_stmt")] Import(&'a crate::StmtImport), #[is(name = "import_from_stmt")] ImportFrom(&'a crate::StmtImportFrom), #[is(name = "global_stmt")] Global(&'a crate::StmtGlobal), #[is(name = "nonlocal_stmt")] Nonlocal(&'a crate::StmtNonlocal), #[is(name = "expr_stmt")] Expr(&'a crate::StmtExpr), #[is(name = "pass_stmt")] Pass(&'a crate::StmtPass), #[is(name = "break_stmt")] Break(&'a crate::StmtBreak), #[is(name = "continue_stmt")] Continue(&'a crate::StmtContinue), #[is(name = "ipy_escape_command_stmt")] IpyEscapeCommand(&'a crate::StmtIpyEscapeCommand), } impl<'a> From<&'a Stmt> for StmtRef<'a> { fn from(node: &'a Stmt) -> Self { match node { Stmt::FunctionDef(node) => StmtRef::FunctionDef(node), Stmt::ClassDef(node) => StmtRef::ClassDef(node), Stmt::Return(node) => StmtRef::Return(node), Stmt::Delete(node) => StmtRef::Delete(node), Stmt::TypeAlias(node) => StmtRef::TypeAlias(node), Stmt::Assign(node) => StmtRef::Assign(node), Stmt::AugAssign(node) => StmtRef::AugAssign(node), Stmt::AnnAssign(node) => StmtRef::AnnAssign(node), Stmt::For(node) => StmtRef::For(node), Stmt::While(node) => StmtRef::While(node), Stmt::If(node) => StmtRef::If(node), Stmt::With(node) => StmtRef::With(node), Stmt::Match(node) => StmtRef::Match(node), Stmt::Raise(node) => StmtRef::Raise(node), Stmt::Try(node) => StmtRef::Try(node), Stmt::Assert(node) => StmtRef::Assert(node), Stmt::Import(node) => StmtRef::Import(node), Stmt::ImportFrom(node) => StmtRef::ImportFrom(node), Stmt::Global(node) => StmtRef::Global(node), Stmt::Nonlocal(node) => StmtRef::Nonlocal(node), Stmt::Expr(node) => StmtRef::Expr(node), Stmt::Pass(node) => StmtRef::Pass(node), Stmt::Break(node) => StmtRef::Break(node), Stmt::Continue(node) => StmtRef::Continue(node), Stmt::IpyEscapeCommand(node) => StmtRef::IpyEscapeCommand(node), } } } impl<'a> From<&'a crate::StmtFunctionDef> for StmtRef<'a> { fn from(node: &'a crate::StmtFunctionDef) -> Self { Self::FunctionDef(node) } } impl<'a> From<&'a crate::StmtClassDef> for StmtRef<'a> { fn from(node: &'a crate::StmtClassDef) -> Self { Self::ClassDef(node) } } impl<'a> From<&'a crate::StmtReturn> for StmtRef<'a> { fn from(node: &'a crate::StmtReturn) -> Self { Self::Return(node) } } impl<'a> From<&'a crate::StmtDelete> for StmtRef<'a> { fn from(node: &'a crate::StmtDelete) -> Self { Self::Delete(node) } } impl<'a> From<&'a crate::StmtTypeAlias> for StmtRef<'a> { fn from(node: &'a crate::StmtTypeAlias) -> Self { Self::TypeAlias(node) } } impl<'a> From<&'a crate::StmtAssign> for StmtRef<'a> { fn from(node: &'a crate::StmtAssign) -> Self { Self::Assign(node) } } impl<'a> From<&'a crate::StmtAugAssign> for StmtRef<'a> { fn from(node: &'a crate::StmtAugAssign) -> Self { Self::AugAssign(node) } } impl<'a> From<&'a crate::StmtAnnAssign> for StmtRef<'a> { fn from(node: &'a crate::StmtAnnAssign) -> Self { Self::AnnAssign(node) } } impl<'a> From<&'a crate::StmtFor> for StmtRef<'a> { fn from(node: &'a crate::StmtFor) -> Self { Self::For(node) } } impl<'a> From<&'a crate::StmtWhile> for StmtRef<'a> { fn from(node: &'a crate::StmtWhile) -> Self { Self::While(node) } } impl<'a> From<&'a crate::StmtIf> for StmtRef<'a> { fn from(node: &'a crate::StmtIf) -> Self { Self::If(node) } } impl<'a> From<&'a crate::StmtWith> for StmtRef<'a> { fn from(node: &'a crate::StmtWith) -> Self { Self::With(node) } } impl<'a> From<&'a crate::StmtMatch> for StmtRef<'a> { fn from(node: &'a crate::StmtMatch) -> Self { Self::Match(node) } } impl<'a> From<&'a crate::StmtRaise> for StmtRef<'a> { fn from(node: &'a crate::StmtRaise) -> Self { Self::Raise(node) } } impl<'a> From<&'a crate::StmtTry> for StmtRef<'a> { fn from(node: &'a crate::StmtTry) -> Self { Self::Try(node) } } impl<'a> From<&'a crate::StmtAssert> for StmtRef<'a> { fn from(node: &'a crate::StmtAssert) -> Self { Self::Assert(node) } } impl<'a> From<&'a crate::StmtImport> for StmtRef<'a> { fn from(node: &'a crate::StmtImport) -> Self { Self::Import(node) } } impl<'a> From<&'a crate::StmtImportFrom> for StmtRef<'a> { fn from(node: &'a crate::StmtImportFrom) -> Self { Self::ImportFrom(node) } } impl<'a> From<&'a crate::StmtGlobal> for StmtRef<'a> { fn from(node: &'a crate::StmtGlobal) -> Self { Self::Global(node) } } impl<'a> From<&'a crate::StmtNonlocal> for StmtRef<'a> { fn from(node: &'a crate::StmtNonlocal) -> Self { Self::Nonlocal(node) } } impl<'a> From<&'a crate::StmtExpr> for StmtRef<'a> { fn from(node: &'a crate::StmtExpr) -> Self { Self::Expr(node) } } impl<'a> From<&'a crate::StmtPass> for StmtRef<'a> { fn from(node: &'a crate::StmtPass) -> Self { Self::Pass(node) } } impl<'a> From<&'a crate::StmtBreak> for StmtRef<'a> { fn from(node: &'a crate::StmtBreak) -> Self { Self::Break(node) } } impl<'a> From<&'a crate::StmtContinue> for StmtRef<'a> { fn from(node: &'a crate::StmtContinue) -> Self { Self::Continue(node) } } impl<'a> From<&'a crate::StmtIpyEscapeCommand> for StmtRef<'a> { fn from(node: &'a crate::StmtIpyEscapeCommand) -> Self { Self::IpyEscapeCommand(node) } } impl ruff_text_size::Ranged for StmtRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::FunctionDef(node) => node.range(), Self::ClassDef(node) => node.range(), Self::Return(node) => node.range(), Self::Delete(node) => node.range(), Self::TypeAlias(node) => node.range(), Self::Assign(node) => node.range(), Self::AugAssign(node) => node.range(), Self::AnnAssign(node) => node.range(), Self::For(node) => node.range(), Self::While(node) => node.range(), Self::If(node) => node.range(), Self::With(node) => node.range(), Self::Match(node) => node.range(), Self::Raise(node) => node.range(), Self::Try(node) => node.range(), Self::Assert(node) => node.range(), Self::Import(node) => node.range(), Self::ImportFrom(node) => node.range(), Self::Global(node) => node.range(), Self::Nonlocal(node) => node.range(), Self::Expr(node) => node.range(), Self::Pass(node) => node.range(), Self::Break(node) => node.range(), Self::Continue(node) => node.range(), Self::IpyEscapeCommand(node) => node.range(), } } } impl crate::HasNodeIndex for StmtRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::FunctionDef(node) => node.node_index(), Self::ClassDef(node) => node.node_index(), Self::Return(node) => node.node_index(), Self::Delete(node) => node.node_index(), Self::TypeAlias(node) => node.node_index(), Self::Assign(node) => node.node_index(), Self::AugAssign(node) => node.node_index(), Self::AnnAssign(node) => node.node_index(), Self::For(node) => node.node_index(), Self::While(node) => node.node_index(), Self::If(node) => node.node_index(), Self::With(node) => node.node_index(), Self::Match(node) => node.node_index(), Self::Raise(node) => node.node_index(), Self::Try(node) => node.node_index(), Self::Assert(node) => node.node_index(), Self::Import(node) => node.node_index(), Self::ImportFrom(node) => node.node_index(), Self::Global(node) => node.node_index(), Self::Nonlocal(node) => node.node_index(), Self::Expr(node) => node.node_index(), Self::Pass(node) => node.node_index(), Self::Break(node) => node.node_index(), Self::Continue(node) => node.node_index(), Self::IpyEscapeCommand(node) => node.node_index(), } } } /// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum ExprRef<'a> { #[is(name = "bool_op_expr")] BoolOp(&'a crate::ExprBoolOp), #[is(name = "named_expr")] Named(&'a crate::ExprNamed), #[is(name = "bin_op_expr")] BinOp(&'a crate::ExprBinOp), #[is(name = "unary_op_expr")] UnaryOp(&'a crate::ExprUnaryOp), #[is(name = "lambda_expr")] Lambda(&'a crate::ExprLambda), #[is(name = "if_expr")] If(&'a crate::ExprIf), #[is(name = "dict_expr")] Dict(&'a crate::ExprDict), #[is(name = "set_expr")] Set(&'a crate::ExprSet), #[is(name = "list_comp_expr")] ListComp(&'a crate::ExprListComp), #[is(name = "set_comp_expr")] SetComp(&'a crate::ExprSetComp), #[is(name = "dict_comp_expr")] DictComp(&'a crate::ExprDictComp), #[is(name = "generator_expr")] Generator(&'a crate::ExprGenerator), #[is(name = "await_expr")] Await(&'a crate::ExprAwait), #[is(name = "yield_expr")] Yield(&'a crate::ExprYield), #[is(name = "yield_from_expr")] YieldFrom(&'a crate::ExprYieldFrom), #[is(name = "compare_expr")] Compare(&'a crate::ExprCompare), #[is(name = "call_expr")] Call(&'a crate::ExprCall), #[is(name = "f_string_expr")] FString(&'a crate::ExprFString), #[is(name = "t_string_expr")] TString(&'a crate::ExprTString), #[is(name = "string_literal_expr")] StringLiteral(&'a crate::ExprStringLiteral), #[is(name = "bytes_literal_expr")] BytesLiteral(&'a crate::ExprBytesLiteral), #[is(name = "number_literal_expr")] NumberLiteral(&'a crate::ExprNumberLiteral), #[is(name = "boolean_literal_expr")] BooleanLiteral(&'a crate::ExprBooleanLiteral), #[is(name = "none_literal_expr")] NoneLiteral(&'a crate::ExprNoneLiteral), #[is(name = "ellipsis_literal_expr")] EllipsisLiteral(&'a crate::ExprEllipsisLiteral), #[is(name = "attribute_expr")] Attribute(&'a crate::ExprAttribute), #[is(name = "subscript_expr")] Subscript(&'a crate::ExprSubscript), #[is(name = "starred_expr")] Starred(&'a crate::ExprStarred), #[is(name = "name_expr")] Name(&'a crate::ExprName), #[is(name = "list_expr")] List(&'a crate::ExprList), #[is(name = "tuple_expr")] Tuple(&'a crate::ExprTuple), #[is(name = "slice_expr")] Slice(&'a crate::ExprSlice), #[is(name = "ipy_escape_command_expr")] IpyEscapeCommand(&'a crate::ExprIpyEscapeCommand), } impl<'a> From<&'a Expr> for ExprRef<'a> { fn from(node: &'a Expr) -> Self { match node { Expr::BoolOp(node) => ExprRef::BoolOp(node), Expr::Named(node) => ExprRef::Named(node), Expr::BinOp(node) => ExprRef::BinOp(node), Expr::UnaryOp(node) => ExprRef::UnaryOp(node), Expr::Lambda(node) => ExprRef::Lambda(node), Expr::If(node) => ExprRef::If(node), Expr::Dict(node) => ExprRef::Dict(node), Expr::Set(node) => ExprRef::Set(node), Expr::ListComp(node) => ExprRef::ListComp(node), Expr::SetComp(node) => ExprRef::SetComp(node), Expr::DictComp(node) => ExprRef::DictComp(node), Expr::Generator(node) => ExprRef::Generator(node), Expr::Await(node) => ExprRef::Await(node), Expr::Yield(node) => ExprRef::Yield(node), Expr::YieldFrom(node) => ExprRef::YieldFrom(node), Expr::Compare(node) => ExprRef::Compare(node), Expr::Call(node) => ExprRef::Call(node), Expr::FString(node) => ExprRef::FString(node), Expr::TString(node) => ExprRef::TString(node), Expr::StringLiteral(node) => ExprRef::StringLiteral(node), Expr::BytesLiteral(node) => ExprRef::BytesLiteral(node), Expr::NumberLiteral(node) => ExprRef::NumberLiteral(node), Expr::BooleanLiteral(node) => ExprRef::BooleanLiteral(node), Expr::NoneLiteral(node) => ExprRef::NoneLiteral(node), Expr::EllipsisLiteral(node) => ExprRef::EllipsisLiteral(node), Expr::Attribute(node) => ExprRef::Attribute(node), Expr::Subscript(node) => ExprRef::Subscript(node), Expr::Starred(node) => ExprRef::Starred(node), Expr::Name(node) => ExprRef::Name(node), Expr::List(node) => ExprRef::List(node), Expr::Tuple(node) => ExprRef::Tuple(node), Expr::Slice(node) => ExprRef::Slice(node), Expr::IpyEscapeCommand(node) => ExprRef::IpyEscapeCommand(node), } } } impl<'a> From<&'a crate::ExprBoolOp> for ExprRef<'a> { fn from(node: &'a crate::ExprBoolOp) -> Self { Self::BoolOp(node) } } impl<'a> From<&'a crate::ExprNamed> for ExprRef<'a> { fn from(node: &'a crate::ExprNamed) -> Self { Self::Named(node) } } impl<'a> From<&'a crate::ExprBinOp> for ExprRef<'a> { fn from(node: &'a crate::ExprBinOp) -> Self { Self::BinOp(node) } } impl<'a> From<&'a crate::ExprUnaryOp> for ExprRef<'a> { fn from(node: &'a crate::ExprUnaryOp) -> Self { Self::UnaryOp(node) } } impl<'a> From<&'a crate::ExprLambda> for ExprRef<'a> { fn from(node: &'a crate::ExprLambda) -> Self { Self::Lambda(node) } } impl<'a> From<&'a crate::ExprIf> for ExprRef<'a> { fn from(node: &'a crate::ExprIf) -> Self { Self::If(node) } } impl<'a> From<&'a crate::ExprDict> for ExprRef<'a> { fn from(node: &'a crate::ExprDict) -> Self { Self::Dict(node) } } impl<'a> From<&'a crate::ExprSet> for ExprRef<'a> { fn from(node: &'a crate::ExprSet) -> Self { Self::Set(node) } } impl<'a> From<&'a crate::ExprListComp> for ExprRef<'a> { fn from(node: &'a crate::ExprListComp) -> Self { Self::ListComp(node) } } impl<'a> From<&'a crate::ExprSetComp> for ExprRef<'a> { fn from(node: &'a crate::ExprSetComp) -> Self { Self::SetComp(node) } } impl<'a> From<&'a crate::ExprDictComp> for ExprRef<'a> { fn from(node: &'a crate::ExprDictComp) -> Self { Self::DictComp(node) } } impl<'a> From<&'a crate::ExprGenerator> for ExprRef<'a> { fn from(node: &'a crate::ExprGenerator) -> Self { Self::Generator(node) } } impl<'a> From<&'a crate::ExprAwait> for ExprRef<'a> { fn from(node: &'a crate::ExprAwait) -> Self { Self::Await(node) } } impl<'a> From<&'a crate::ExprYield> for ExprRef<'a> { fn from(node: &'a crate::ExprYield) -> Self { Self::Yield(node) } } impl<'a> From<&'a crate::ExprYieldFrom> for ExprRef<'a> { fn from(node: &'a crate::ExprYieldFrom) -> Self { Self::YieldFrom(node) } } impl<'a> From<&'a crate::ExprCompare> for ExprRef<'a> { fn from(node: &'a crate::ExprCompare) -> Self { Self::Compare(node) } } impl<'a> From<&'a crate::ExprCall> for ExprRef<'a> { fn from(node: &'a crate::ExprCall) -> Self { Self::Call(node) } } impl<'a> From<&'a crate::ExprFString> for ExprRef<'a> { fn from(node: &'a crate::ExprFString) -> Self { Self::FString(node) } } impl<'a> From<&'a crate::ExprTString> for ExprRef<'a> { fn from(node: &'a crate::ExprTString) -> Self { Self::TString(node) } } impl<'a> From<&'a crate::ExprStringLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprStringLiteral) -> Self { Self::StringLiteral(node) } } impl<'a> From<&'a crate::ExprBytesLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprBytesLiteral) -> Self { Self::BytesLiteral(node) } } impl<'a> From<&'a crate::ExprNumberLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprNumberLiteral) -> Self { Self::NumberLiteral(node) } } impl<'a> From<&'a crate::ExprBooleanLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprBooleanLiteral) -> Self { Self::BooleanLiteral(node) } } impl<'a> From<&'a crate::ExprNoneLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprNoneLiteral) -> Self { Self::NoneLiteral(node) } } impl<'a> From<&'a crate::ExprEllipsisLiteral> for ExprRef<'a> { fn from(node: &'a crate::ExprEllipsisLiteral) -> Self { Self::EllipsisLiteral(node) } } impl<'a> From<&'a crate::ExprAttribute> for ExprRef<'a> { fn from(node: &'a crate::ExprAttribute) -> Self { Self::Attribute(node) } } impl<'a> From<&'a crate::ExprSubscript> for ExprRef<'a> { fn from(node: &'a crate::ExprSubscript) -> Self { Self::Subscript(node) } } impl<'a> From<&'a crate::ExprStarred> for ExprRef<'a> { fn from(node: &'a crate::ExprStarred) -> Self { Self::Starred(node) } } impl<'a> From<&'a crate::ExprName> for ExprRef<'a> { fn from(node: &'a crate::ExprName) -> Self { Self::Name(node) } } impl<'a> From<&'a crate::ExprList> for ExprRef<'a> { fn from(node: &'a crate::ExprList) -> Self { Self::List(node) } } impl<'a> From<&'a crate::ExprTuple> for ExprRef<'a> { fn from(node: &'a crate::ExprTuple) -> Self { Self::Tuple(node) } } impl<'a> From<&'a crate::ExprSlice> for ExprRef<'a> { fn from(node: &'a crate::ExprSlice) -> Self { Self::Slice(node) } } impl<'a> From<&'a crate::ExprIpyEscapeCommand> for ExprRef<'a> { fn from(node: &'a crate::ExprIpyEscapeCommand) -> Self { Self::IpyEscapeCommand(node) } } impl ruff_text_size::Ranged for ExprRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::BoolOp(node) => node.range(), Self::Named(node) => node.range(), Self::BinOp(node) => node.range(), Self::UnaryOp(node) => node.range(), Self::Lambda(node) => node.range(), Self::If(node) => node.range(), Self::Dict(node) => node.range(), Self::Set(node) => node.range(), Self::ListComp(node) => node.range(), Self::SetComp(node) => node.range(), Self::DictComp(node) => node.range(), Self::Generator(node) => node.range(), Self::Await(node) => node.range(), Self::Yield(node) => node.range(), Self::YieldFrom(node) => node.range(), Self::Compare(node) => node.range(), Self::Call(node) => node.range(), Self::FString(node) => node.range(), Self::TString(node) => node.range(), Self::StringLiteral(node) => node.range(), Self::BytesLiteral(node) => node.range(), Self::NumberLiteral(node) => node.range(), Self::BooleanLiteral(node) => node.range(), Self::NoneLiteral(node) => node.range(), Self::EllipsisLiteral(node) => node.range(), Self::Attribute(node) => node.range(), Self::Subscript(node) => node.range(), Self::Starred(node) => node.range(), Self::Name(node) => node.range(), Self::List(node) => node.range(), Self::Tuple(node) => node.range(), Self::Slice(node) => node.range(), Self::IpyEscapeCommand(node) => node.range(), } } } impl crate::HasNodeIndex for ExprRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::BoolOp(node) => node.node_index(), Self::Named(node) => node.node_index(), Self::BinOp(node) => node.node_index(), Self::UnaryOp(node) => node.node_index(), Self::Lambda(node) => node.node_index(), Self::If(node) => node.node_index(), Self::Dict(node) => node.node_index(), Self::Set(node) => node.node_index(), Self::ListComp(node) => node.node_index(), Self::SetComp(node) => node.node_index(), Self::DictComp(node) => node.node_index(), Self::Generator(node) => node.node_index(), Self::Await(node) => node.node_index(), Self::Yield(node) => node.node_index(), Self::YieldFrom(node) => node.node_index(), Self::Compare(node) => node.node_index(), Self::Call(node) => node.node_index(), Self::FString(node) => node.node_index(), Self::TString(node) => node.node_index(), Self::StringLiteral(node) => node.node_index(), Self::BytesLiteral(node) => node.node_index(), Self::NumberLiteral(node) => node.node_index(), Self::BooleanLiteral(node) => node.node_index(), Self::NoneLiteral(node) => node.node_index(), Self::EllipsisLiteral(node) => node.node_index(), Self::Attribute(node) => node.node_index(), Self::Subscript(node) => node.node_index(), Self::Starred(node) => node.node_index(), Self::Name(node) => node.node_index(), Self::List(node) => node.node_index(), Self::Tuple(node) => node.node_index(), Self::Slice(node) => node.node_index(), Self::IpyEscapeCommand(node) => node.node_index(), } } } /// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum ExceptHandlerRef<'a> { ExceptHandler(&'a crate::ExceptHandlerExceptHandler), } impl<'a> From<&'a ExceptHandler> for ExceptHandlerRef<'a> { fn from(node: &'a ExceptHandler) -> Self { match node { ExceptHandler::ExceptHandler(node) => ExceptHandlerRef::ExceptHandler(node), } } } impl<'a> From<&'a crate::ExceptHandlerExceptHandler> for ExceptHandlerRef<'a> { fn from(node: &'a crate::ExceptHandlerExceptHandler) -> Self { Self::ExceptHandler(node) } } impl ruff_text_size::Ranged for ExceptHandlerRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::ExceptHandler(node) => node.range(), } } } impl crate::HasNodeIndex for ExceptHandlerRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::ExceptHandler(node) => node.node_index(), } } } #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum InterpolatedStringElementRef<'a> { Interpolation(&'a crate::InterpolatedElement), Literal(&'a crate::InterpolatedStringLiteralElement), } impl<'a> From<&'a InterpolatedStringElement> for InterpolatedStringElementRef<'a> { fn from(node: &'a InterpolatedStringElement) -> Self { match node { InterpolatedStringElement::Interpolation(node) => { InterpolatedStringElementRef::Interpolation(node) } InterpolatedStringElement::Literal(node) => InterpolatedStringElementRef::Literal(node), } } } impl<'a> From<&'a crate::InterpolatedElement> for InterpolatedStringElementRef<'a> { fn from(node: &'a crate::InterpolatedElement) -> Self { Self::Interpolation(node) } } impl<'a> From<&'a crate::InterpolatedStringLiteralElement> for InterpolatedStringElementRef<'a> { fn from(node: &'a crate::InterpolatedStringLiteralElement) -> Self { Self::Literal(node) } } impl ruff_text_size::Ranged for InterpolatedStringElementRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::Interpolation(node) => node.range(), Self::Literal(node) => node.range(), } } } impl crate::HasNodeIndex for InterpolatedStringElementRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::Interpolation(node) => node.node_index(), Self::Literal(node) => node.node_index(), } } } /// See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum PatternRef<'a> { MatchValue(&'a crate::PatternMatchValue), MatchSingleton(&'a crate::PatternMatchSingleton), MatchSequence(&'a crate::PatternMatchSequence), MatchMapping(&'a crate::PatternMatchMapping), MatchClass(&'a crate::PatternMatchClass), MatchStar(&'a crate::PatternMatchStar), MatchAs(&'a crate::PatternMatchAs), MatchOr(&'a crate::PatternMatchOr), } impl<'a> From<&'a Pattern> for PatternRef<'a> { fn from(node: &'a Pattern) -> Self { match node { Pattern::MatchValue(node) => PatternRef::MatchValue(node), Pattern::MatchSingleton(node) => PatternRef::MatchSingleton(node), Pattern::MatchSequence(node) => PatternRef::MatchSequence(node), Pattern::MatchMapping(node) => PatternRef::MatchMapping(node), Pattern::MatchClass(node) => PatternRef::MatchClass(node), Pattern::MatchStar(node) => PatternRef::MatchStar(node), Pattern::MatchAs(node) => PatternRef::MatchAs(node), Pattern::MatchOr(node) => PatternRef::MatchOr(node), } } } impl<'a> From<&'a crate::PatternMatchValue> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchValue) -> Self { Self::MatchValue(node) } } impl<'a> From<&'a crate::PatternMatchSingleton> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchSingleton) -> Self { Self::MatchSingleton(node) } } impl<'a> From<&'a crate::PatternMatchSequence> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchSequence) -> Self { Self::MatchSequence(node) } } impl<'a> From<&'a crate::PatternMatchMapping> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchMapping) -> Self { Self::MatchMapping(node) } } impl<'a> From<&'a crate::PatternMatchClass> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchClass) -> Self { Self::MatchClass(node) } } impl<'a> From<&'a crate::PatternMatchStar> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchStar) -> Self { Self::MatchStar(node) } } impl<'a> From<&'a crate::PatternMatchAs> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchAs) -> Self { Self::MatchAs(node) } } impl<'a> From<&'a crate::PatternMatchOr> for PatternRef<'a> { fn from(node: &'a crate::PatternMatchOr) -> Self { Self::MatchOr(node) } } impl ruff_text_size::Ranged for PatternRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::MatchValue(node) => node.range(), Self::MatchSingleton(node) => node.range(), Self::MatchSequence(node) => node.range(), Self::MatchMapping(node) => node.range(), Self::MatchClass(node) => node.range(), Self::MatchStar(node) => node.range(), Self::MatchAs(node) => node.range(), Self::MatchOr(node) => node.range(), } } } impl crate::HasNodeIndex for PatternRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::MatchValue(node) => node.node_index(), Self::MatchSingleton(node) => node.node_index(), Self::MatchSequence(node) => node.node_index(), Self::MatchMapping(node) => node.node_index(), Self::MatchClass(node) => node.node_index(), Self::MatchStar(node) => node.node_index(), Self::MatchAs(node) => node.node_index(), Self::MatchOr(node) => node.node_index(), } } } /// See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param) #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum TypeParamRef<'a> { TypeVar(&'a crate::TypeParamTypeVar), TypeVarTuple(&'a crate::TypeParamTypeVarTuple), ParamSpec(&'a crate::TypeParamParamSpec), } impl<'a> From<&'a TypeParam> for TypeParamRef<'a> { fn from(node: &'a TypeParam) -> Self { match node { TypeParam::TypeVar(node) => TypeParamRef::TypeVar(node), TypeParam::TypeVarTuple(node) => TypeParamRef::TypeVarTuple(node), TypeParam::ParamSpec(node) => TypeParamRef::ParamSpec(node), } } } impl<'a> From<&'a crate::TypeParamTypeVar> for TypeParamRef<'a> { fn from(node: &'a crate::TypeParamTypeVar) -> Self { Self::TypeVar(node) } } impl<'a> From<&'a crate::TypeParamTypeVarTuple> for TypeParamRef<'a> { fn from(node: &'a crate::TypeParamTypeVarTuple) -> Self { Self::TypeVarTuple(node) } } impl<'a> From<&'a crate::TypeParamParamSpec> for TypeParamRef<'a> { fn from(node: &'a crate::TypeParamParamSpec) -> Self { Self::ParamSpec(node) } } impl ruff_text_size::Ranged for TypeParamRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { Self::TypeVar(node) => node.range(), Self::TypeVarTuple(node) => node.range(), Self::ParamSpec(node) => node.range(), } } } impl crate::HasNodeIndex for TypeParamRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { Self::TypeVar(node) => node.node_index(), Self::TypeVarTuple(node) => node.node_index(), Self::ParamSpec(node) => node.node_index(), } } } /// A flattened enumeration of all AST nodes. #[derive(Copy, Clone, Debug, is_macro::Is, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum AnyNodeRef<'a> { ModModule(&'a crate::ModModule), ModExpression(&'a crate::ModExpression), StmtFunctionDef(&'a crate::StmtFunctionDef), StmtClassDef(&'a crate::StmtClassDef), StmtReturn(&'a crate::StmtReturn), StmtDelete(&'a crate::StmtDelete), StmtTypeAlias(&'a crate::StmtTypeAlias), StmtAssign(&'a crate::StmtAssign), StmtAugAssign(&'a crate::StmtAugAssign), StmtAnnAssign(&'a crate::StmtAnnAssign), StmtFor(&'a crate::StmtFor), StmtWhile(&'a crate::StmtWhile), StmtIf(&'a crate::StmtIf), StmtWith(&'a crate::StmtWith), StmtMatch(&'a crate::StmtMatch), StmtRaise(&'a crate::StmtRaise), StmtTry(&'a crate::StmtTry), StmtAssert(&'a crate::StmtAssert), StmtImport(&'a crate::StmtImport), StmtImportFrom(&'a crate::StmtImportFrom), StmtGlobal(&'a crate::StmtGlobal), StmtNonlocal(&'a crate::StmtNonlocal), StmtExpr(&'a crate::StmtExpr), StmtPass(&'a crate::StmtPass), StmtBreak(&'a crate::StmtBreak), StmtContinue(&'a crate::StmtContinue), StmtIpyEscapeCommand(&'a crate::StmtIpyEscapeCommand), ExprBoolOp(&'a crate::ExprBoolOp), ExprNamed(&'a crate::ExprNamed), ExprBinOp(&'a crate::ExprBinOp), ExprUnaryOp(&'a crate::ExprUnaryOp), ExprLambda(&'a crate::ExprLambda), ExprIf(&'a crate::ExprIf), ExprDict(&'a crate::ExprDict), ExprSet(&'a crate::ExprSet), ExprListComp(&'a crate::ExprListComp), ExprSetComp(&'a crate::ExprSetComp), ExprDictComp(&'a crate::ExprDictComp), ExprGenerator(&'a crate::ExprGenerator), ExprAwait(&'a crate::ExprAwait), ExprYield(&'a crate::ExprYield), ExprYieldFrom(&'a crate::ExprYieldFrom), ExprCompare(&'a crate::ExprCompare), ExprCall(&'a crate::ExprCall), ExprFString(&'a crate::ExprFString), ExprTString(&'a crate::ExprTString), ExprStringLiteral(&'a crate::ExprStringLiteral), ExprBytesLiteral(&'a crate::ExprBytesLiteral), ExprNumberLiteral(&'a crate::ExprNumberLiteral), ExprBooleanLiteral(&'a crate::ExprBooleanLiteral), ExprNoneLiteral(&'a crate::ExprNoneLiteral), ExprEllipsisLiteral(&'a crate::ExprEllipsisLiteral), ExprAttribute(&'a crate::ExprAttribute), ExprSubscript(&'a crate::ExprSubscript), ExprStarred(&'a crate::ExprStarred), ExprName(&'a crate::ExprName), ExprList(&'a crate::ExprList), ExprTuple(&'a crate::ExprTuple), ExprSlice(&'a crate::ExprSlice), ExprIpyEscapeCommand(&'a crate::ExprIpyEscapeCommand), ExceptHandlerExceptHandler(&'a crate::ExceptHandlerExceptHandler), InterpolatedElement(&'a crate::InterpolatedElement), InterpolatedStringLiteralElement(&'a crate::InterpolatedStringLiteralElement), PatternMatchValue(&'a crate::PatternMatchValue), PatternMatchSingleton(&'a crate::PatternMatchSingleton), PatternMatchSequence(&'a crate::PatternMatchSequence), PatternMatchMapping(&'a crate::PatternMatchMapping), PatternMatchClass(&'a crate::PatternMatchClass), PatternMatchStar(&'a crate::PatternMatchStar), PatternMatchAs(&'a crate::PatternMatchAs), PatternMatchOr(&'a crate::PatternMatchOr), TypeParamTypeVar(&'a crate::TypeParamTypeVar), TypeParamTypeVarTuple(&'a crate::TypeParamTypeVarTuple), TypeParamParamSpec(&'a crate::TypeParamParamSpec), InterpolatedStringFormatSpec(&'a crate::InterpolatedStringFormatSpec), PatternArguments(&'a crate::PatternArguments), PatternKeyword(&'a crate::PatternKeyword), Comprehension(&'a crate::Comprehension), Arguments(&'a crate::Arguments), Parameters(&'a crate::Parameters), Parameter(&'a crate::Parameter), ParameterWithDefault(&'a crate::ParameterWithDefault), Keyword(&'a crate::Keyword), Alias(&'a crate::Alias), WithItem(&'a crate::WithItem), MatchCase(&'a crate::MatchCase), Decorator(&'a crate::Decorator), ElifElseClause(&'a crate::ElifElseClause), TypeParams(&'a crate::TypeParams), FString(&'a crate::FString), TString(&'a crate::TString), StringLiteral(&'a crate::StringLiteral), BytesLiteral(&'a crate::BytesLiteral), Identifier(&'a crate::Identifier), } impl<'a> From<&'a Mod> for AnyNodeRef<'a> { fn from(node: &'a Mod) -> AnyNodeRef<'a> { match node { Mod::Module(node) => AnyNodeRef::ModModule(node), Mod::Expression(node) => AnyNodeRef::ModExpression(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: ModRef<'a>) -> AnyNodeRef<'a> { match node { ModRef::Module(node) => AnyNodeRef::ModModule(node), ModRef::Expression(node) => AnyNodeRef::ModExpression(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_mod_ref(self) -> Option> { match self { Self::ModModule(node) => Some(ModRef::Module(node)), Self::ModExpression(node) => Some(ModRef::Expression(node)), _ => None, } } } impl<'a> From<&'a Stmt> for AnyNodeRef<'a> { fn from(node: &'a Stmt) -> AnyNodeRef<'a> { match node { Stmt::FunctionDef(node) => AnyNodeRef::StmtFunctionDef(node), Stmt::ClassDef(node) => AnyNodeRef::StmtClassDef(node), Stmt::Return(node) => AnyNodeRef::StmtReturn(node), Stmt::Delete(node) => AnyNodeRef::StmtDelete(node), Stmt::TypeAlias(node) => AnyNodeRef::StmtTypeAlias(node), Stmt::Assign(node) => AnyNodeRef::StmtAssign(node), Stmt::AugAssign(node) => AnyNodeRef::StmtAugAssign(node), Stmt::AnnAssign(node) => AnyNodeRef::StmtAnnAssign(node), Stmt::For(node) => AnyNodeRef::StmtFor(node), Stmt::While(node) => AnyNodeRef::StmtWhile(node), Stmt::If(node) => AnyNodeRef::StmtIf(node), Stmt::With(node) => AnyNodeRef::StmtWith(node), Stmt::Match(node) => AnyNodeRef::StmtMatch(node), Stmt::Raise(node) => AnyNodeRef::StmtRaise(node), Stmt::Try(node) => AnyNodeRef::StmtTry(node), Stmt::Assert(node) => AnyNodeRef::StmtAssert(node), Stmt::Import(node) => AnyNodeRef::StmtImport(node), Stmt::ImportFrom(node) => AnyNodeRef::StmtImportFrom(node), Stmt::Global(node) => AnyNodeRef::StmtGlobal(node), Stmt::Nonlocal(node) => AnyNodeRef::StmtNonlocal(node), Stmt::Expr(node) => AnyNodeRef::StmtExpr(node), Stmt::Pass(node) => AnyNodeRef::StmtPass(node), Stmt::Break(node) => AnyNodeRef::StmtBreak(node), Stmt::Continue(node) => AnyNodeRef::StmtContinue(node), Stmt::IpyEscapeCommand(node) => AnyNodeRef::StmtIpyEscapeCommand(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: StmtRef<'a>) -> AnyNodeRef<'a> { match node { StmtRef::FunctionDef(node) => AnyNodeRef::StmtFunctionDef(node), StmtRef::ClassDef(node) => AnyNodeRef::StmtClassDef(node), StmtRef::Return(node) => AnyNodeRef::StmtReturn(node), StmtRef::Delete(node) => AnyNodeRef::StmtDelete(node), StmtRef::TypeAlias(node) => AnyNodeRef::StmtTypeAlias(node), StmtRef::Assign(node) => AnyNodeRef::StmtAssign(node), StmtRef::AugAssign(node) => AnyNodeRef::StmtAugAssign(node), StmtRef::AnnAssign(node) => AnyNodeRef::StmtAnnAssign(node), StmtRef::For(node) => AnyNodeRef::StmtFor(node), StmtRef::While(node) => AnyNodeRef::StmtWhile(node), StmtRef::If(node) => AnyNodeRef::StmtIf(node), StmtRef::With(node) => AnyNodeRef::StmtWith(node), StmtRef::Match(node) => AnyNodeRef::StmtMatch(node), StmtRef::Raise(node) => AnyNodeRef::StmtRaise(node), StmtRef::Try(node) => AnyNodeRef::StmtTry(node), StmtRef::Assert(node) => AnyNodeRef::StmtAssert(node), StmtRef::Import(node) => AnyNodeRef::StmtImport(node), StmtRef::ImportFrom(node) => AnyNodeRef::StmtImportFrom(node), StmtRef::Global(node) => AnyNodeRef::StmtGlobal(node), StmtRef::Nonlocal(node) => AnyNodeRef::StmtNonlocal(node), StmtRef::Expr(node) => AnyNodeRef::StmtExpr(node), StmtRef::Pass(node) => AnyNodeRef::StmtPass(node), StmtRef::Break(node) => AnyNodeRef::StmtBreak(node), StmtRef::Continue(node) => AnyNodeRef::StmtContinue(node), StmtRef::IpyEscapeCommand(node) => AnyNodeRef::StmtIpyEscapeCommand(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_stmt_ref(self) -> Option> { match self { Self::StmtFunctionDef(node) => Some(StmtRef::FunctionDef(node)), Self::StmtClassDef(node) => Some(StmtRef::ClassDef(node)), Self::StmtReturn(node) => Some(StmtRef::Return(node)), Self::StmtDelete(node) => Some(StmtRef::Delete(node)), Self::StmtTypeAlias(node) => Some(StmtRef::TypeAlias(node)), Self::StmtAssign(node) => Some(StmtRef::Assign(node)), Self::StmtAugAssign(node) => Some(StmtRef::AugAssign(node)), Self::StmtAnnAssign(node) => Some(StmtRef::AnnAssign(node)), Self::StmtFor(node) => Some(StmtRef::For(node)), Self::StmtWhile(node) => Some(StmtRef::While(node)), Self::StmtIf(node) => Some(StmtRef::If(node)), Self::StmtWith(node) => Some(StmtRef::With(node)), Self::StmtMatch(node) => Some(StmtRef::Match(node)), Self::StmtRaise(node) => Some(StmtRef::Raise(node)), Self::StmtTry(node) => Some(StmtRef::Try(node)), Self::StmtAssert(node) => Some(StmtRef::Assert(node)), Self::StmtImport(node) => Some(StmtRef::Import(node)), Self::StmtImportFrom(node) => Some(StmtRef::ImportFrom(node)), Self::StmtGlobal(node) => Some(StmtRef::Global(node)), Self::StmtNonlocal(node) => Some(StmtRef::Nonlocal(node)), Self::StmtExpr(node) => Some(StmtRef::Expr(node)), Self::StmtPass(node) => Some(StmtRef::Pass(node)), Self::StmtBreak(node) => Some(StmtRef::Break(node)), Self::StmtContinue(node) => Some(StmtRef::Continue(node)), Self::StmtIpyEscapeCommand(node) => Some(StmtRef::IpyEscapeCommand(node)), _ => None, } } } impl<'a> From<&'a Expr> for AnyNodeRef<'a> { fn from(node: &'a Expr) -> AnyNodeRef<'a> { match node { Expr::BoolOp(node) => AnyNodeRef::ExprBoolOp(node), Expr::Named(node) => AnyNodeRef::ExprNamed(node), Expr::BinOp(node) => AnyNodeRef::ExprBinOp(node), Expr::UnaryOp(node) => AnyNodeRef::ExprUnaryOp(node), Expr::Lambda(node) => AnyNodeRef::ExprLambda(node), Expr::If(node) => AnyNodeRef::ExprIf(node), Expr::Dict(node) => AnyNodeRef::ExprDict(node), Expr::Set(node) => AnyNodeRef::ExprSet(node), Expr::ListComp(node) => AnyNodeRef::ExprListComp(node), Expr::SetComp(node) => AnyNodeRef::ExprSetComp(node), Expr::DictComp(node) => AnyNodeRef::ExprDictComp(node), Expr::Generator(node) => AnyNodeRef::ExprGenerator(node), Expr::Await(node) => AnyNodeRef::ExprAwait(node), Expr::Yield(node) => AnyNodeRef::ExprYield(node), Expr::YieldFrom(node) => AnyNodeRef::ExprYieldFrom(node), Expr::Compare(node) => AnyNodeRef::ExprCompare(node), Expr::Call(node) => AnyNodeRef::ExprCall(node), Expr::FString(node) => AnyNodeRef::ExprFString(node), Expr::TString(node) => AnyNodeRef::ExprTString(node), Expr::StringLiteral(node) => AnyNodeRef::ExprStringLiteral(node), Expr::BytesLiteral(node) => AnyNodeRef::ExprBytesLiteral(node), Expr::NumberLiteral(node) => AnyNodeRef::ExprNumberLiteral(node), Expr::BooleanLiteral(node) => AnyNodeRef::ExprBooleanLiteral(node), Expr::NoneLiteral(node) => AnyNodeRef::ExprNoneLiteral(node), Expr::EllipsisLiteral(node) => AnyNodeRef::ExprEllipsisLiteral(node), Expr::Attribute(node) => AnyNodeRef::ExprAttribute(node), Expr::Subscript(node) => AnyNodeRef::ExprSubscript(node), Expr::Starred(node) => AnyNodeRef::ExprStarred(node), Expr::Name(node) => AnyNodeRef::ExprName(node), Expr::List(node) => AnyNodeRef::ExprList(node), Expr::Tuple(node) => AnyNodeRef::ExprTuple(node), Expr::Slice(node) => AnyNodeRef::ExprSlice(node), Expr::IpyEscapeCommand(node) => AnyNodeRef::ExprIpyEscapeCommand(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: ExprRef<'a>) -> AnyNodeRef<'a> { match node { ExprRef::BoolOp(node) => AnyNodeRef::ExprBoolOp(node), ExprRef::Named(node) => AnyNodeRef::ExprNamed(node), ExprRef::BinOp(node) => AnyNodeRef::ExprBinOp(node), ExprRef::UnaryOp(node) => AnyNodeRef::ExprUnaryOp(node), ExprRef::Lambda(node) => AnyNodeRef::ExprLambda(node), ExprRef::If(node) => AnyNodeRef::ExprIf(node), ExprRef::Dict(node) => AnyNodeRef::ExprDict(node), ExprRef::Set(node) => AnyNodeRef::ExprSet(node), ExprRef::ListComp(node) => AnyNodeRef::ExprListComp(node), ExprRef::SetComp(node) => AnyNodeRef::ExprSetComp(node), ExprRef::DictComp(node) => AnyNodeRef::ExprDictComp(node), ExprRef::Generator(node) => AnyNodeRef::ExprGenerator(node), ExprRef::Await(node) => AnyNodeRef::ExprAwait(node), ExprRef::Yield(node) => AnyNodeRef::ExprYield(node), ExprRef::YieldFrom(node) => AnyNodeRef::ExprYieldFrom(node), ExprRef::Compare(node) => AnyNodeRef::ExprCompare(node), ExprRef::Call(node) => AnyNodeRef::ExprCall(node), ExprRef::FString(node) => AnyNodeRef::ExprFString(node), ExprRef::TString(node) => AnyNodeRef::ExprTString(node), ExprRef::StringLiteral(node) => AnyNodeRef::ExprStringLiteral(node), ExprRef::BytesLiteral(node) => AnyNodeRef::ExprBytesLiteral(node), ExprRef::NumberLiteral(node) => AnyNodeRef::ExprNumberLiteral(node), ExprRef::BooleanLiteral(node) => AnyNodeRef::ExprBooleanLiteral(node), ExprRef::NoneLiteral(node) => AnyNodeRef::ExprNoneLiteral(node), ExprRef::EllipsisLiteral(node) => AnyNodeRef::ExprEllipsisLiteral(node), ExprRef::Attribute(node) => AnyNodeRef::ExprAttribute(node), ExprRef::Subscript(node) => AnyNodeRef::ExprSubscript(node), ExprRef::Starred(node) => AnyNodeRef::ExprStarred(node), ExprRef::Name(node) => AnyNodeRef::ExprName(node), ExprRef::List(node) => AnyNodeRef::ExprList(node), ExprRef::Tuple(node) => AnyNodeRef::ExprTuple(node), ExprRef::Slice(node) => AnyNodeRef::ExprSlice(node), ExprRef::IpyEscapeCommand(node) => AnyNodeRef::ExprIpyEscapeCommand(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_expr_ref(self) -> Option> { match self { Self::ExprBoolOp(node) => Some(ExprRef::BoolOp(node)), Self::ExprNamed(node) => Some(ExprRef::Named(node)), Self::ExprBinOp(node) => Some(ExprRef::BinOp(node)), Self::ExprUnaryOp(node) => Some(ExprRef::UnaryOp(node)), Self::ExprLambda(node) => Some(ExprRef::Lambda(node)), Self::ExprIf(node) => Some(ExprRef::If(node)), Self::ExprDict(node) => Some(ExprRef::Dict(node)), Self::ExprSet(node) => Some(ExprRef::Set(node)), Self::ExprListComp(node) => Some(ExprRef::ListComp(node)), Self::ExprSetComp(node) => Some(ExprRef::SetComp(node)), Self::ExprDictComp(node) => Some(ExprRef::DictComp(node)), Self::ExprGenerator(node) => Some(ExprRef::Generator(node)), Self::ExprAwait(node) => Some(ExprRef::Await(node)), Self::ExprYield(node) => Some(ExprRef::Yield(node)), Self::ExprYieldFrom(node) => Some(ExprRef::YieldFrom(node)), Self::ExprCompare(node) => Some(ExprRef::Compare(node)), Self::ExprCall(node) => Some(ExprRef::Call(node)), Self::ExprFString(node) => Some(ExprRef::FString(node)), Self::ExprTString(node) => Some(ExprRef::TString(node)), Self::ExprStringLiteral(node) => Some(ExprRef::StringLiteral(node)), Self::ExprBytesLiteral(node) => Some(ExprRef::BytesLiteral(node)), Self::ExprNumberLiteral(node) => Some(ExprRef::NumberLiteral(node)), Self::ExprBooleanLiteral(node) => Some(ExprRef::BooleanLiteral(node)), Self::ExprNoneLiteral(node) => Some(ExprRef::NoneLiteral(node)), Self::ExprEllipsisLiteral(node) => Some(ExprRef::EllipsisLiteral(node)), Self::ExprAttribute(node) => Some(ExprRef::Attribute(node)), Self::ExprSubscript(node) => Some(ExprRef::Subscript(node)), Self::ExprStarred(node) => Some(ExprRef::Starred(node)), Self::ExprName(node) => Some(ExprRef::Name(node)), Self::ExprList(node) => Some(ExprRef::List(node)), Self::ExprTuple(node) => Some(ExprRef::Tuple(node)), Self::ExprSlice(node) => Some(ExprRef::Slice(node)), Self::ExprIpyEscapeCommand(node) => Some(ExprRef::IpyEscapeCommand(node)), _ => None, } } } impl<'a> From<&'a ExceptHandler> for AnyNodeRef<'a> { fn from(node: &'a ExceptHandler) -> AnyNodeRef<'a> { match node { ExceptHandler::ExceptHandler(node) => AnyNodeRef::ExceptHandlerExceptHandler(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: ExceptHandlerRef<'a>) -> AnyNodeRef<'a> { match node { ExceptHandlerRef::ExceptHandler(node) => AnyNodeRef::ExceptHandlerExceptHandler(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_except_handler_ref(self) -> Option> { match self { Self::ExceptHandlerExceptHandler(node) => Some(ExceptHandlerRef::ExceptHandler(node)), _ => None, } } } impl<'a> From<&'a InterpolatedStringElement> for AnyNodeRef<'a> { fn from(node: &'a InterpolatedStringElement) -> AnyNodeRef<'a> { match node { InterpolatedStringElement::Interpolation(node) => AnyNodeRef::InterpolatedElement(node), InterpolatedStringElement::Literal(node) => { AnyNodeRef::InterpolatedStringLiteralElement(node) } } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: InterpolatedStringElementRef<'a>) -> AnyNodeRef<'a> { match node { InterpolatedStringElementRef::Interpolation(node) => { AnyNodeRef::InterpolatedElement(node) } InterpolatedStringElementRef::Literal(node) => { AnyNodeRef::InterpolatedStringLiteralElement(node) } } } } impl<'a> AnyNodeRef<'a> { pub fn as_interpolated_string_element_ref(self) -> Option> { match self { Self::InterpolatedElement(node) => { Some(InterpolatedStringElementRef::Interpolation(node)) } Self::InterpolatedStringLiteralElement(node) => { Some(InterpolatedStringElementRef::Literal(node)) } _ => None, } } } impl<'a> From<&'a Pattern> for AnyNodeRef<'a> { fn from(node: &'a Pattern) -> AnyNodeRef<'a> { match node { Pattern::MatchValue(node) => AnyNodeRef::PatternMatchValue(node), Pattern::MatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node), Pattern::MatchSequence(node) => AnyNodeRef::PatternMatchSequence(node), Pattern::MatchMapping(node) => AnyNodeRef::PatternMatchMapping(node), Pattern::MatchClass(node) => AnyNodeRef::PatternMatchClass(node), Pattern::MatchStar(node) => AnyNodeRef::PatternMatchStar(node), Pattern::MatchAs(node) => AnyNodeRef::PatternMatchAs(node), Pattern::MatchOr(node) => AnyNodeRef::PatternMatchOr(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: PatternRef<'a>) -> AnyNodeRef<'a> { match node { PatternRef::MatchValue(node) => AnyNodeRef::PatternMatchValue(node), PatternRef::MatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node), PatternRef::MatchSequence(node) => AnyNodeRef::PatternMatchSequence(node), PatternRef::MatchMapping(node) => AnyNodeRef::PatternMatchMapping(node), PatternRef::MatchClass(node) => AnyNodeRef::PatternMatchClass(node), PatternRef::MatchStar(node) => AnyNodeRef::PatternMatchStar(node), PatternRef::MatchAs(node) => AnyNodeRef::PatternMatchAs(node), PatternRef::MatchOr(node) => AnyNodeRef::PatternMatchOr(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_pattern_ref(self) -> Option> { match self { Self::PatternMatchValue(node) => Some(PatternRef::MatchValue(node)), Self::PatternMatchSingleton(node) => Some(PatternRef::MatchSingleton(node)), Self::PatternMatchSequence(node) => Some(PatternRef::MatchSequence(node)), Self::PatternMatchMapping(node) => Some(PatternRef::MatchMapping(node)), Self::PatternMatchClass(node) => Some(PatternRef::MatchClass(node)), Self::PatternMatchStar(node) => Some(PatternRef::MatchStar(node)), Self::PatternMatchAs(node) => Some(PatternRef::MatchAs(node)), Self::PatternMatchOr(node) => Some(PatternRef::MatchOr(node)), _ => None, } } } impl<'a> From<&'a TypeParam> for AnyNodeRef<'a> { fn from(node: &'a TypeParam) -> AnyNodeRef<'a> { match node { TypeParam::TypeVar(node) => AnyNodeRef::TypeParamTypeVar(node), TypeParam::TypeVarTuple(node) => AnyNodeRef::TypeParamTypeVarTuple(node), TypeParam::ParamSpec(node) => AnyNodeRef::TypeParamParamSpec(node), } } } impl<'a> From> for AnyNodeRef<'a> { fn from(node: TypeParamRef<'a>) -> AnyNodeRef<'a> { match node { TypeParamRef::TypeVar(node) => AnyNodeRef::TypeParamTypeVar(node), TypeParamRef::TypeVarTuple(node) => AnyNodeRef::TypeParamTypeVarTuple(node), TypeParamRef::ParamSpec(node) => AnyNodeRef::TypeParamParamSpec(node), } } } impl<'a> AnyNodeRef<'a> { pub fn as_type_param_ref(self) -> Option> { match self { Self::TypeParamTypeVar(node) => Some(TypeParamRef::TypeVar(node)), Self::TypeParamTypeVarTuple(node) => Some(TypeParamRef::TypeVarTuple(node)), Self::TypeParamParamSpec(node) => Some(TypeParamRef::ParamSpec(node)), _ => None, } } } impl<'a> From<&'a crate::ModModule> for AnyNodeRef<'a> { fn from(node: &'a crate::ModModule) -> AnyNodeRef<'a> { AnyNodeRef::ModModule(node) } } impl<'a> From<&'a crate::ModExpression> for AnyNodeRef<'a> { fn from(node: &'a crate::ModExpression) -> AnyNodeRef<'a> { AnyNodeRef::ModExpression(node) } } impl<'a> From<&'a crate::StmtFunctionDef> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtFunctionDef) -> AnyNodeRef<'a> { AnyNodeRef::StmtFunctionDef(node) } } impl<'a> From<&'a crate::StmtClassDef> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtClassDef) -> AnyNodeRef<'a> { AnyNodeRef::StmtClassDef(node) } } impl<'a> From<&'a crate::StmtReturn> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtReturn) -> AnyNodeRef<'a> { AnyNodeRef::StmtReturn(node) } } impl<'a> From<&'a crate::StmtDelete> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtDelete) -> AnyNodeRef<'a> { AnyNodeRef::StmtDelete(node) } } impl<'a> From<&'a crate::StmtTypeAlias> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtTypeAlias) -> AnyNodeRef<'a> { AnyNodeRef::StmtTypeAlias(node) } } impl<'a> From<&'a crate::StmtAssign> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtAssign) -> AnyNodeRef<'a> { AnyNodeRef::StmtAssign(node) } } impl<'a> From<&'a crate::StmtAugAssign> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtAugAssign) -> AnyNodeRef<'a> { AnyNodeRef::StmtAugAssign(node) } } impl<'a> From<&'a crate::StmtAnnAssign> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtAnnAssign) -> AnyNodeRef<'a> { AnyNodeRef::StmtAnnAssign(node) } } impl<'a> From<&'a crate::StmtFor> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtFor) -> AnyNodeRef<'a> { AnyNodeRef::StmtFor(node) } } impl<'a> From<&'a crate::StmtWhile> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtWhile) -> AnyNodeRef<'a> { AnyNodeRef::StmtWhile(node) } } impl<'a> From<&'a crate::StmtIf> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtIf) -> AnyNodeRef<'a> { AnyNodeRef::StmtIf(node) } } impl<'a> From<&'a crate::StmtWith> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtWith) -> AnyNodeRef<'a> { AnyNodeRef::StmtWith(node) } } impl<'a> From<&'a crate::StmtMatch> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtMatch) -> AnyNodeRef<'a> { AnyNodeRef::StmtMatch(node) } } impl<'a> From<&'a crate::StmtRaise> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtRaise) -> AnyNodeRef<'a> { AnyNodeRef::StmtRaise(node) } } impl<'a> From<&'a crate::StmtTry> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtTry) -> AnyNodeRef<'a> { AnyNodeRef::StmtTry(node) } } impl<'a> From<&'a crate::StmtAssert> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtAssert) -> AnyNodeRef<'a> { AnyNodeRef::StmtAssert(node) } } impl<'a> From<&'a crate::StmtImport> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtImport) -> AnyNodeRef<'a> { AnyNodeRef::StmtImport(node) } } impl<'a> From<&'a crate::StmtImportFrom> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtImportFrom) -> AnyNodeRef<'a> { AnyNodeRef::StmtImportFrom(node) } } impl<'a> From<&'a crate::StmtGlobal> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtGlobal) -> AnyNodeRef<'a> { AnyNodeRef::StmtGlobal(node) } } impl<'a> From<&'a crate::StmtNonlocal> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtNonlocal) -> AnyNodeRef<'a> { AnyNodeRef::StmtNonlocal(node) } } impl<'a> From<&'a crate::StmtExpr> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtExpr) -> AnyNodeRef<'a> { AnyNodeRef::StmtExpr(node) } } impl<'a> From<&'a crate::StmtPass> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtPass) -> AnyNodeRef<'a> { AnyNodeRef::StmtPass(node) } } impl<'a> From<&'a crate::StmtBreak> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtBreak) -> AnyNodeRef<'a> { AnyNodeRef::StmtBreak(node) } } impl<'a> From<&'a crate::StmtContinue> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtContinue) -> AnyNodeRef<'a> { AnyNodeRef::StmtContinue(node) } } impl<'a> From<&'a crate::StmtIpyEscapeCommand> for AnyNodeRef<'a> { fn from(node: &'a crate::StmtIpyEscapeCommand) -> AnyNodeRef<'a> { AnyNodeRef::StmtIpyEscapeCommand(node) } } impl<'a> From<&'a crate::ExprBoolOp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprBoolOp) -> AnyNodeRef<'a> { AnyNodeRef::ExprBoolOp(node) } } impl<'a> From<&'a crate::ExprNamed> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprNamed) -> AnyNodeRef<'a> { AnyNodeRef::ExprNamed(node) } } impl<'a> From<&'a crate::ExprBinOp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprBinOp) -> AnyNodeRef<'a> { AnyNodeRef::ExprBinOp(node) } } impl<'a> From<&'a crate::ExprUnaryOp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprUnaryOp) -> AnyNodeRef<'a> { AnyNodeRef::ExprUnaryOp(node) } } impl<'a> From<&'a crate::ExprLambda> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprLambda) -> AnyNodeRef<'a> { AnyNodeRef::ExprLambda(node) } } impl<'a> From<&'a crate::ExprIf> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprIf) -> AnyNodeRef<'a> { AnyNodeRef::ExprIf(node) } } impl<'a> From<&'a crate::ExprDict> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprDict) -> AnyNodeRef<'a> { AnyNodeRef::ExprDict(node) } } impl<'a> From<&'a crate::ExprSet> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprSet) -> AnyNodeRef<'a> { AnyNodeRef::ExprSet(node) } } impl<'a> From<&'a crate::ExprListComp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprListComp) -> AnyNodeRef<'a> { AnyNodeRef::ExprListComp(node) } } impl<'a> From<&'a crate::ExprSetComp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprSetComp) -> AnyNodeRef<'a> { AnyNodeRef::ExprSetComp(node) } } impl<'a> From<&'a crate::ExprDictComp> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprDictComp) -> AnyNodeRef<'a> { AnyNodeRef::ExprDictComp(node) } } impl<'a> From<&'a crate::ExprGenerator> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprGenerator) -> AnyNodeRef<'a> { AnyNodeRef::ExprGenerator(node) } } impl<'a> From<&'a crate::ExprAwait> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprAwait) -> AnyNodeRef<'a> { AnyNodeRef::ExprAwait(node) } } impl<'a> From<&'a crate::ExprYield> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprYield) -> AnyNodeRef<'a> { AnyNodeRef::ExprYield(node) } } impl<'a> From<&'a crate::ExprYieldFrom> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprYieldFrom) -> AnyNodeRef<'a> { AnyNodeRef::ExprYieldFrom(node) } } impl<'a> From<&'a crate::ExprCompare> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprCompare) -> AnyNodeRef<'a> { AnyNodeRef::ExprCompare(node) } } impl<'a> From<&'a crate::ExprCall> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprCall) -> AnyNodeRef<'a> { AnyNodeRef::ExprCall(node) } } impl<'a> From<&'a crate::ExprFString> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprFString) -> AnyNodeRef<'a> { AnyNodeRef::ExprFString(node) } } impl<'a> From<&'a crate::ExprTString> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprTString) -> AnyNodeRef<'a> { AnyNodeRef::ExprTString(node) } } impl<'a> From<&'a crate::ExprStringLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprStringLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprStringLiteral(node) } } impl<'a> From<&'a crate::ExprBytesLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprBytesLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprBytesLiteral(node) } } impl<'a> From<&'a crate::ExprNumberLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprNumberLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprNumberLiteral(node) } } impl<'a> From<&'a crate::ExprBooleanLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprBooleanLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprBooleanLiteral(node) } } impl<'a> From<&'a crate::ExprNoneLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprNoneLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprNoneLiteral(node) } } impl<'a> From<&'a crate::ExprEllipsisLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprEllipsisLiteral) -> AnyNodeRef<'a> { AnyNodeRef::ExprEllipsisLiteral(node) } } impl<'a> From<&'a crate::ExprAttribute> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprAttribute) -> AnyNodeRef<'a> { AnyNodeRef::ExprAttribute(node) } } impl<'a> From<&'a crate::ExprSubscript> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprSubscript) -> AnyNodeRef<'a> { AnyNodeRef::ExprSubscript(node) } } impl<'a> From<&'a crate::ExprStarred> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprStarred) -> AnyNodeRef<'a> { AnyNodeRef::ExprStarred(node) } } impl<'a> From<&'a crate::ExprName> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprName) -> AnyNodeRef<'a> { AnyNodeRef::ExprName(node) } } impl<'a> From<&'a crate::ExprList> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprList) -> AnyNodeRef<'a> { AnyNodeRef::ExprList(node) } } impl<'a> From<&'a crate::ExprTuple> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprTuple) -> AnyNodeRef<'a> { AnyNodeRef::ExprTuple(node) } } impl<'a> From<&'a crate::ExprSlice> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprSlice) -> AnyNodeRef<'a> { AnyNodeRef::ExprSlice(node) } } impl<'a> From<&'a crate::ExprIpyEscapeCommand> for AnyNodeRef<'a> { fn from(node: &'a crate::ExprIpyEscapeCommand) -> AnyNodeRef<'a> { AnyNodeRef::ExprIpyEscapeCommand(node) } } impl<'a> From<&'a crate::ExceptHandlerExceptHandler> for AnyNodeRef<'a> { fn from(node: &'a crate::ExceptHandlerExceptHandler) -> AnyNodeRef<'a> { AnyNodeRef::ExceptHandlerExceptHandler(node) } } impl<'a> From<&'a crate::InterpolatedElement> for AnyNodeRef<'a> { fn from(node: &'a crate::InterpolatedElement) -> AnyNodeRef<'a> { AnyNodeRef::InterpolatedElement(node) } } impl<'a> From<&'a crate::InterpolatedStringLiteralElement> for AnyNodeRef<'a> { fn from(node: &'a crate::InterpolatedStringLiteralElement) -> AnyNodeRef<'a> { AnyNodeRef::InterpolatedStringLiteralElement(node) } } impl<'a> From<&'a crate::PatternMatchValue> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchValue) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchValue(node) } } impl<'a> From<&'a crate::PatternMatchSingleton> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchSingleton) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchSingleton(node) } } impl<'a> From<&'a crate::PatternMatchSequence> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchSequence) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchSequence(node) } } impl<'a> From<&'a crate::PatternMatchMapping> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchMapping) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchMapping(node) } } impl<'a> From<&'a crate::PatternMatchClass> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchClass) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchClass(node) } } impl<'a> From<&'a crate::PatternMatchStar> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchStar) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchStar(node) } } impl<'a> From<&'a crate::PatternMatchAs> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchAs) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchAs(node) } } impl<'a> From<&'a crate::PatternMatchOr> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternMatchOr) -> AnyNodeRef<'a> { AnyNodeRef::PatternMatchOr(node) } } impl<'a> From<&'a crate::TypeParamTypeVar> for AnyNodeRef<'a> { fn from(node: &'a crate::TypeParamTypeVar) -> AnyNodeRef<'a> { AnyNodeRef::TypeParamTypeVar(node) } } impl<'a> From<&'a crate::TypeParamTypeVarTuple> for AnyNodeRef<'a> { fn from(node: &'a crate::TypeParamTypeVarTuple) -> AnyNodeRef<'a> { AnyNodeRef::TypeParamTypeVarTuple(node) } } impl<'a> From<&'a crate::TypeParamParamSpec> for AnyNodeRef<'a> { fn from(node: &'a crate::TypeParamParamSpec) -> AnyNodeRef<'a> { AnyNodeRef::TypeParamParamSpec(node) } } impl<'a> From<&'a crate::InterpolatedStringFormatSpec> for AnyNodeRef<'a> { fn from(node: &'a crate::InterpolatedStringFormatSpec) -> AnyNodeRef<'a> { AnyNodeRef::InterpolatedStringFormatSpec(node) } } impl<'a> From<&'a crate::PatternArguments> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternArguments) -> AnyNodeRef<'a> { AnyNodeRef::PatternArguments(node) } } impl<'a> From<&'a crate::PatternKeyword> for AnyNodeRef<'a> { fn from(node: &'a crate::PatternKeyword) -> AnyNodeRef<'a> { AnyNodeRef::PatternKeyword(node) } } impl<'a> From<&'a crate::Comprehension> for AnyNodeRef<'a> { fn from(node: &'a crate::Comprehension) -> AnyNodeRef<'a> { AnyNodeRef::Comprehension(node) } } impl<'a> From<&'a crate::Arguments> for AnyNodeRef<'a> { fn from(node: &'a crate::Arguments) -> AnyNodeRef<'a> { AnyNodeRef::Arguments(node) } } impl<'a> From<&'a crate::Parameters> for AnyNodeRef<'a> { fn from(node: &'a crate::Parameters) -> AnyNodeRef<'a> { AnyNodeRef::Parameters(node) } } impl<'a> From<&'a crate::Parameter> for AnyNodeRef<'a> { fn from(node: &'a crate::Parameter) -> AnyNodeRef<'a> { AnyNodeRef::Parameter(node) } } impl<'a> From<&'a crate::ParameterWithDefault> for AnyNodeRef<'a> { fn from(node: &'a crate::ParameterWithDefault) -> AnyNodeRef<'a> { AnyNodeRef::ParameterWithDefault(node) } } impl<'a> From<&'a crate::Keyword> for AnyNodeRef<'a> { fn from(node: &'a crate::Keyword) -> AnyNodeRef<'a> { AnyNodeRef::Keyword(node) } } impl<'a> From<&'a crate::Alias> for AnyNodeRef<'a> { fn from(node: &'a crate::Alias) -> AnyNodeRef<'a> { AnyNodeRef::Alias(node) } } impl<'a> From<&'a crate::WithItem> for AnyNodeRef<'a> { fn from(node: &'a crate::WithItem) -> AnyNodeRef<'a> { AnyNodeRef::WithItem(node) } } impl<'a> From<&'a crate::MatchCase> for AnyNodeRef<'a> { fn from(node: &'a crate::MatchCase) -> AnyNodeRef<'a> { AnyNodeRef::MatchCase(node) } } impl<'a> From<&'a crate::Decorator> for AnyNodeRef<'a> { fn from(node: &'a crate::Decorator) -> AnyNodeRef<'a> { AnyNodeRef::Decorator(node) } } impl<'a> From<&'a crate::ElifElseClause> for AnyNodeRef<'a> { fn from(node: &'a crate::ElifElseClause) -> AnyNodeRef<'a> { AnyNodeRef::ElifElseClause(node) } } impl<'a> From<&'a crate::TypeParams> for AnyNodeRef<'a> { fn from(node: &'a crate::TypeParams) -> AnyNodeRef<'a> { AnyNodeRef::TypeParams(node) } } impl<'a> From<&'a crate::FString> for AnyNodeRef<'a> { fn from(node: &'a crate::FString) -> AnyNodeRef<'a> { AnyNodeRef::FString(node) } } impl<'a> From<&'a crate::TString> for AnyNodeRef<'a> { fn from(node: &'a crate::TString) -> AnyNodeRef<'a> { AnyNodeRef::TString(node) } } impl<'a> From<&'a crate::StringLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::StringLiteral) -> AnyNodeRef<'a> { AnyNodeRef::StringLiteral(node) } } impl<'a> From<&'a crate::BytesLiteral> for AnyNodeRef<'a> { fn from(node: &'a crate::BytesLiteral) -> AnyNodeRef<'a> { AnyNodeRef::BytesLiteral(node) } } impl<'a> From<&'a crate::Identifier> for AnyNodeRef<'a> { fn from(node: &'a crate::Identifier) -> AnyNodeRef<'a> { AnyNodeRef::Identifier(node) } } impl ruff_text_size::Ranged for AnyNodeRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { AnyNodeRef::ModModule(node) => node.range(), AnyNodeRef::ModExpression(node) => node.range(), AnyNodeRef::StmtFunctionDef(node) => node.range(), AnyNodeRef::StmtClassDef(node) => node.range(), AnyNodeRef::StmtReturn(node) => node.range(), AnyNodeRef::StmtDelete(node) => node.range(), AnyNodeRef::StmtTypeAlias(node) => node.range(), AnyNodeRef::StmtAssign(node) => node.range(), AnyNodeRef::StmtAugAssign(node) => node.range(), AnyNodeRef::StmtAnnAssign(node) => node.range(), AnyNodeRef::StmtFor(node) => node.range(), AnyNodeRef::StmtWhile(node) => node.range(), AnyNodeRef::StmtIf(node) => node.range(), AnyNodeRef::StmtWith(node) => node.range(), AnyNodeRef::StmtMatch(node) => node.range(), AnyNodeRef::StmtRaise(node) => node.range(), AnyNodeRef::StmtTry(node) => node.range(), AnyNodeRef::StmtAssert(node) => node.range(), AnyNodeRef::StmtImport(node) => node.range(), AnyNodeRef::StmtImportFrom(node) => node.range(), AnyNodeRef::StmtGlobal(node) => node.range(), AnyNodeRef::StmtNonlocal(node) => node.range(), AnyNodeRef::StmtExpr(node) => node.range(), AnyNodeRef::StmtPass(node) => node.range(), AnyNodeRef::StmtBreak(node) => node.range(), AnyNodeRef::StmtContinue(node) => node.range(), AnyNodeRef::StmtIpyEscapeCommand(node) => node.range(), AnyNodeRef::ExprBoolOp(node) => node.range(), AnyNodeRef::ExprNamed(node) => node.range(), AnyNodeRef::ExprBinOp(node) => node.range(), AnyNodeRef::ExprUnaryOp(node) => node.range(), AnyNodeRef::ExprLambda(node) => node.range(), AnyNodeRef::ExprIf(node) => node.range(), AnyNodeRef::ExprDict(node) => node.range(), AnyNodeRef::ExprSet(node) => node.range(), AnyNodeRef::ExprListComp(node) => node.range(), AnyNodeRef::ExprSetComp(node) => node.range(), AnyNodeRef::ExprDictComp(node) => node.range(), AnyNodeRef::ExprGenerator(node) => node.range(), AnyNodeRef::ExprAwait(node) => node.range(), AnyNodeRef::ExprYield(node) => node.range(), AnyNodeRef::ExprYieldFrom(node) => node.range(), AnyNodeRef::ExprCompare(node) => node.range(), AnyNodeRef::ExprCall(node) => node.range(), AnyNodeRef::ExprFString(node) => node.range(), AnyNodeRef::ExprTString(node) => node.range(), AnyNodeRef::ExprStringLiteral(node) => node.range(), AnyNodeRef::ExprBytesLiteral(node) => node.range(), AnyNodeRef::ExprNumberLiteral(node) => node.range(), AnyNodeRef::ExprBooleanLiteral(node) => node.range(), AnyNodeRef::ExprNoneLiteral(node) => node.range(), AnyNodeRef::ExprEllipsisLiteral(node) => node.range(), AnyNodeRef::ExprAttribute(node) => node.range(), AnyNodeRef::ExprSubscript(node) => node.range(), AnyNodeRef::ExprStarred(node) => node.range(), AnyNodeRef::ExprName(node) => node.range(), AnyNodeRef::ExprList(node) => node.range(), AnyNodeRef::ExprTuple(node) => node.range(), AnyNodeRef::ExprSlice(node) => node.range(), AnyNodeRef::ExprIpyEscapeCommand(node) => node.range(), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.range(), AnyNodeRef::InterpolatedElement(node) => node.range(), AnyNodeRef::InterpolatedStringLiteralElement(node) => node.range(), AnyNodeRef::PatternMatchValue(node) => node.range(), AnyNodeRef::PatternMatchSingleton(node) => node.range(), AnyNodeRef::PatternMatchSequence(node) => node.range(), AnyNodeRef::PatternMatchMapping(node) => node.range(), AnyNodeRef::PatternMatchClass(node) => node.range(), AnyNodeRef::PatternMatchStar(node) => node.range(), AnyNodeRef::PatternMatchAs(node) => node.range(), AnyNodeRef::PatternMatchOr(node) => node.range(), AnyNodeRef::TypeParamTypeVar(node) => node.range(), AnyNodeRef::TypeParamTypeVarTuple(node) => node.range(), AnyNodeRef::TypeParamParamSpec(node) => node.range(), AnyNodeRef::InterpolatedStringFormatSpec(node) => node.range(), AnyNodeRef::PatternArguments(node) => node.range(), AnyNodeRef::PatternKeyword(node) => node.range(), AnyNodeRef::Comprehension(node) => node.range(), AnyNodeRef::Arguments(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::FString(node) => node.range(), AnyNodeRef::TString(node) => node.range(), AnyNodeRef::StringLiteral(node) => node.range(), AnyNodeRef::BytesLiteral(node) => node.range(), AnyNodeRef::Identifier(node) => node.range(), } } } impl crate::HasNodeIndex for AnyNodeRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { AnyNodeRef::ModModule(node) => node.node_index(), AnyNodeRef::ModExpression(node) => node.node_index(), AnyNodeRef::StmtFunctionDef(node) => node.node_index(), AnyNodeRef::StmtClassDef(node) => node.node_index(), AnyNodeRef::StmtReturn(node) => node.node_index(), AnyNodeRef::StmtDelete(node) => node.node_index(), AnyNodeRef::StmtTypeAlias(node) => node.node_index(), AnyNodeRef::StmtAssign(node) => node.node_index(), AnyNodeRef::StmtAugAssign(node) => node.node_index(), AnyNodeRef::StmtAnnAssign(node) => node.node_index(), AnyNodeRef::StmtFor(node) => node.node_index(), AnyNodeRef::StmtWhile(node) => node.node_index(), AnyNodeRef::StmtIf(node) => node.node_index(), AnyNodeRef::StmtWith(node) => node.node_index(), AnyNodeRef::StmtMatch(node) => node.node_index(), AnyNodeRef::StmtRaise(node) => node.node_index(), AnyNodeRef::StmtTry(node) => node.node_index(), AnyNodeRef::StmtAssert(node) => node.node_index(), AnyNodeRef::StmtImport(node) => node.node_index(), AnyNodeRef::StmtImportFrom(node) => node.node_index(), AnyNodeRef::StmtGlobal(node) => node.node_index(), AnyNodeRef::StmtNonlocal(node) => node.node_index(), AnyNodeRef::StmtExpr(node) => node.node_index(), AnyNodeRef::StmtPass(node) => node.node_index(), AnyNodeRef::StmtBreak(node) => node.node_index(), AnyNodeRef::StmtContinue(node) => node.node_index(), AnyNodeRef::StmtIpyEscapeCommand(node) => node.node_index(), AnyNodeRef::ExprBoolOp(node) => node.node_index(), AnyNodeRef::ExprNamed(node) => node.node_index(), AnyNodeRef::ExprBinOp(node) => node.node_index(), AnyNodeRef::ExprUnaryOp(node) => node.node_index(), AnyNodeRef::ExprLambda(node) => node.node_index(), AnyNodeRef::ExprIf(node) => node.node_index(), AnyNodeRef::ExprDict(node) => node.node_index(), AnyNodeRef::ExprSet(node) => node.node_index(), AnyNodeRef::ExprListComp(node) => node.node_index(), AnyNodeRef::ExprSetComp(node) => node.node_index(), AnyNodeRef::ExprDictComp(node) => node.node_index(), AnyNodeRef::ExprGenerator(node) => node.node_index(), AnyNodeRef::ExprAwait(node) => node.node_index(), AnyNodeRef::ExprYield(node) => node.node_index(), AnyNodeRef::ExprYieldFrom(node) => node.node_index(), AnyNodeRef::ExprCompare(node) => node.node_index(), AnyNodeRef::ExprCall(node) => node.node_index(), AnyNodeRef::ExprFString(node) => node.node_index(), AnyNodeRef::ExprTString(node) => node.node_index(), AnyNodeRef::ExprStringLiteral(node) => node.node_index(), AnyNodeRef::ExprBytesLiteral(node) => node.node_index(), AnyNodeRef::ExprNumberLiteral(node) => node.node_index(), AnyNodeRef::ExprBooleanLiteral(node) => node.node_index(), AnyNodeRef::ExprNoneLiteral(node) => node.node_index(), AnyNodeRef::ExprEllipsisLiteral(node) => node.node_index(), AnyNodeRef::ExprAttribute(node) => node.node_index(), AnyNodeRef::ExprSubscript(node) => node.node_index(), AnyNodeRef::ExprStarred(node) => node.node_index(), AnyNodeRef::ExprName(node) => node.node_index(), AnyNodeRef::ExprList(node) => node.node_index(), AnyNodeRef::ExprTuple(node) => node.node_index(), AnyNodeRef::ExprSlice(node) => node.node_index(), AnyNodeRef::ExprIpyEscapeCommand(node) => node.node_index(), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.node_index(), AnyNodeRef::InterpolatedElement(node) => node.node_index(), AnyNodeRef::InterpolatedStringLiteralElement(node) => node.node_index(), AnyNodeRef::PatternMatchValue(node) => node.node_index(), AnyNodeRef::PatternMatchSingleton(node) => node.node_index(), AnyNodeRef::PatternMatchSequence(node) => node.node_index(), AnyNodeRef::PatternMatchMapping(node) => node.node_index(), AnyNodeRef::PatternMatchClass(node) => node.node_index(), AnyNodeRef::PatternMatchStar(node) => node.node_index(), AnyNodeRef::PatternMatchAs(node) => node.node_index(), AnyNodeRef::PatternMatchOr(node) => node.node_index(), AnyNodeRef::TypeParamTypeVar(node) => node.node_index(), AnyNodeRef::TypeParamTypeVarTuple(node) => node.node_index(), AnyNodeRef::TypeParamParamSpec(node) => node.node_index(), AnyNodeRef::InterpolatedStringFormatSpec(node) => node.node_index(), AnyNodeRef::PatternArguments(node) => node.node_index(), AnyNodeRef::PatternKeyword(node) => node.node_index(), AnyNodeRef::Comprehension(node) => node.node_index(), AnyNodeRef::Arguments(node) => node.node_index(), AnyNodeRef::Parameters(node) => node.node_index(), AnyNodeRef::Parameter(node) => node.node_index(), AnyNodeRef::ParameterWithDefault(node) => node.node_index(), AnyNodeRef::Keyword(node) => node.node_index(), AnyNodeRef::Alias(node) => node.node_index(), AnyNodeRef::WithItem(node) => node.node_index(), AnyNodeRef::MatchCase(node) => node.node_index(), AnyNodeRef::Decorator(node) => node.node_index(), AnyNodeRef::ElifElseClause(node) => node.node_index(), AnyNodeRef::TypeParams(node) => node.node_index(), AnyNodeRef::FString(node) => node.node_index(), AnyNodeRef::TString(node) => node.node_index(), AnyNodeRef::StringLiteral(node) => node.node_index(), AnyNodeRef::BytesLiteral(node) => node.node_index(), AnyNodeRef::Identifier(node) => node.node_index(), } } } impl AnyNodeRef<'_> { pub fn as_ptr(&self) -> std::ptr::NonNull<()> { match self { AnyNodeRef::ModModule(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ModExpression(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtFunctionDef(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtClassDef(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtReturn(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtDelete(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtTypeAlias(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtAssign(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtAugAssign(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtAnnAssign(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtFor(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtWhile(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtIf(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtWith(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtMatch(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtRaise(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtTry(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtAssert(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtImport(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtImportFrom(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtGlobal(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtNonlocal(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtExpr(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtPass(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtBreak(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtContinue(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StmtIpyEscapeCommand(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprBoolOp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprNamed(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprBinOp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprUnaryOp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprLambda(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprIf(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprDict(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprSet(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprListComp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprSetComp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprDictComp(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprGenerator(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprAwait(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprYield(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprYieldFrom(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprCompare(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprCall(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprFString(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprTString(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprStringLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprBytesLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprNumberLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprBooleanLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprNoneLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprEllipsisLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprAttribute(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprSubscript(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprStarred(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprName(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprList(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprTuple(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprSlice(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExprIpyEscapeCommand(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ExceptHandlerExceptHandler(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::InterpolatedElement(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::InterpolatedStringLiteralElement(node) => { std::ptr::NonNull::from(*node).cast() } AnyNodeRef::PatternMatchValue(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSingleton(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSequence(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchMapping(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchClass(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchStar(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchAs(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternMatchOr(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::TypeParamTypeVar(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::TypeParamTypeVarTuple(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::TypeParamParamSpec(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::InterpolatedStringFormatSpec(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternArguments(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::PatternKeyword(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Comprehension(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Arguments(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Parameters(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Parameter(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ParameterWithDefault(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Keyword(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Alias(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::WithItem(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::MatchCase(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Decorator(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::ElifElseClause(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::TypeParams(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::FString(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::TString(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::StringLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::BytesLiteral(node) => std::ptr::NonNull::from(*node).cast(), AnyNodeRef::Identifier(node) => std::ptr::NonNull::from(*node).cast(), } } } impl<'a> AnyNodeRef<'a> { pub fn visit_source_order<'b, V>(self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'b> + ?Sized, 'a: 'b, { match self { AnyNodeRef::ModModule(node) => node.visit_source_order(visitor), AnyNodeRef::ModExpression(node) => node.visit_source_order(visitor), AnyNodeRef::StmtFunctionDef(node) => node.visit_source_order(visitor), AnyNodeRef::StmtClassDef(node) => node.visit_source_order(visitor), AnyNodeRef::StmtReturn(node) => node.visit_source_order(visitor), AnyNodeRef::StmtDelete(node) => node.visit_source_order(visitor), AnyNodeRef::StmtTypeAlias(node) => node.visit_source_order(visitor), AnyNodeRef::StmtAssign(node) => node.visit_source_order(visitor), AnyNodeRef::StmtAugAssign(node) => node.visit_source_order(visitor), AnyNodeRef::StmtAnnAssign(node) => node.visit_source_order(visitor), AnyNodeRef::StmtFor(node) => node.visit_source_order(visitor), AnyNodeRef::StmtWhile(node) => node.visit_source_order(visitor), AnyNodeRef::StmtIf(node) => node.visit_source_order(visitor), AnyNodeRef::StmtWith(node) => node.visit_source_order(visitor), AnyNodeRef::StmtMatch(node) => node.visit_source_order(visitor), AnyNodeRef::StmtRaise(node) => node.visit_source_order(visitor), AnyNodeRef::StmtTry(node) => node.visit_source_order(visitor), AnyNodeRef::StmtAssert(node) => node.visit_source_order(visitor), AnyNodeRef::StmtImport(node) => node.visit_source_order(visitor), AnyNodeRef::StmtImportFrom(node) => node.visit_source_order(visitor), AnyNodeRef::StmtGlobal(node) => node.visit_source_order(visitor), AnyNodeRef::StmtNonlocal(node) => node.visit_source_order(visitor), AnyNodeRef::StmtExpr(node) => node.visit_source_order(visitor), AnyNodeRef::StmtPass(node) => node.visit_source_order(visitor), AnyNodeRef::StmtBreak(node) => node.visit_source_order(visitor), AnyNodeRef::StmtContinue(node) => node.visit_source_order(visitor), AnyNodeRef::StmtIpyEscapeCommand(node) => node.visit_source_order(visitor), AnyNodeRef::ExprBoolOp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprNamed(node) => node.visit_source_order(visitor), AnyNodeRef::ExprBinOp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprUnaryOp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprLambda(node) => node.visit_source_order(visitor), AnyNodeRef::ExprIf(node) => node.visit_source_order(visitor), AnyNodeRef::ExprDict(node) => node.visit_source_order(visitor), AnyNodeRef::ExprSet(node) => node.visit_source_order(visitor), AnyNodeRef::ExprListComp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprSetComp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprDictComp(node) => node.visit_source_order(visitor), AnyNodeRef::ExprGenerator(node) => node.visit_source_order(visitor), AnyNodeRef::ExprAwait(node) => node.visit_source_order(visitor), AnyNodeRef::ExprYield(node) => node.visit_source_order(visitor), AnyNodeRef::ExprYieldFrom(node) => node.visit_source_order(visitor), AnyNodeRef::ExprCompare(node) => node.visit_source_order(visitor), AnyNodeRef::ExprCall(node) => node.visit_source_order(visitor), AnyNodeRef::ExprFString(node) => node.visit_source_order(visitor), AnyNodeRef::ExprTString(node) => node.visit_source_order(visitor), AnyNodeRef::ExprStringLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprBytesLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprNumberLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprBooleanLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprNoneLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprEllipsisLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::ExprAttribute(node) => node.visit_source_order(visitor), AnyNodeRef::ExprSubscript(node) => node.visit_source_order(visitor), AnyNodeRef::ExprStarred(node) => node.visit_source_order(visitor), AnyNodeRef::ExprName(node) => node.visit_source_order(visitor), AnyNodeRef::ExprList(node) => node.visit_source_order(visitor), AnyNodeRef::ExprTuple(node) => node.visit_source_order(visitor), AnyNodeRef::ExprSlice(node) => node.visit_source_order(visitor), AnyNodeRef::ExprIpyEscapeCommand(node) => node.visit_source_order(visitor), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.visit_source_order(visitor), AnyNodeRef::InterpolatedElement(node) => node.visit_source_order(visitor), AnyNodeRef::InterpolatedStringLiteralElement(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchValue(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchSingleton(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchSequence(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchMapping(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchClass(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchStar(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchAs(node) => node.visit_source_order(visitor), AnyNodeRef::PatternMatchOr(node) => node.visit_source_order(visitor), AnyNodeRef::TypeParamTypeVar(node) => node.visit_source_order(visitor), AnyNodeRef::TypeParamTypeVarTuple(node) => node.visit_source_order(visitor), AnyNodeRef::TypeParamParamSpec(node) => node.visit_source_order(visitor), AnyNodeRef::InterpolatedStringFormatSpec(node) => node.visit_source_order(visitor), AnyNodeRef::PatternArguments(node) => node.visit_source_order(visitor), AnyNodeRef::PatternKeyword(node) => node.visit_source_order(visitor), AnyNodeRef::Comprehension(node) => node.visit_source_order(visitor), AnyNodeRef::Arguments(node) => node.visit_source_order(visitor), AnyNodeRef::Parameters(node) => node.visit_source_order(visitor), AnyNodeRef::Parameter(node) => node.visit_source_order(visitor), AnyNodeRef::ParameterWithDefault(node) => node.visit_source_order(visitor), AnyNodeRef::Keyword(node) => node.visit_source_order(visitor), AnyNodeRef::Alias(node) => node.visit_source_order(visitor), AnyNodeRef::WithItem(node) => node.visit_source_order(visitor), AnyNodeRef::MatchCase(node) => node.visit_source_order(visitor), AnyNodeRef::Decorator(node) => node.visit_source_order(visitor), AnyNodeRef::ElifElseClause(node) => node.visit_source_order(visitor), AnyNodeRef::TypeParams(node) => node.visit_source_order(visitor), AnyNodeRef::FString(node) => node.visit_source_order(visitor), AnyNodeRef::TString(node) => node.visit_source_order(visitor), AnyNodeRef::StringLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::BytesLiteral(node) => node.visit_source_order(visitor), AnyNodeRef::Identifier(node) => node.visit_source_order(visitor), } } } impl AnyNodeRef<'_> { pub const fn is_module(self) -> bool { matches!( self, AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) ) } } impl AnyNodeRef<'_> { pub const fn is_statement(self) -> bool { matches!( self, AnyNodeRef::StmtFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) | AnyNodeRef::StmtTypeAlias(_) | AnyNodeRef::StmtAssign(_) | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) | AnyNodeRef::StmtGlobal(_) | AnyNodeRef::StmtNonlocal(_) | AnyNodeRef::StmtExpr(_) | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) | AnyNodeRef::StmtIpyEscapeCommand(_) ) } } impl AnyNodeRef<'_> { pub const fn is_expression(self) -> bool { matches!( self, AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamed(_) | AnyNodeRef::ExprBinOp(_) | AnyNodeRef::ExprUnaryOp(_) | AnyNodeRef::ExprLambda(_) | AnyNodeRef::ExprIf(_) | AnyNodeRef::ExprDict(_) | AnyNodeRef::ExprSet(_) | AnyNodeRef::ExprListComp(_) | AnyNodeRef::ExprSetComp(_) | AnyNodeRef::ExprDictComp(_) | AnyNodeRef::ExprGenerator(_) | AnyNodeRef::ExprAwait(_) | AnyNodeRef::ExprYield(_) | AnyNodeRef::ExprYieldFrom(_) | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprTString(_) | AnyNodeRef::ExprStringLiteral(_) | AnyNodeRef::ExprBytesLiteral(_) | AnyNodeRef::ExprNumberLiteral(_) | AnyNodeRef::ExprBooleanLiteral(_) | AnyNodeRef::ExprNoneLiteral(_) | AnyNodeRef::ExprEllipsisLiteral(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) | AnyNodeRef::ExprStarred(_) | AnyNodeRef::ExprName(_) | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) | AnyNodeRef::ExprIpyEscapeCommand(_) ) } } impl AnyNodeRef<'_> { pub const fn is_except_handler(self) -> bool { matches!(self, AnyNodeRef::ExceptHandlerExceptHandler(_)) } } impl AnyNodeRef<'_> { pub const fn is_interpolated_string_element(self) -> bool { matches!( self, AnyNodeRef::InterpolatedElement(_) | AnyNodeRef::InterpolatedStringLiteralElement(_) ) } } impl AnyNodeRef<'_> { pub const fn is_pattern(self) -> bool { matches!( self, AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSequence(_) | AnyNodeRef::PatternMatchMapping(_) | AnyNodeRef::PatternMatchClass(_) | AnyNodeRef::PatternMatchStar(_) | AnyNodeRef::PatternMatchAs(_) | AnyNodeRef::PatternMatchOr(_) ) } } impl AnyNodeRef<'_> { pub const fn is_type_param(self) -> bool { matches!( self, AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) ) } } /// An enumeration of all AST nodes. /// /// Unlike `AnyNodeRef`, this type does not flatten nested enums, so its variants only /// consist of the "root" AST node types. This is useful as it exposes references to the /// original enums, not just references to their inner values. /// /// For example, `AnyRootNodeRef::Mod` contains a reference to the `Mod` enum, while /// `AnyNodeRef` has top-level `AnyNodeRef::ModModule` and `AnyNodeRef::ModExpression` /// variants. #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum AnyRootNodeRef<'a> { Mod(&'a Mod), Stmt(&'a Stmt), Expr(&'a Expr), ExceptHandler(&'a ExceptHandler), InterpolatedStringElement(&'a InterpolatedStringElement), Pattern(&'a Pattern), TypeParam(&'a TypeParam), InterpolatedStringFormatSpec(&'a crate::InterpolatedStringFormatSpec), PatternArguments(&'a crate::PatternArguments), PatternKeyword(&'a crate::PatternKeyword), Comprehension(&'a crate::Comprehension), Arguments(&'a crate::Arguments), Parameters(&'a crate::Parameters), Parameter(&'a crate::Parameter), ParameterWithDefault(&'a crate::ParameterWithDefault), Keyword(&'a crate::Keyword), Alias(&'a crate::Alias), WithItem(&'a crate::WithItem), MatchCase(&'a crate::MatchCase), Decorator(&'a crate::Decorator), ElifElseClause(&'a crate::ElifElseClause), TypeParams(&'a crate::TypeParams), FString(&'a crate::FString), TString(&'a crate::TString), StringLiteral(&'a crate::StringLiteral), BytesLiteral(&'a crate::BytesLiteral), Identifier(&'a crate::Identifier), } /// The unflattened enum or struct type stored by an [`AnyRootNodeRef`]. /// /// Unlike [`NodeKind`], this does not distinguish variants of root enums such as [`Stmt`] /// and [`Expr`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] #[repr(u8)] pub enum RootNodeKind { Mod, Stmt, Expr, ExceptHandler, InterpolatedStringElement, Pattern, TypeParam, InterpolatedStringFormatSpec, PatternArguments, PatternKeyword, Comprehension, Arguments, Parameters, Parameter, ParameterWithDefault, Keyword, Alias, WithItem, MatchCase, Decorator, ElifElseClause, TypeParams, FString, TString, StringLiteral, BytesLiteral, Identifier, } impl RootNodeKind { /// All root node kinds in discriminant order. pub const ALL: &'static [Self] = &[ Self::Mod, Self::Stmt, Self::Expr, Self::ExceptHandler, Self::InterpolatedStringElement, Self::Pattern, Self::TypeParam, Self::InterpolatedStringFormatSpec, Self::PatternArguments, Self::PatternKeyword, Self::Comprehension, Self::Arguments, Self::Parameters, Self::Parameter, Self::ParameterWithDefault, Self::Keyword, Self::Alias, Self::WithItem, Self::MatchCase, Self::Decorator, Self::ElifElseClause, Self::TypeParams, Self::FString, Self::TString, Self::StringLiteral, Self::BytesLiteral, Self::Identifier, ]; /// Returns the root node kind with the given discriminant. #[inline] pub fn from_u8(value: u8) -> Option { match value { 0 => Some(Self::Mod), 1 => Some(Self::Stmt), 2 => Some(Self::Expr), 3 => Some(Self::ExceptHandler), 4 => Some(Self::InterpolatedStringElement), 5 => Some(Self::Pattern), 6 => Some(Self::TypeParam), 7 => Some(Self::InterpolatedStringFormatSpec), 8 => Some(Self::PatternArguments), 9 => Some(Self::PatternKeyword), 10 => Some(Self::Comprehension), 11 => Some(Self::Arguments), 12 => Some(Self::Parameters), 13 => Some(Self::Parameter), 14 => Some(Self::ParameterWithDefault), 15 => Some(Self::Keyword), 16 => Some(Self::Alias), 17 => Some(Self::WithItem), 18 => Some(Self::MatchCase), 19 => Some(Self::Decorator), 20 => Some(Self::ElifElseClause), 21 => Some(Self::TypeParams), 22 => Some(Self::FString), 23 => Some(Self::TString), 24 => Some(Self::StringLiteral), 25 => Some(Self::BytesLiteral), 26 => Some(Self::Identifier), _ => None, } } } impl<'a> From<&'a Mod> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a Mod) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Mod(node) } } impl<'a> TryFrom> for &'a Mod { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a Mod, ()> { match node { AnyRootNodeRef::Mod(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ModModule { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ModModule, ()> { match node { AnyRootNodeRef::Mod(Mod::Module(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ModExpression { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ModExpression, ()> { match node { AnyRootNodeRef::Mod(Mod::Expression(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a Stmt> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a Stmt) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Stmt(node) } } impl<'a> TryFrom> for &'a Stmt { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a Stmt, ()> { match node { AnyRootNodeRef::Stmt(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtFunctionDef { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtFunctionDef, ()> { match node { AnyRootNodeRef::Stmt(Stmt::FunctionDef(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtClassDef { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtClassDef, ()> { match node { AnyRootNodeRef::Stmt(Stmt::ClassDef(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtReturn { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtReturn, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Return(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtDelete { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtDelete, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Delete(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtTypeAlias { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtTypeAlias, ()> { match node { AnyRootNodeRef::Stmt(Stmt::TypeAlias(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtAssign { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtAssign, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Assign(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtAugAssign { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtAugAssign, ()> { match node { AnyRootNodeRef::Stmt(Stmt::AugAssign(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtAnnAssign { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtAnnAssign, ()> { match node { AnyRootNodeRef::Stmt(Stmt::AnnAssign(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtFor { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtFor, ()> { match node { AnyRootNodeRef::Stmt(Stmt::For(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtWhile { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtWhile, ()> { match node { AnyRootNodeRef::Stmt(Stmt::While(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtIf { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtIf, ()> { match node { AnyRootNodeRef::Stmt(Stmt::If(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtWith { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtWith, ()> { match node { AnyRootNodeRef::Stmt(Stmt::With(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtMatch { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtMatch, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Match(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtRaise { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtRaise, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Raise(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtTry { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtTry, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Try(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtAssert { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtAssert, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Assert(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtImport { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtImport, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Import(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtImportFrom { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtImportFrom, ()> { match node { AnyRootNodeRef::Stmt(Stmt::ImportFrom(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtGlobal { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtGlobal, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Global(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtNonlocal { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtNonlocal, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Nonlocal(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtExpr { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtExpr, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Expr(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtPass { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtPass, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Pass(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtBreak { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtBreak, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Break(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtContinue { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtContinue, ()> { match node { AnyRootNodeRef::Stmt(Stmt::Continue(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::StmtIpyEscapeCommand { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StmtIpyEscapeCommand, ()> { match node { AnyRootNodeRef::Stmt(Stmt::IpyEscapeCommand(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a Expr> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a Expr) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Expr(node) } } impl<'a> TryFrom> for &'a Expr { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a Expr, ()> { match node { AnyRootNodeRef::Expr(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprBoolOp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprBoolOp, ()> { match node { AnyRootNodeRef::Expr(Expr::BoolOp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprNamed { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprNamed, ()> { match node { AnyRootNodeRef::Expr(Expr::Named(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprBinOp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprBinOp, ()> { match node { AnyRootNodeRef::Expr(Expr::BinOp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprUnaryOp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprUnaryOp, ()> { match node { AnyRootNodeRef::Expr(Expr::UnaryOp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprLambda { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprLambda, ()> { match node { AnyRootNodeRef::Expr(Expr::Lambda(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprIf { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprIf, ()> { match node { AnyRootNodeRef::Expr(Expr::If(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprDict { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprDict, ()> { match node { AnyRootNodeRef::Expr(Expr::Dict(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprSet { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprSet, ()> { match node { AnyRootNodeRef::Expr(Expr::Set(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprListComp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprListComp, ()> { match node { AnyRootNodeRef::Expr(Expr::ListComp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprSetComp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprSetComp, ()> { match node { AnyRootNodeRef::Expr(Expr::SetComp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprDictComp { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprDictComp, ()> { match node { AnyRootNodeRef::Expr(Expr::DictComp(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprGenerator { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprGenerator, ()> { match node { AnyRootNodeRef::Expr(Expr::Generator(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprAwait { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprAwait, ()> { match node { AnyRootNodeRef::Expr(Expr::Await(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprYield { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprYield, ()> { match node { AnyRootNodeRef::Expr(Expr::Yield(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprYieldFrom { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprYieldFrom, ()> { match node { AnyRootNodeRef::Expr(Expr::YieldFrom(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprCompare { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprCompare, ()> { match node { AnyRootNodeRef::Expr(Expr::Compare(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprCall { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprCall, ()> { match node { AnyRootNodeRef::Expr(Expr::Call(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprFString { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprFString, ()> { match node { AnyRootNodeRef::Expr(Expr::FString(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprTString { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprTString, ()> { match node { AnyRootNodeRef::Expr(Expr::TString(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprStringLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprStringLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::StringLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprBytesLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprBytesLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::BytesLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprNumberLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprNumberLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::NumberLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprBooleanLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprBooleanLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::BooleanLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprNoneLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprNoneLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::NoneLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprEllipsisLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprEllipsisLiteral, ()> { match node { AnyRootNodeRef::Expr(Expr::EllipsisLiteral(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprAttribute { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprAttribute, ()> { match node { AnyRootNodeRef::Expr(Expr::Attribute(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprSubscript { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprSubscript, ()> { match node { AnyRootNodeRef::Expr(Expr::Subscript(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprStarred { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprStarred, ()> { match node { AnyRootNodeRef::Expr(Expr::Starred(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprName { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprName, ()> { match node { AnyRootNodeRef::Expr(Expr::Name(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprList { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprList, ()> { match node { AnyRootNodeRef::Expr(Expr::List(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprTuple { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprTuple, ()> { match node { AnyRootNodeRef::Expr(Expr::Tuple(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprSlice { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprSlice, ()> { match node { AnyRootNodeRef::Expr(Expr::Slice(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExprIpyEscapeCommand { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExprIpyEscapeCommand, ()> { match node { AnyRootNodeRef::Expr(Expr::IpyEscapeCommand(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a ExceptHandler> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a ExceptHandler) -> AnyRootNodeRef<'a> { AnyRootNodeRef::ExceptHandler(node) } } impl<'a> TryFrom> for &'a ExceptHandler { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a ExceptHandler, ()> { match node { AnyRootNodeRef::ExceptHandler(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::ExceptHandlerExceptHandler { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ExceptHandlerExceptHandler, ()> { match node { AnyRootNodeRef::ExceptHandler(ExceptHandler::ExceptHandler(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a InterpolatedStringElement> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a InterpolatedStringElement) -> AnyRootNodeRef<'a> { AnyRootNodeRef::InterpolatedStringElement(node) } } impl<'a> TryFrom> for &'a InterpolatedStringElement { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a InterpolatedStringElement, ()> { match node { AnyRootNodeRef::InterpolatedStringElement(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::InterpolatedElement { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::InterpolatedElement, ()> { match node { AnyRootNodeRef::InterpolatedStringElement( InterpolatedStringElement::Interpolation(node), ) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::InterpolatedStringLiteralElement { type Error = (); fn try_from( node: AnyRootNodeRef<'a>, ) -> Result<&'a crate::InterpolatedStringLiteralElement, ()> { match node { AnyRootNodeRef::InterpolatedStringElement(InterpolatedStringElement::Literal(node)) => { Ok(node) } _ => Err(()), } } } impl<'a> From<&'a Pattern> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a Pattern) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Pattern(node) } } impl<'a> TryFrom> for &'a Pattern { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a Pattern, ()> { match node { AnyRootNodeRef::Pattern(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchValue { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchValue, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchValue(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchSingleton { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchSingleton, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchSingleton(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchSequence { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchSequence, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchSequence(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchMapping { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchMapping, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchMapping(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchClass { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchClass, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchClass(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchStar { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchStar, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchStar(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchAs { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchAs, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchAs(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::PatternMatchOr { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternMatchOr, ()> { match node { AnyRootNodeRef::Pattern(Pattern::MatchOr(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a TypeParam> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a TypeParam) -> AnyRootNodeRef<'a> { AnyRootNodeRef::TypeParam(node) } } impl<'a> TryFrom> for &'a TypeParam { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a TypeParam, ()> { match node { AnyRootNodeRef::TypeParam(node) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::TypeParamTypeVar { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::TypeParamTypeVar, ()> { match node { AnyRootNodeRef::TypeParam(TypeParam::TypeVar(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::TypeParamTypeVarTuple { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::TypeParamTypeVarTuple, ()> { match node { AnyRootNodeRef::TypeParam(TypeParam::TypeVarTuple(node)) => Ok(node), _ => Err(()), } } } impl<'a> TryFrom> for &'a crate::TypeParamParamSpec { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::TypeParamParamSpec, ()> { match node { AnyRootNodeRef::TypeParam(TypeParam::ParamSpec(node)) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::InterpolatedStringFormatSpec> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::InterpolatedStringFormatSpec) -> AnyRootNodeRef<'a> { AnyRootNodeRef::InterpolatedStringFormatSpec(node) } } impl<'a> TryFrom> for &'a crate::InterpolatedStringFormatSpec { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::InterpolatedStringFormatSpec, ()> { match node { AnyRootNodeRef::InterpolatedStringFormatSpec(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::PatternArguments> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::PatternArguments) -> AnyRootNodeRef<'a> { AnyRootNodeRef::PatternArguments(node) } } impl<'a> TryFrom> for &'a crate::PatternArguments { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternArguments, ()> { match node { AnyRootNodeRef::PatternArguments(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::PatternKeyword> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::PatternKeyword) -> AnyRootNodeRef<'a> { AnyRootNodeRef::PatternKeyword(node) } } impl<'a> TryFrom> for &'a crate::PatternKeyword { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::PatternKeyword, ()> { match node { AnyRootNodeRef::PatternKeyword(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Comprehension> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Comprehension) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Comprehension(node) } } impl<'a> TryFrom> for &'a crate::Comprehension { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Comprehension, ()> { match node { AnyRootNodeRef::Comprehension(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Arguments> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Arguments) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Arguments(node) } } impl<'a> TryFrom> for &'a crate::Arguments { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Arguments, ()> { match node { AnyRootNodeRef::Arguments(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Parameters> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Parameters) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Parameters(node) } } impl<'a> TryFrom> for &'a crate::Parameters { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Parameters, ()> { match node { AnyRootNodeRef::Parameters(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Parameter> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Parameter) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Parameter(node) } } impl<'a> TryFrom> for &'a crate::Parameter { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Parameter, ()> { match node { AnyRootNodeRef::Parameter(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::ParameterWithDefault> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::ParameterWithDefault) -> AnyRootNodeRef<'a> { AnyRootNodeRef::ParameterWithDefault(node) } } impl<'a> TryFrom> for &'a crate::ParameterWithDefault { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ParameterWithDefault, ()> { match node { AnyRootNodeRef::ParameterWithDefault(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Keyword> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Keyword) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Keyword(node) } } impl<'a> TryFrom> for &'a crate::Keyword { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Keyword, ()> { match node { AnyRootNodeRef::Keyword(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Alias> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Alias) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Alias(node) } } impl<'a> TryFrom> for &'a crate::Alias { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Alias, ()> { match node { AnyRootNodeRef::Alias(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::WithItem> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::WithItem) -> AnyRootNodeRef<'a> { AnyRootNodeRef::WithItem(node) } } impl<'a> TryFrom> for &'a crate::WithItem { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::WithItem, ()> { match node { AnyRootNodeRef::WithItem(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::MatchCase> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::MatchCase) -> AnyRootNodeRef<'a> { AnyRootNodeRef::MatchCase(node) } } impl<'a> TryFrom> for &'a crate::MatchCase { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::MatchCase, ()> { match node { AnyRootNodeRef::MatchCase(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Decorator> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Decorator) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Decorator(node) } } impl<'a> TryFrom> for &'a crate::Decorator { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Decorator, ()> { match node { AnyRootNodeRef::Decorator(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::ElifElseClause> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::ElifElseClause) -> AnyRootNodeRef<'a> { AnyRootNodeRef::ElifElseClause(node) } } impl<'a> TryFrom> for &'a crate::ElifElseClause { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::ElifElseClause, ()> { match node { AnyRootNodeRef::ElifElseClause(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::TypeParams> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::TypeParams) -> AnyRootNodeRef<'a> { AnyRootNodeRef::TypeParams(node) } } impl<'a> TryFrom> for &'a crate::TypeParams { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::TypeParams, ()> { match node { AnyRootNodeRef::TypeParams(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::FString> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::FString) -> AnyRootNodeRef<'a> { AnyRootNodeRef::FString(node) } } impl<'a> TryFrom> for &'a crate::FString { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::FString, ()> { match node { AnyRootNodeRef::FString(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::TString> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::TString) -> AnyRootNodeRef<'a> { AnyRootNodeRef::TString(node) } } impl<'a> TryFrom> for &'a crate::TString { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::TString, ()> { match node { AnyRootNodeRef::TString(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::StringLiteral> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::StringLiteral) -> AnyRootNodeRef<'a> { AnyRootNodeRef::StringLiteral(node) } } impl<'a> TryFrom> for &'a crate::StringLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::StringLiteral, ()> { match node { AnyRootNodeRef::StringLiteral(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::BytesLiteral> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::BytesLiteral) -> AnyRootNodeRef<'a> { AnyRootNodeRef::BytesLiteral(node) } } impl<'a> TryFrom> for &'a crate::BytesLiteral { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::BytesLiteral, ()> { match node { AnyRootNodeRef::BytesLiteral(node) => Ok(node), _ => Err(()), } } } impl<'a> From<&'a crate::Identifier> for AnyRootNodeRef<'a> { #[inline] fn from(node: &'a crate::Identifier) -> AnyRootNodeRef<'a> { AnyRootNodeRef::Identifier(node) } } impl<'a> TryFrom> for &'a crate::Identifier { type Error = (); fn try_from(node: AnyRootNodeRef<'a>) -> Result<&'a crate::Identifier, ()> { match node { AnyRootNodeRef::Identifier(node) => Ok(node), _ => Err(()), } } } impl ruff_text_size::Ranged for AnyRootNodeRef<'_> { fn range(&self) -> ruff_text_size::TextRange { match self { AnyRootNodeRef::Mod(node) => node.range(), AnyRootNodeRef::Stmt(node) => node.range(), AnyRootNodeRef::Expr(node) => node.range(), AnyRootNodeRef::ExceptHandler(node) => node.range(), AnyRootNodeRef::InterpolatedStringElement(node) => node.range(), AnyRootNodeRef::Pattern(node) => node.range(), AnyRootNodeRef::TypeParam(node) => node.range(), AnyRootNodeRef::InterpolatedStringFormatSpec(node) => node.range(), AnyRootNodeRef::PatternArguments(node) => node.range(), AnyRootNodeRef::PatternKeyword(node) => node.range(), AnyRootNodeRef::Comprehension(node) => node.range(), AnyRootNodeRef::Arguments(node) => node.range(), AnyRootNodeRef::Parameters(node) => node.range(), AnyRootNodeRef::Parameter(node) => node.range(), AnyRootNodeRef::ParameterWithDefault(node) => node.range(), AnyRootNodeRef::Keyword(node) => node.range(), AnyRootNodeRef::Alias(node) => node.range(), AnyRootNodeRef::WithItem(node) => node.range(), AnyRootNodeRef::MatchCase(node) => node.range(), AnyRootNodeRef::Decorator(node) => node.range(), AnyRootNodeRef::ElifElseClause(node) => node.range(), AnyRootNodeRef::TypeParams(node) => node.range(), AnyRootNodeRef::FString(node) => node.range(), AnyRootNodeRef::TString(node) => node.range(), AnyRootNodeRef::StringLiteral(node) => node.range(), AnyRootNodeRef::BytesLiteral(node) => node.range(), AnyRootNodeRef::Identifier(node) => node.range(), } } } impl crate::HasNodeIndex for AnyRootNodeRef<'_> { fn node_index(&self) -> &crate::AtomicNodeIndex { match self { AnyRootNodeRef::Mod(node) => node.node_index(), AnyRootNodeRef::Stmt(node) => node.node_index(), AnyRootNodeRef::Expr(node) => node.node_index(), AnyRootNodeRef::ExceptHandler(node) => node.node_index(), AnyRootNodeRef::InterpolatedStringElement(node) => node.node_index(), AnyRootNodeRef::Pattern(node) => node.node_index(), AnyRootNodeRef::TypeParam(node) => node.node_index(), AnyRootNodeRef::InterpolatedStringFormatSpec(node) => node.node_index(), AnyRootNodeRef::PatternArguments(node) => node.node_index(), AnyRootNodeRef::PatternKeyword(node) => node.node_index(), AnyRootNodeRef::Comprehension(node) => node.node_index(), AnyRootNodeRef::Arguments(node) => node.node_index(), AnyRootNodeRef::Parameters(node) => node.node_index(), AnyRootNodeRef::Parameter(node) => node.node_index(), AnyRootNodeRef::ParameterWithDefault(node) => node.node_index(), AnyRootNodeRef::Keyword(node) => node.node_index(), AnyRootNodeRef::Alias(node) => node.node_index(), AnyRootNodeRef::WithItem(node) => node.node_index(), AnyRootNodeRef::MatchCase(node) => node.node_index(), AnyRootNodeRef::Decorator(node) => node.node_index(), AnyRootNodeRef::ElifElseClause(node) => node.node_index(), AnyRootNodeRef::TypeParams(node) => node.node_index(), AnyRootNodeRef::FString(node) => node.node_index(), AnyRootNodeRef::TString(node) => node.node_index(), AnyRootNodeRef::StringLiteral(node) => node.node_index(), AnyRootNodeRef::BytesLiteral(node) => node.node_index(), AnyRootNodeRef::Identifier(node) => node.node_index(), } } } impl<'a> AnyRootNodeRef<'a> { /// Decomposes this reference into its root node kind and a type-erased pointer. #[inline] pub fn into_raw_parts(self) -> (RootNodeKind, std::ptr::NonNull<()>) { match self { AnyRootNodeRef::Mod(node) => (RootNodeKind::Mod, std::ptr::NonNull::from(node).cast()), AnyRootNodeRef::Stmt(node) => { (RootNodeKind::Stmt, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::Expr(node) => { (RootNodeKind::Expr, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::ExceptHandler(node) => ( RootNodeKind::ExceptHandler, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::InterpolatedStringElement(node) => ( RootNodeKind::InterpolatedStringElement, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Pattern(node) => { (RootNodeKind::Pattern, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::TypeParam(node) => ( RootNodeKind::TypeParam, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::InterpolatedStringFormatSpec(node) => ( RootNodeKind::InterpolatedStringFormatSpec, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::PatternArguments(node) => ( RootNodeKind::PatternArguments, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::PatternKeyword(node) => ( RootNodeKind::PatternKeyword, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Comprehension(node) => ( RootNodeKind::Comprehension, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Arguments(node) => ( RootNodeKind::Arguments, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Parameters(node) => ( RootNodeKind::Parameters, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Parameter(node) => ( RootNodeKind::Parameter, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::ParameterWithDefault(node) => ( RootNodeKind::ParameterWithDefault, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Keyword(node) => { (RootNodeKind::Keyword, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::Alias(node) => { (RootNodeKind::Alias, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::WithItem(node) => { (RootNodeKind::WithItem, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::MatchCase(node) => ( RootNodeKind::MatchCase, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Decorator(node) => ( RootNodeKind::Decorator, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::ElifElseClause(node) => ( RootNodeKind::ElifElseClause, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::TypeParams(node) => ( RootNodeKind::TypeParams, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::FString(node) => { (RootNodeKind::FString, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::TString(node) => { (RootNodeKind::TString, std::ptr::NonNull::from(node).cast()) } AnyRootNodeRef::StringLiteral(node) => ( RootNodeKind::StringLiteral, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::BytesLiteral(node) => ( RootNodeKind::BytesLiteral, std::ptr::NonNull::from(node).cast(), ), AnyRootNodeRef::Identifier(node) => ( RootNodeKind::Identifier, std::ptr::NonNull::from(node).cast(), ), } } /// Reconstructs an AST reference from its root node kind and type-erased pointer. /// /// # Safety /// /// - `pointer` must be properly aligned for and point to the exact root node type /// represented by `kind`. /// - The pointer's provenance must permit reads of a complete, initialized, and valid /// value of that type. /// - The pointed-to value must not be moved, dropped, or accessed mutably for `'a`. #[inline] #[expect(unsafe_code, reason = "reconstructs a type-erased AST reference")] pub unsafe fn from_raw_parts(kind: RootNodeKind, pointer: std::ptr::NonNull<()>) -> Self { let pointer = pointer.as_ptr(); // SAFETY: The caller guarantees that `pointer` is readable as the exact root node // type selected by `kind` and remains valid and immutable for `'a`. unsafe { match kind { RootNodeKind::Mod => AnyRootNodeRef::Mod(&*pointer.cast::()), RootNodeKind::Stmt => AnyRootNodeRef::Stmt(&*pointer.cast::()), RootNodeKind::Expr => AnyRootNodeRef::Expr(&*pointer.cast::()), RootNodeKind::ExceptHandler => { AnyRootNodeRef::ExceptHandler(&*pointer.cast::()) } RootNodeKind::InterpolatedStringElement => { AnyRootNodeRef::InterpolatedStringElement( &*pointer.cast::(), ) } RootNodeKind::Pattern => AnyRootNodeRef::Pattern(&*pointer.cast::()), RootNodeKind::TypeParam => AnyRootNodeRef::TypeParam(&*pointer.cast::()), RootNodeKind::InterpolatedStringFormatSpec => { AnyRootNodeRef::InterpolatedStringFormatSpec( &*pointer.cast::(), ) } RootNodeKind::PatternArguments => { AnyRootNodeRef::PatternArguments(&*pointer.cast::()) } RootNodeKind::PatternKeyword => { AnyRootNodeRef::PatternKeyword(&*pointer.cast::()) } RootNodeKind::Comprehension => { AnyRootNodeRef::Comprehension(&*pointer.cast::()) } RootNodeKind::Arguments => { AnyRootNodeRef::Arguments(&*pointer.cast::()) } RootNodeKind::Parameters => { AnyRootNodeRef::Parameters(&*pointer.cast::()) } RootNodeKind::Parameter => { AnyRootNodeRef::Parameter(&*pointer.cast::()) } RootNodeKind::ParameterWithDefault => AnyRootNodeRef::ParameterWithDefault( &*pointer.cast::(), ), RootNodeKind::Keyword => { AnyRootNodeRef::Keyword(&*pointer.cast::()) } RootNodeKind::Alias => AnyRootNodeRef::Alias(&*pointer.cast::()), RootNodeKind::WithItem => { AnyRootNodeRef::WithItem(&*pointer.cast::()) } RootNodeKind::MatchCase => { AnyRootNodeRef::MatchCase(&*pointer.cast::()) } RootNodeKind::Decorator => { AnyRootNodeRef::Decorator(&*pointer.cast::()) } RootNodeKind::ElifElseClause => { AnyRootNodeRef::ElifElseClause(&*pointer.cast::()) } RootNodeKind::TypeParams => { AnyRootNodeRef::TypeParams(&*pointer.cast::()) } RootNodeKind::FString => { AnyRootNodeRef::FString(&*pointer.cast::()) } RootNodeKind::TString => { AnyRootNodeRef::TString(&*pointer.cast::()) } RootNodeKind::StringLiteral => { AnyRootNodeRef::StringLiteral(&*pointer.cast::()) } RootNodeKind::BytesLiteral => { AnyRootNodeRef::BytesLiteral(&*pointer.cast::()) } RootNodeKind::Identifier => { AnyRootNodeRef::Identifier(&*pointer.cast::()) } } } } pub fn visit_source_order<'b, V>(self, visitor: &mut V) where V: crate::visitor::source_order::SourceOrderVisitor<'b> + ?Sized, 'a: 'b, { match self { AnyRootNodeRef::Mod(node) => node.visit_source_order(visitor), AnyRootNodeRef::Stmt(node) => node.visit_source_order(visitor), AnyRootNodeRef::Expr(node) => node.visit_source_order(visitor), AnyRootNodeRef::ExceptHandler(node) => node.visit_source_order(visitor), AnyRootNodeRef::InterpolatedStringElement(node) => node.visit_source_order(visitor), AnyRootNodeRef::Pattern(node) => node.visit_source_order(visitor), AnyRootNodeRef::TypeParam(node) => node.visit_source_order(visitor), AnyRootNodeRef::InterpolatedStringFormatSpec(node) => node.visit_source_order(visitor), AnyRootNodeRef::PatternArguments(node) => node.visit_source_order(visitor), AnyRootNodeRef::PatternKeyword(node) => node.visit_source_order(visitor), AnyRootNodeRef::Comprehension(node) => node.visit_source_order(visitor), AnyRootNodeRef::Arguments(node) => node.visit_source_order(visitor), AnyRootNodeRef::Parameters(node) => node.visit_source_order(visitor), AnyRootNodeRef::Parameter(node) => node.visit_source_order(visitor), AnyRootNodeRef::ParameterWithDefault(node) => node.visit_source_order(visitor), AnyRootNodeRef::Keyword(node) => node.visit_source_order(visitor), AnyRootNodeRef::Alias(node) => node.visit_source_order(visitor), AnyRootNodeRef::WithItem(node) => node.visit_source_order(visitor), AnyRootNodeRef::MatchCase(node) => node.visit_source_order(visitor), AnyRootNodeRef::Decorator(node) => node.visit_source_order(visitor), AnyRootNodeRef::ElifElseClause(node) => node.visit_source_order(visitor), AnyRootNodeRef::TypeParams(node) => node.visit_source_order(visitor), AnyRootNodeRef::FString(node) => node.visit_source_order(visitor), AnyRootNodeRef::TString(node) => node.visit_source_order(visitor), AnyRootNodeRef::StringLiteral(node) => node.visit_source_order(visitor), AnyRootNodeRef::BytesLiteral(node) => node.visit_source_order(visitor), AnyRootNodeRef::Identifier(node) => node.visit_source_order(visitor), } } } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum NodeKind { ModModule, ModExpression, StmtFunctionDef, StmtClassDef, StmtReturn, StmtDelete, StmtTypeAlias, StmtAssign, StmtAugAssign, StmtAnnAssign, StmtFor, StmtWhile, StmtIf, StmtWith, StmtMatch, StmtRaise, StmtTry, StmtAssert, StmtImport, StmtImportFrom, StmtGlobal, StmtNonlocal, StmtExpr, StmtPass, StmtBreak, StmtContinue, StmtIpyEscapeCommand, ExprBoolOp, ExprNamed, ExprBinOp, ExprUnaryOp, ExprLambda, ExprIf, ExprDict, ExprSet, ExprListComp, ExprSetComp, ExprDictComp, ExprGenerator, ExprAwait, ExprYield, ExprYieldFrom, ExprCompare, ExprCall, ExprFString, ExprTString, ExprStringLiteral, ExprBytesLiteral, ExprNumberLiteral, ExprBooleanLiteral, ExprNoneLiteral, ExprEllipsisLiteral, ExprAttribute, ExprSubscript, ExprStarred, ExprName, ExprList, ExprTuple, ExprSlice, ExprIpyEscapeCommand, ExceptHandlerExceptHandler, InterpolatedElement, InterpolatedStringLiteralElement, PatternMatchValue, PatternMatchSingleton, PatternMatchSequence, PatternMatchMapping, PatternMatchClass, PatternMatchStar, PatternMatchAs, PatternMatchOr, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParamParamSpec, InterpolatedStringFormatSpec, PatternArguments, PatternKeyword, Comprehension, Arguments, Parameters, Parameter, ParameterWithDefault, Keyword, Alias, WithItem, MatchCase, Decorator, ElifElseClause, TypeParams, FString, TString, StringLiteral, BytesLiteral, Identifier, } impl AnyNodeRef<'_> { pub const fn kind(self) -> NodeKind { match self { AnyNodeRef::ModModule(_) => NodeKind::ModModule, AnyNodeRef::ModExpression(_) => NodeKind::ModExpression, AnyNodeRef::StmtFunctionDef(_) => NodeKind::StmtFunctionDef, AnyNodeRef::StmtClassDef(_) => NodeKind::StmtClassDef, AnyNodeRef::StmtReturn(_) => NodeKind::StmtReturn, AnyNodeRef::StmtDelete(_) => NodeKind::StmtDelete, AnyNodeRef::StmtTypeAlias(_) => NodeKind::StmtTypeAlias, AnyNodeRef::StmtAssign(_) => NodeKind::StmtAssign, AnyNodeRef::StmtAugAssign(_) => NodeKind::StmtAugAssign, AnyNodeRef::StmtAnnAssign(_) => NodeKind::StmtAnnAssign, AnyNodeRef::StmtFor(_) => NodeKind::StmtFor, AnyNodeRef::StmtWhile(_) => NodeKind::StmtWhile, AnyNodeRef::StmtIf(_) => NodeKind::StmtIf, AnyNodeRef::StmtWith(_) => NodeKind::StmtWith, AnyNodeRef::StmtMatch(_) => NodeKind::StmtMatch, AnyNodeRef::StmtRaise(_) => NodeKind::StmtRaise, AnyNodeRef::StmtTry(_) => NodeKind::StmtTry, AnyNodeRef::StmtAssert(_) => NodeKind::StmtAssert, AnyNodeRef::StmtImport(_) => NodeKind::StmtImport, AnyNodeRef::StmtImportFrom(_) => NodeKind::StmtImportFrom, AnyNodeRef::StmtGlobal(_) => NodeKind::StmtGlobal, AnyNodeRef::StmtNonlocal(_) => NodeKind::StmtNonlocal, AnyNodeRef::StmtExpr(_) => NodeKind::StmtExpr, AnyNodeRef::StmtPass(_) => NodeKind::StmtPass, AnyNodeRef::StmtBreak(_) => NodeKind::StmtBreak, AnyNodeRef::StmtContinue(_) => NodeKind::StmtContinue, AnyNodeRef::StmtIpyEscapeCommand(_) => NodeKind::StmtIpyEscapeCommand, AnyNodeRef::ExprBoolOp(_) => NodeKind::ExprBoolOp, AnyNodeRef::ExprNamed(_) => NodeKind::ExprNamed, AnyNodeRef::ExprBinOp(_) => NodeKind::ExprBinOp, AnyNodeRef::ExprUnaryOp(_) => NodeKind::ExprUnaryOp, AnyNodeRef::ExprLambda(_) => NodeKind::ExprLambda, AnyNodeRef::ExprIf(_) => NodeKind::ExprIf, AnyNodeRef::ExprDict(_) => NodeKind::ExprDict, AnyNodeRef::ExprSet(_) => NodeKind::ExprSet, AnyNodeRef::ExprListComp(_) => NodeKind::ExprListComp, AnyNodeRef::ExprSetComp(_) => NodeKind::ExprSetComp, AnyNodeRef::ExprDictComp(_) => NodeKind::ExprDictComp, AnyNodeRef::ExprGenerator(_) => NodeKind::ExprGenerator, AnyNodeRef::ExprAwait(_) => NodeKind::ExprAwait, AnyNodeRef::ExprYield(_) => NodeKind::ExprYield, AnyNodeRef::ExprYieldFrom(_) => NodeKind::ExprYieldFrom, AnyNodeRef::ExprCompare(_) => NodeKind::ExprCompare, AnyNodeRef::ExprCall(_) => NodeKind::ExprCall, AnyNodeRef::ExprFString(_) => NodeKind::ExprFString, AnyNodeRef::ExprTString(_) => NodeKind::ExprTString, AnyNodeRef::ExprStringLiteral(_) => NodeKind::ExprStringLiteral, AnyNodeRef::ExprBytesLiteral(_) => NodeKind::ExprBytesLiteral, AnyNodeRef::ExprNumberLiteral(_) => NodeKind::ExprNumberLiteral, AnyNodeRef::ExprBooleanLiteral(_) => NodeKind::ExprBooleanLiteral, AnyNodeRef::ExprNoneLiteral(_) => NodeKind::ExprNoneLiteral, AnyNodeRef::ExprEllipsisLiteral(_) => NodeKind::ExprEllipsisLiteral, AnyNodeRef::ExprAttribute(_) => NodeKind::ExprAttribute, AnyNodeRef::ExprSubscript(_) => NodeKind::ExprSubscript, AnyNodeRef::ExprStarred(_) => NodeKind::ExprStarred, AnyNodeRef::ExprName(_) => NodeKind::ExprName, AnyNodeRef::ExprList(_) => NodeKind::ExprList, AnyNodeRef::ExprTuple(_) => NodeKind::ExprTuple, AnyNodeRef::ExprSlice(_) => NodeKind::ExprSlice, AnyNodeRef::ExprIpyEscapeCommand(_) => NodeKind::ExprIpyEscapeCommand, AnyNodeRef::ExceptHandlerExceptHandler(_) => NodeKind::ExceptHandlerExceptHandler, AnyNodeRef::InterpolatedElement(_) => NodeKind::InterpolatedElement, AnyNodeRef::InterpolatedStringLiteralElement(_) => { NodeKind::InterpolatedStringLiteralElement } AnyNodeRef::PatternMatchValue(_) => NodeKind::PatternMatchValue, AnyNodeRef::PatternMatchSingleton(_) => NodeKind::PatternMatchSingleton, AnyNodeRef::PatternMatchSequence(_) => NodeKind::PatternMatchSequence, AnyNodeRef::PatternMatchMapping(_) => NodeKind::PatternMatchMapping, AnyNodeRef::PatternMatchClass(_) => NodeKind::PatternMatchClass, AnyNodeRef::PatternMatchStar(_) => NodeKind::PatternMatchStar, AnyNodeRef::PatternMatchAs(_) => NodeKind::PatternMatchAs, AnyNodeRef::PatternMatchOr(_) => NodeKind::PatternMatchOr, AnyNodeRef::TypeParamTypeVar(_) => NodeKind::TypeParamTypeVar, AnyNodeRef::TypeParamTypeVarTuple(_) => NodeKind::TypeParamTypeVarTuple, AnyNodeRef::TypeParamParamSpec(_) => NodeKind::TypeParamParamSpec, AnyNodeRef::InterpolatedStringFormatSpec(_) => NodeKind::InterpolatedStringFormatSpec, AnyNodeRef::PatternArguments(_) => NodeKind::PatternArguments, AnyNodeRef::PatternKeyword(_) => NodeKind::PatternKeyword, AnyNodeRef::Comprehension(_) => NodeKind::Comprehension, AnyNodeRef::Arguments(_) => NodeKind::Arguments, 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::ElifElseClause(_) => NodeKind::ElifElseClause, AnyNodeRef::TypeParams(_) => NodeKind::TypeParams, AnyNodeRef::FString(_) => NodeKind::FString, AnyNodeRef::TString(_) => NodeKind::TString, AnyNodeRef::StringLiteral(_) => NodeKind::StringLiteral, AnyNodeRef::BytesLiteral(_) => NodeKind::BytesLiteral, AnyNodeRef::Identifier(_) => NodeKind::Identifier, } } } /// See also [Module](https://docs.python.org/3/library/ast.html#ast.Module) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ModModule { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub body: thin_vec::ThinVec, } /// See also [Module](https://docs.python.org/3/library/ast.html#ast.Module) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ModExpression { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub body: Box, } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtFunctionDef { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub is_async: bool, pub decorator_list: thin_vec::ThinVec, pub name: crate::Identifier, pub type_params: Option>, pub parameters: Box, pub returns: Option>, pub body: thin_vec::ThinVec, } /// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtClassDef { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub decorator_list: thin_vec::ThinVec, pub name: crate::Identifier, pub type_params: Option>, pub arguments: Option>, pub body: thin_vec::ThinVec, } /// See also [Return](https://docs.python.org/3/library/ast.html#ast.Return) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtReturn { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Option>, } /// See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtDelete { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub targets: Vec, } /// See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtTypeAlias { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub name: Box, pub type_params: Option>, pub value: Box, } /// See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtAssign { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub targets: Vec, pub value: Box, } /// See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtAugAssign { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub target: Box, pub op: crate::Operator, pub value: Box, } /// See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtAnnAssign { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub target: Box, pub annotation: Box, pub value: Option>, pub simple: bool, } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtFor { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub is_async: bool, pub target: Box, pub iter: Box, pub body: thin_vec::ThinVec, pub orelse: thin_vec::ThinVec, } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtWhile { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub test: Box, pub body: thin_vec::ThinVec, pub orelse: thin_vec::ThinVec, } /// See also [If](https://docs.python.org/3/library/ast.html#ast.If) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtIf { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub test: Box, pub body: thin_vec::ThinVec, pub elif_else_clauses: Vec, } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtWith { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub is_async: bool, pub items: Vec, pub body: thin_vec::ThinVec, } /// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtMatch { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub subject: Box, pub cases: Vec, } /// See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtRaise { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub exc: Option>, pub cause: Option>, } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtTry { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub body: thin_vec::ThinVec, pub handlers: Vec, pub orelse: thin_vec::ThinVec, pub finalbody: thin_vec::ThinVec, pub is_star: bool, } /// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtAssert { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub test: Box, pub msg: Option>, } /// See also [Import](https://docs.python.org/3/library/ast.html#ast.Import) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtImport { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub names: Vec, pub is_lazy: bool, } /// See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtImportFrom { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub module: Option, pub names: Vec, pub level: u32, pub is_lazy: bool, } /// See also [Global](https://docs.python.org/3/library/ast.html#ast.Global) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtGlobal { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub names: Vec, } /// See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtNonlocal { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub names: Vec, } /// See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtExpr { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, } /// See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtPass { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, } /// See also [Break](https://docs.python.org/3/library/ast.html#ast.Break) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtBreak { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, } /// See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtContinue { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, } /// An AST node used to represent a IPython escape command at the statement level. /// /// For example, /// ```python /// %matplotlib inline /// ``` /// /// ## Terminology /// /// Escape commands are special IPython syntax which starts with a token to identify /// the escape kind followed by the command value itself. [Escape kind] are the kind /// of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`, /// `?`, `??`, `/`, `;`, and `,`. /// /// Help command (or Dynamic Object Introspection as it's called) are the escape commands /// of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset /// of Help command where the token can be at the end of the line i.e., after the value. /// For example, `str.replace?`. /// /// Here's where things get tricky. I'll divide the help end command into two types for /// better understanding: /// 1. Strict version: The token is _only_ at the end of the line. For example, /// `str.replace?` or `str.replace??`. /// 2. Combined version: Along with the `?` or `??` token, which are at the end of the /// line, there are other escape kind tokens that are present at the start as well. /// For example, `%matplotlib?` or `%%timeit?`. /// /// Priority comes into picture for the "Combined version" mentioned above. How do /// we determine the escape kind if there are tokens on both side of the value, i.e., which /// token to choose? The Help end command always takes priority over any other token which /// means that if there is `?`/`??` at the end then that is used to determine the kind. /// For example, in `%matplotlib?` the escape kind is determined using the `?` token /// instead of `%` token. /// /// ## Syntax /// /// `` /// /// The simplest form is an escape kind token followed by the command value. For example, /// `%matplotlib inline`, `/foo`, `!pwd`, etc. /// /// `` /// /// The help end escape command would be the reverse of the above syntax. Here, the /// escape kind token can only be either `?` or `??` and it is at the end of the line. /// For example, `str.replace?`, `math.pi??`, etc. /// /// `` /// /// The final syntax is the combined version of the above two. For example, `%matplotlib?`, /// `%%timeit??`, etc. /// /// [Escape kind]: crate::IpyEscapeKind /// #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StmtIpyEscapeCommand { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub kind: crate::IpyEscapeKind, pub value: Box, } /// See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprBoolOp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub op: crate::BoolOp, pub values: Vec, } /// See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprNamed { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub target: Box, pub value: Box, } /// See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprBinOp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub left: Box, pub op: crate::Operator, pub right: Box, } /// See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprUnaryOp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub op: crate::UnaryOp, pub operand: Box, } /// See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprLambda { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub parameters: Option>, pub body: Box, } /// See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprIf { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub test: Box, pub body: Box, pub orelse: Box, } /// See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprDict { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub items: Vec, } /// See also [Set](https://docs.python.org/3/library/ast.html#ast.Set) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprSet { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elts: Vec, } /// See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprListComp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elt: Box, pub generators: Vec, } /// See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprSetComp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elt: Box, pub generators: Vec, } /// See also [DictComp](https://docs.python.org/3/library/ast.html#ast.DictComp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprDictComp { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub key: Option>, pub value: Box, pub generators: Vec, } /// See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.GeneratorExp) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprGenerator { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elt: Box, pub generators: Vec, pub parenthesized: bool, } /// See also [Await](https://docs.python.org/3/library/ast.html#ast.Await) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprAwait { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, } /// See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprYield { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Option>, } /// See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprYieldFrom { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, } /// See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprCompare { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub left: Box, pub ops: Box<[crate::CmpOp]>, pub comparators: Box<[Expr]>, } /// A call expression whose end offset is derived from its arguments. /// /// The parser and error-recovery code must ensure that the call and its arguments /// end at the same offset. /// /// See also [Call](https://docs.python.org/3/library/ast.html#ast.Call) #[derive(Clone, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprCall { pub node_index: crate::AtomicNodeIndex, pub range_start: ruff_text_size::TextSize, pub func: Box, pub arguments: crate::Arguments, } /// An AST node that represents either a single-part f-string literal /// or an implicitly concatenated f-string literal. /// /// This type differs from the original Python AST `JoinedStr` in that it /// doesn't join the implicitly concatenated parts into a single string. Instead, /// it keeps them separate and provide various methods to access the parts. /// /// See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprFString { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::FStringValue, } /// An AST node that represents either a single-part t-string literal /// or an implicitly concatenated t-string literal. /// /// This type differs from the original Python AST `TemplateStr` in that it /// doesn't join the implicitly concatenated parts into a single string. Instead, /// it keeps them separate and provide various methods to access the parts. /// /// See also [TemplateStr](https://docs.python.org/3/library/ast.html#ast.TemplateStr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprTString { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::TStringValue, } /// An AST node that represents either a single-part string literal /// or an implicitly concatenated string literal. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprStringLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::StringLiteralValue, } /// An AST node that represents either a single-part bytestring literal /// or an implicitly concatenated bytestring literal. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprBytesLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::BytesLiteralValue, } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprNumberLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::Number, } #[derive(Clone, Debug, PartialEq, Default)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprBooleanLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: bool, } #[derive(Clone, Debug, PartialEq, Default)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprNoneLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, } #[derive(Clone, Debug, PartialEq, Default)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprEllipsisLiteral { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, } /// See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attribute) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprAttribute { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, pub attr: crate::Identifier, pub ctx: crate::ExprContext, } /// See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subscript) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprSubscript { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, pub slice: Box, pub ctx: crate::ExprContext, } /// See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprStarred { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, pub ctx: crate::ExprContext, } /// See also [Name](https://docs.python.org/3/library/ast.html#ast.Name) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprName { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub id: Name, pub ctx: crate::ExprContext, } /// See also [List](https://docs.python.org/3/library/ast.html#ast.List) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprList { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elts: Vec, pub ctx: crate::ExprContext, } /// See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprTuple { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub elts: Vec, pub ctx: crate::ExprContext, pub parenthesized: bool, } /// See also [Slice](https://docs.python.org/3/library/ast.html#ast.Slice) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprSlice { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub lower: Option>, pub upper: Option>, pub step: Option>, } /// An AST node used to represent a IPython escape command at the expression level. /// /// For example, /// ```python /// dir = !pwd /// ``` /// /// Here, the escape kind can only be `!` or `%` otherwise it is a syntax error. /// /// For more information related to terminology and syntax of escape commands, /// see [`StmtIpyEscapeCommand`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExprIpyEscapeCommand { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub kind: crate::IpyEscapeKind, pub value: Box, } /// See also [MatchValue](https://docs.python.org/3/library/ast.html#ast.MatchValue) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchValue { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: Box, } /// See also [MatchSingleton](https://docs.python.org/3/library/ast.html#ast.MatchSingleton) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchSingleton { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub value: crate::Singleton, } /// See also [MatchSequence](https://docs.python.org/3/library/ast.html#ast.MatchSequence) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchSequence { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub patterns: Vec, } /// See also [MatchMapping](https://docs.python.org/3/library/ast.html#ast.MatchMapping) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchMapping { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub keys: thin_vec::ThinVec, pub patterns: thin_vec::ThinVec, pub rest: Option, } /// See also [MatchClass](https://docs.python.org/3/library/ast.html#ast.MatchClass) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchClass { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub cls: Box, pub arguments: crate::PatternArguments, } /// See also [MatchStar](https://docs.python.org/3/library/ast.html#ast.MatchStar) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchStar { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub name: Option, } /// See also [MatchAs](https://docs.python.org/3/library/ast.html#ast.MatchAs) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchAs { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub pattern: Option>, pub name: Option, } /// See also [MatchOr](https://docs.python.org/3/library/ast.html#ast.MatchOr) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternMatchOr { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub patterns: Vec, } /// See also [TypeVar](https://docs.python.org/3/library/ast.html#ast.TypeVar) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TypeParamTypeVar { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub name: crate::Identifier, pub bound: Option>, pub default: Option>, } /// See also [TypeVarTuple](https://docs.python.org/3/library/ast.html#ast.TypeVarTuple) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TypeParamTypeVarTuple { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub name: crate::Identifier, pub default: Option>, } /// See also [ParamSpec](https://docs.python.org/3/library/ast.html#ast.ParamSpec) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TypeParamParamSpec { pub node_index: crate::AtomicNodeIndex, pub range: ruff_text_size::TextRange, pub name: crate::Identifier, pub default: Option>, } impl ModModule { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ModModule { body, range: _, node_index: _, } = self; visitor.visit_body(body); } } impl ModExpression { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ModExpression { body, range: _, node_index: _, } = self; visitor.visit_expr(body); } } impl StmtFunctionDef { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtFunctionDef { is_async: _, decorator_list, name, type_params, parameters, returns, body, range: _, node_index: _, } = self; for elm in decorator_list { visitor.visit_decorator(elm); } visitor.visit_identifier(name); if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_parameters(parameters); if let Some(returns) = returns { visitor.visit_annotation(returns); } visitor.visit_body(body); } } impl StmtClassDef { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtClassDef { decorator_list, name, type_params, arguments, body, range: _, node_index: _, } = self; for elm in decorator_list { visitor.visit_decorator(elm); } visitor.visit_identifier(name); 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 StmtReturn { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtReturn { value, range: _, node_index: _, } = self; if let Some(value) = value { visitor.visit_expr(value); } } } impl StmtDelete { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtDelete { targets, range: _, node_index: _, } = self; for elm in targets { visitor.visit_expr(elm); } } } impl StmtTypeAlias { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtTypeAlias { name, type_params, value, range: _, node_index: _, } = self; visitor.visit_expr(name); if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_expr(value); } } impl StmtAssign { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtAssign { targets, value, range: _, node_index: _, } = self; for elm in targets { visitor.visit_expr(elm); } visitor.visit_expr(value); } } impl StmtAugAssign { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtAugAssign { target, op, value, range: _, node_index: _, } = self; visitor.visit_expr(target); visitor.visit_operator(op); visitor.visit_expr(value); } } impl StmtAnnAssign { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtAnnAssign { target, annotation, value, simple: _, range: _, node_index: _, } = self; visitor.visit_expr(target); visitor.visit_annotation(annotation); if let Some(value) = value { visitor.visit_expr(value); } } } impl StmtFor { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtFor { is_async: _, target, iter, body, orelse, range: _, node_index: _, } = self; visitor.visit_expr(target); visitor.visit_expr(iter); visitor.visit_body(body); visitor.visit_body(orelse); } } impl StmtWhile { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtWhile { test, body, orelse, range: _, node_index: _, } = self; visitor.visit_expr(test); visitor.visit_body(body); visitor.visit_body(orelse); } } impl StmtIf { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtIf { test, body, elif_else_clauses, range: _, node_index: _, } = self; visitor.visit_expr(test); visitor.visit_body(body); for elm in elif_else_clauses { visitor.visit_elif_else_clause(elm); } } } impl StmtWith { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtWith { is_async: _, items, body, range: _, node_index: _, } = self; for elm in items { visitor.visit_with_item(elm); } visitor.visit_body(body); } } impl StmtMatch { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtMatch { subject, cases, range: _, node_index: _, } = self; visitor.visit_expr(subject); for elm in cases { visitor.visit_match_case(elm); } } } impl StmtRaise { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtRaise { exc, cause, range: _, node_index: _, } = self; if let Some(exc) = exc { visitor.visit_expr(exc); } if let Some(cause) = cause { visitor.visit_expr(cause); } } } impl StmtTry { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtTry { body, handlers, orelse, finalbody, is_star: _, range: _, node_index: _, } = self; visitor.visit_body(body); for elm in handlers { visitor.visit_except_handler(elm); } visitor.visit_body(orelse); visitor.visit_body(finalbody); } } impl StmtAssert { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtAssert { test, msg, range: _, node_index: _, } = self; visitor.visit_expr(test); if let Some(msg) = msg { visitor.visit_expr(msg); } } } impl StmtImport { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtImport { names, is_lazy: _, range: _, node_index: _, } = self; for elm in names { visitor.visit_alias(elm); } } } impl StmtImportFrom { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtImportFrom { module, names, level: _, is_lazy: _, range: _, node_index: _, } = self; if let Some(module) = module { visitor.visit_identifier(module); } for elm in names { visitor.visit_alias(elm); } } } impl StmtGlobal { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtGlobal { names, range: _, node_index: _, } = self; for elm in names { visitor.visit_identifier(elm); } } } impl StmtNonlocal { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtNonlocal { names, range: _, node_index: _, } = self; for elm in names { visitor.visit_identifier(elm); } } } impl StmtExpr { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtExpr { value, range: _, node_index: _, } = self; visitor.visit_expr(value); } } impl StmtPass { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtPass { range: _, node_index: _, } = self; } } impl StmtBreak { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtBreak { range: _, node_index: _, } = self; } } impl StmtContinue { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtContinue { range: _, node_index: _, } = self; } } impl StmtIpyEscapeCommand { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let StmtIpyEscapeCommand { kind: _, value: _, range: _, node_index: _, } = self; } } impl ExprNamed { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprNamed { target, value, range: _, node_index: _, } = self; visitor.visit_expr(target); visitor.visit_expr(value); } } impl ExprBinOp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprBinOp { left, op, right, range: _, node_index: _, } = self; visitor.visit_expr(left); visitor.visit_operator(op); visitor.visit_expr(right); } } impl ExprUnaryOp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprUnaryOp { op, operand, range: _, node_index: _, } = self; visitor.visit_unary_op(op); visitor.visit_expr(operand); } } impl ExprLambda { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprLambda { parameters, body, range: _, node_index: _, } = self; if let Some(parameters) = parameters { visitor.visit_parameters(parameters); } visitor.visit_expr(body); } } impl ExprIf { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprIf { test, body, orelse, range: _, node_index: _, } = self; visitor.visit_expr(body); visitor.visit_expr(test); visitor.visit_expr(orelse); } } impl ExprSet { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprSet { elts, range: _, node_index: _, } = self; for elm in elts { visitor.visit_expr(elm); } } } impl ExprListComp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprListComp { elt, generators, range: _, node_index: _, } = self; visitor.visit_expr(elt); for elm in generators { visitor.visit_comprehension(elm); } } } impl ExprSetComp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprSetComp { elt, generators, range: _, node_index: _, } = self; visitor.visit_expr(elt); for elm in generators { visitor.visit_comprehension(elm); } } } impl ExprDictComp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprDictComp { key, value, generators, range: _, node_index: _, } = self; if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); for elm in generators { visitor.visit_comprehension(elm); } } } impl ExprGenerator { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprGenerator { elt, generators, parenthesized: _, range: _, node_index: _, } = self; visitor.visit_expr(elt); for elm in generators { visitor.visit_comprehension(elm); } } } impl ExprAwait { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprAwait { value, range: _, node_index: _, } = self; visitor.visit_expr(value); } } impl ExprYield { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprYield { value, range: _, node_index: _, } = self; if let Some(value) = value { visitor.visit_expr(value); } } } impl ExprYieldFrom { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprYieldFrom { value, range: _, node_index: _, } = self; visitor.visit_expr(value); } } impl ExprCall { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprCall { range_start: _, func, arguments, node_index: _, } = self; visitor.visit_expr(func); visitor.visit_arguments(arguments); } } impl ExprNumberLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprNumberLiteral { value: _, range: _, node_index: _, } = self; } } impl ExprBooleanLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprBooleanLiteral { value: _, range: _, node_index: _, } = self; } } impl ExprNoneLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprNoneLiteral { range: _, node_index: _, } = self; } } impl ExprEllipsisLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprEllipsisLiteral { range: _, node_index: _, } = self; } } impl ExprAttribute { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprAttribute { value, attr, ctx: _, range: _, node_index: _, } = self; visitor.visit_expr(value); visitor.visit_identifier(attr); } } impl ExprSubscript { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprSubscript { value, slice, ctx: _, range: _, node_index: _, } = self; visitor.visit_expr(value); visitor.visit_expr(slice); } } impl ExprStarred { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprStarred { value, ctx: _, range: _, node_index: _, } = self; visitor.visit_expr(value); } } impl ExprName { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprName { id: _, ctx: _, range: _, node_index: _, } = self; } } impl ExprList { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprList { elts, ctx: _, range: _, node_index: _, } = self; for elm in elts { visitor.visit_expr(elm); } } } impl ExprTuple { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprTuple { elts, ctx: _, parenthesized: _, range: _, node_index: _, } = self; for elm in elts { visitor.visit_expr(elm); } } } impl ExprSlice { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprSlice { lower, upper, step, range: _, node_index: _, } = self; if let Some(lower) = lower { visitor.visit_expr(lower); } if let Some(upper) = upper { visitor.visit_expr(upper); } if let Some(step) = step { visitor.visit_expr(step); } } } impl ExprIpyEscapeCommand { pub(crate) fn visit_source_order<'a, V>(&'a self, _: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ExprIpyEscapeCommand { kind: _, value: _, range: _, node_index: _, } = self; } } impl PatternMatchValue { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchValue { value, range: _, node_index: _, } = self; visitor.visit_expr(value); } } impl PatternMatchSingleton { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchSingleton { value, range: _, node_index: _, } = self; visitor.visit_singleton(value); } } impl PatternMatchSequence { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchSequence { patterns, range: _, node_index: _, } = self; for elm in patterns { visitor.visit_pattern(elm); } } } impl PatternMatchClass { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchClass { cls, arguments, range: _, node_index: _, } = self; visitor.visit_expr(cls); visitor.visit_pattern_arguments(arguments); } } impl PatternMatchStar { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchStar { name, range: _, node_index: _, } = self; if let Some(name) = name { visitor.visit_identifier(name); } } } impl PatternMatchAs { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchAs { pattern, name, range: _, node_index: _, } = self; if let Some(pattern) = pattern { visitor.visit_pattern(pattern); } if let Some(name) = name { visitor.visit_identifier(name); } } } impl PatternMatchOr { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternMatchOr { patterns, range: _, node_index: _, } = self; for elm in patterns { visitor.visit_pattern(elm); } } } impl TypeParamTypeVar { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let TypeParamTypeVar { name, bound, default, range: _, node_index: _, } = self; visitor.visit_identifier(name); if let Some(bound) = bound { visitor.visit_expr(bound); } if let Some(default) = default { visitor.visit_expr(default); } } } impl TypeParamTypeVarTuple { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let TypeParamTypeVarTuple { name, default, range: _, node_index: _, } = self; visitor.visit_identifier(name); if let Some(default) = default { visitor.visit_expr(default); } } } impl TypeParamParamSpec { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let TypeParamParamSpec { name, default, range: _, node_index: _, } = self; visitor.visit_identifier(name); if let Some(default) = default { visitor.visit_expr(default); } } } ast_serialize-0.13.1/crates/ruff_python_ast/src/helpers.rs000064400000000000000000002174131046102023000206460ustar00use std::borrow::Cow; use std::path::Path; use rustc_hash::FxHashMap; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer, indentation_at_offset}; use ruff_source_file::LineRanges; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use crate::name::{Name, QualifiedName, QualifiedNameBuilder}; use crate::statement_visitor::StatementVisitor; use crate::token::Tokens; use crate::token::parenthesized_range; use crate::visitor::Visitor; use crate::{ self as ast, Arguments, AtomicNodeIndex, CmpOp, DictItem, ExceptHandler, Expr, ExprNoneLiteral, InterpolatedStringElement, MatchCase, Operator, Pattern, Stmt, TypeParam, }; use crate::{AnyNodeRef, ExprContext}; /// 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::ClassDef(_) | Stmt::While(_) | Stmt::For(_) | Stmt::Match(_) | Stmt::With(_) | Stmt::If(_) | Stmt::Try(_) ) } fn is_iterable_initializer(id: &str, is_builtin: F) -> bool where F: Fn(&str) -> bool, { matches!(id, "list" | "tuple" | "set" | "dict" | "frozenset") && is_builtin(id) } /// Whether an expression has no side effects, may have side effects, /// or is assumed to have side effects. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SideEffect { /// The expression is definitely side-effect-free. Absent, /// The expression may have side effects (e.g., f-string interpolation /// may invoke `__format__` or `__str__`). Possible, /// The expression is assumed to have side effects. Present, } impl SideEffect { pub const fn is_present(self) -> bool { matches!(self, Self::Present) } pub const fn is_absent(self) -> bool { matches!(self, Self::Absent) } #[must_use] pub const fn merge(self, other: Self) -> Self { match (self, other) { (Self::Present, _) | (_, Self::Present) => Self::Present, (Self::Possible, _) | (_, Self::Possible) => Self::Possible, _ => Self::Absent, } } /// Classify a single expression node's side effect. fn from_expr(expr: &Expr, is_builtin: &dyn Fn(&str) -> bool) -> Self { match expr { // Empty initializers for known builtins are side-effect-free. Expr::Call(ast::ExprCall { func, arguments, .. }) if arguments.is_empty() => { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if is_iterable_initializer(id.as_str(), |id| is_builtin(id)) { return Self::Absent; } } Self::Present } // Overloaded operators: only side-effect-free if both sides are literals. Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { if is_known_safe_binop_operand(left) && is_known_safe_binop_operand(right) { Self::Absent } else { Self::Present } } // Non-literal f-string interpolation may invoke `__format__`/`__str__`. Expr::FString(ast::ExprFString { value, .. }) => { if value.elements().any(has_uncertain_interpolation) { Self::Possible } else { Self::Absent } } Expr::TString(ast::ExprTString { value, .. }) => { if value.elements().any(has_uncertain_interpolation) { Self::Possible } else { Self::Absent } } // Named expressions (walrus operator) are assignments. Expr::Named(_) => Self::Present, // Complex expressions that are assumed to have side effects. Expr::Await(_) | Expr::Call(_) | Expr::DictComp(_) | Expr::Generator(_) | Expr::ListComp(_) | Expr::SetComp(_) | Expr::Subscript(_) | Expr::Yield(_) | Expr::YieldFrom(_) | Expr::IpyEscapeCommand(_) => Self::Present, // Side-effect-free expressions — continue walking child nodes. Expr::BoolOp(_) | Expr::Compare(_) | Expr::Dict(_) | Expr::If(_) | Expr::Lambda(_) | Expr::List(_) | Expr::Set(_) | Expr::Slice(_) | Expr::Starred(_) | Expr::Tuple(_) | Expr::UnaryOp(_) | Expr::Attribute(_) | Expr::Name(_) | Expr::StringLiteral(_) | Expr::BytesLiteral(_) | Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) => Self::Absent, } } } const fn is_known_safe_binop_operand(expr: &Expr) -> bool { match expr { Expr::StringLiteral(_) | Expr::BytesLiteral(_) | Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) | Expr::FString(_) | Expr::List(_) | Expr::Tuple(_) | Expr::Set(_) | Expr::Dict(_) | Expr::ListComp(_) | Expr::SetComp(_) | Expr::DictComp(_) => true, Expr::BoolOp(_) | Expr::Named(_) | Expr::BinOp(_) | Expr::UnaryOp(_) | Expr::Lambda(_) | Expr::If(_) | Expr::Compare(_) | Expr::Call(_) | Expr::Generator(_) | Expr::Await(_) | Expr::Yield(_) | Expr::YieldFrom(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Starred(_) | Expr::Name(_) | Expr::Slice(_) | Expr::IpyEscapeCommand(_) | Expr::TString(_) => false, } } fn is_definitely_side_effect_free_interpolation_expr(expr: &Expr) -> bool { matches!( expr, Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) | Expr::StringLiteral(_) | Expr::BytesLiteral(_) ) } fn has_uncertain_interpolation(element: &InterpolatedStringElement) -> bool { match element { InterpolatedStringElement::Literal(_) => false, InterpolatedStringElement::Interpolation(interp) => { !is_definitely_side_effect_free_interpolation_expr(&interp.expression) || interp .format_spec .as_ref() .is_some_and(|spec| spec.elements.iter().any(has_uncertain_interpolation)) } } } /// Return `true` if the `Expr` contains an expression that appears to include a /// side-effect (like a function call). /// /// Accepts a closure that determines whether a given name (e.g., `"list"`) is a Python builtin. pub fn contains_effect(expr: &Expr, is_builtin: F) -> bool where F: Fn(&str) -> bool, { side_effect(expr, is_builtin).is_present() } /// Return whether `expr` has no side effects, maybe has side effects, or definitely /// has side effects. /// /// Unlike [`contains_effect`], which returns a simple `bool`, this function distinguishes /// between expressions that are definitely side-effect-free, definitely side-effectful, /// and those that may invoke user-defined code (e.g., formatting a non-literal f-string /// interpolation can call `__format__` or `__str__`). pub fn side_effect(expr: &Expr, is_builtin: F) -> SideEffect where F: Fn(&str) -> bool, { let mut effect = SideEffect::Absent; any_over_expr(expr, |expr| { match SideEffect::from_expr(expr, &is_builtin) { SideEffect::Present => { effect = SideEffect::Present; true } SideEffect::Possible => { effect = effect.merge(SideEffect::Possible); false } SideEffect::Absent => false, } }); effect } /// Call `func` over every `Expr` in `expr`, returning `true` if any expression /// returns `true`.. pub fn any_over_expr(expr: &Expr, mut func: F) -> bool where F: FnMut(&Expr) -> bool, { fn inner(expr: &Expr, func: &mut dyn FnMut(&Expr) -> bool) -> bool { if func(expr) { return true; } match expr { Expr::BoolOp(ast::ExprBoolOp { values, .. }) => { values.iter().any(|expr| any_over_expr(expr, &mut *func)) } Expr::FString(ast::ExprFString { value, .. }) => value .elements() .any(|expr| any_over_interpolated_string_element(expr, &mut *func)), Expr::TString(ast::ExprTString { value, .. }) => value .elements() .any(|expr| any_over_interpolated_string_element(expr, &mut *func)), Expr::Named(ast::ExprNamed { target, value, range: _, node_index: _, }) => any_over_expr(target, &mut *func) || any_over_expr(value, &mut *func), Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { any_over_expr(left, &mut *func) || any_over_expr(right, &mut *func) } Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => any_over_expr(operand, func), Expr::Lambda(ast::ExprLambda { body, .. }) => any_over_expr(body, func), Expr::If(ast::ExprIf { test, body, orelse, range: _, node_index: _, }) => { any_over_expr(test, &mut *func) || any_over_expr(body, &mut *func) || any_over_expr(orelse, &mut *func) } Expr::Dict(ast::ExprDict { items, range: _, node_index: _, }) => items.iter().any(|ast::DictItem { key, value }| { any_over_expr(value, &mut *func) || key .as_ref() .is_some_and(|key| any_over_expr(key, &mut *func)) }), Expr::Set(ast::ExprSet { elts, range: _, node_index: _, }) | Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) => { elts.iter().any(|expr| any_over_expr(expr, &mut *func)) } Expr::ListComp(ast::ExprListComp { elt, generators, range: _, node_index: _, }) | Expr::SetComp(ast::ExprSetComp { elt, generators, range: _, node_index: _, }) | Expr::Generator(ast::ExprGenerator { elt, generators, range: _, node_index: _, parenthesized: _, }) => { any_over_expr(elt, &mut *func) || generators.iter().any(|generator| { any_over_expr(&generator.target, &mut *func) || any_over_expr(&generator.iter, &mut *func) || generator .ifs .iter() .any(|expr| any_over_expr(expr, &mut *func)) }) } Expr::DictComp(ast::ExprDictComp { key, value, generators, range: _, node_index: _, }) => { key.as_deref() .is_some_and(|key| any_over_expr(key, &mut *func)) || any_over_expr(value, &mut *func) || generators.iter().any(|generator| { any_over_expr(&generator.target, &mut *func) || any_over_expr(&generator.iter, &mut *func) || generator .ifs .iter() .any(|expr| any_over_expr(expr, &mut *func)) }) } Expr::Await(ast::ExprAwait { value, range: _, node_index: _, }) | Expr::YieldFrom(ast::ExprYieldFrom { value, range: _, node_index: _, }) | Expr::Attribute(ast::ExprAttribute { value, .. }) | Expr::Starred(ast::ExprStarred { value, .. }) => any_over_expr(value, func), Expr::Yield(ast::ExprYield { value, range: _, node_index: _, }) => value .as_ref() .is_some_and(|value| any_over_expr(value, func)), Expr::Compare(ast::ExprCompare { left, comparators, .. }) => { any_over_expr(left, &mut *func) || comparators .iter() .any(|expr| any_over_expr(expr, &mut *func)) } Expr::Call(ast::ExprCall { func: call_func, arguments, range_start: _, node_index: _, }) => { // Note that this is the evaluation order but not necessarily the declaration order // (e.g. for `f(*args, a=2, *args2, **kwargs)` it's not) any_over_expr(call_func, &mut *func) || arguments .args .iter() .any(|expr| any_over_expr(expr, &mut *func)) || arguments .keywords .iter() .any(|keyword| any_over_expr(&keyword.value, &mut *func)) } Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { any_over_expr(value, &mut *func) || any_over_expr(slice, &mut *func) } Expr::Slice(ast::ExprSlice { lower, upper, step, range: _, node_index: _, }) => { lower .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) || upper .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) || step .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) } Expr::Name(_) | Expr::StringLiteral(_) | Expr::BytesLiteral(_) | Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) | Expr::IpyEscapeCommand(_) => false, } } inner(expr, &mut func) } fn any_over_type_param(type_param: &TypeParam, func: &mut dyn FnMut(&Expr) -> bool) -> bool { match type_param { TypeParam::TypeVar(ast::TypeParamTypeVar { bound, default, .. }) => { bound .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) || default .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) } TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) => default .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)), TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => default .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)), } } fn any_over_pattern(pattern: &Pattern, func: &mut dyn FnMut(&Expr) -> bool) -> bool { match pattern { Pattern::MatchValue(ast::PatternMatchValue { value, range: _, node_index: _, }) => any_over_expr(value, func), Pattern::MatchSingleton(_) => false, Pattern::MatchSequence(ast::PatternMatchSequence { patterns, range: _, node_index: _, }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, &mut *func)), Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { keys.iter().any(|key| any_over_expr(key, &mut *func)) || patterns .iter() .any(|pattern| any_over_pattern(pattern, &mut *func)) } Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => { any_over_expr(cls, &mut *func) || arguments .patterns .iter() .any(|pattern| any_over_pattern(pattern, &mut *func)) || arguments .keywords .iter() .any(|keyword| any_over_pattern(&keyword.pattern, &mut *func)) } Pattern::MatchStar(_) => false, Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => pattern .as_ref() .is_some_and(|pattern| any_over_pattern(pattern, func)), Pattern::MatchOr(ast::PatternMatchOr { patterns, range: _, node_index: _, }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, &mut *func)), } } fn any_over_interpolated_string_element( element: &ast::InterpolatedStringElement, func: &mut dyn FnMut(&Expr) -> bool, ) -> bool { match element { ast::InterpolatedStringElement::Literal(_) => false, ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement { expression, format_spec, .. }) => { any_over_expr(expression, &mut *func) || format_spec.as_ref().is_some_and(|spec| { spec.elements.iter().any(|spec_element| { any_over_interpolated_string_element(spec_element, &mut *func) }) }) } } } fn any_over_stmt(stmt: &Stmt, mut func: F) -> bool where F: FnMut(&Expr) -> bool, { fn inner(stmt: &Stmt, func: &mut dyn FnMut(&Expr) -> bool) -> bool { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { parameters, type_params, body, decorator_list, returns, .. }) => { parameters.iter().any(|param| { param .default() .is_some_and(|default| any_over_expr(default, &mut *func)) || param .annotation() .is_some_and(|annotation| any_over_expr(annotation, &mut *func)) }) || type_params.as_ref().is_some_and(|type_params| { type_params .iter() .any(|type_param| any_over_type_param(type_param, &mut *func)) }) || body.iter().any(|stmt| any_over_stmt(stmt, &mut *func)) || decorator_list .iter() .any(|decorator| any_over_expr(&decorator.expression, &mut *func)) || returns .as_ref() .is_some_and(|value| any_over_expr(value, func)) } Stmt::ClassDef(ast::StmtClassDef { arguments, type_params, body, decorator_list, .. }) => { // Note that e.g. `class A(*args, a=2, *args2, **kwargs): pass` is a valid class // definition arguments .as_deref() .is_some_and(|Arguments { args, keywords, .. }| { args.iter().any(|expr| any_over_expr(expr, &mut *func)) || keywords .iter() .any(|keyword| any_over_expr(&keyword.value, &mut *func)) }) || type_params.as_ref().is_some_and(|type_params| { type_params .iter() .any(|type_param| any_over_type_param(type_param, &mut *func)) }) || body.iter().any(|stmt| any_over_stmt(stmt, &mut *func)) || decorator_list .iter() .any(|decorator| any_over_expr(&decorator.expression, &mut *func)) } Stmt::Return(ast::StmtReturn { value, range: _, node_index: _, }) => value .as_ref() .is_some_and(|value| any_over_expr(value, func)), Stmt::Delete(ast::StmtDelete { targets, range: _, node_index: _, }) => targets.iter().any(|expr| any_over_expr(expr, &mut *func)), Stmt::TypeAlias(ast::StmtTypeAlias { name, type_params, value, .. }) => { any_over_expr(name, &mut *func) || type_params.as_ref().is_some_and(|type_params| { type_params .iter() .any(|type_param| any_over_type_param(type_param, &mut *func)) }) || any_over_expr(value, func) } Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { targets.iter().any(|expr| any_over_expr(expr, &mut *func)) || any_over_expr(value, func) } Stmt::AugAssign(ast::StmtAugAssign { target, value, .. }) => { any_over_expr(target, &mut *func) || any_over_expr(value, &mut *func) } Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, .. }) => { any_over_expr(target, &mut *func) || any_over_expr(annotation, &mut *func) || value .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) } Stmt::For(ast::StmtFor { target, iter, body, orelse, .. }) => { any_over_expr(target, &mut *func) || any_over_expr(iter, &mut *func) || any_over_body(body, &mut *func) || any_over_body(orelse, &mut *func) } Stmt::While(ast::StmtWhile { test, body, orelse, range: _, node_index: _, }) => { any_over_expr(test, &mut *func) || any_over_body(body, &mut *func) || any_over_body(orelse, &mut *func) } Stmt::If(ast::StmtIf { test, body, elif_else_clauses, range: _, node_index: _, }) => { any_over_expr(test, &mut *func) || any_over_body(body, &mut *func) || elif_else_clauses.iter().any(|clause| { clause .test .as_ref() .is_some_and(|test| any_over_expr(test, &mut *func)) || any_over_body(&clause.body, &mut *func) }) } Stmt::With(ast::StmtWith { items, body, .. }) => { items.iter().any(|with_item| { any_over_expr(&with_item.context_expr, &mut *func) || with_item .optional_vars .as_ref() .is_some_and(|expr| any_over_expr(expr, &mut *func)) }) || any_over_body(body, &mut *func) } Stmt::Raise(ast::StmtRaise { exc, cause, range: _, node_index: _, }) => { exc.as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) || cause .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) } Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, is_star: _, range: _, node_index: _, }) => { any_over_body(body, &mut *func) || handlers.iter().any(|handler| { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) = handler; type_ .as_ref() .is_some_and(|expr| any_over_expr(expr, &mut *func)) || any_over_body(body, &mut *func) }) || any_over_body(orelse, &mut *func) || any_over_body(finalbody, &mut *func) } Stmt::Assert(ast::StmtAssert { test, msg, range: _, node_index: _, }) => { any_over_expr(test, &mut *func) || msg .as_ref() .is_some_and(|value| any_over_expr(value, &mut *func)) } Stmt::Match(ast::StmtMatch { subject, cases, range: _, node_index: _, }) => { any_over_expr(subject, &mut *func) || cases.iter().any(|case| { let MatchCase { pattern, guard, body, range: _, node_index: _, } = case; any_over_pattern(pattern, &mut *func) || guard .as_ref() .is_some_and(|expr| any_over_expr(expr, &mut *func)) || any_over_body(body, &mut *func) }) } Stmt::Import(_) => false, Stmt::ImportFrom(_) => false, Stmt::Global(_) => false, Stmt::Nonlocal(_) => false, Stmt::Expr(ast::StmtExpr { value, range: _, node_index: _, }) => any_over_expr(value, func), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => false, Stmt::IpyEscapeCommand(_) => false, } } inner(stmt, &mut func) } pub fn any_over_body(body: &[Stmt], mut func: F) -> bool where F: FnMut(&Expr) -> bool, { body.iter().any(|stmt| any_over_stmt(stmt, &mut func)) } pub fn is_dunder(id: &str) -> bool { id.starts_with("__") && id.ends_with("__") } /// Whether a name starts and ends with a single underscore. /// /// `_a__` is considered neither a dunder nor a sunder name. pub fn is_sunder(id: &str) -> bool { id.starts_with('_') && id.ends_with('_') && !id.starts_with("__") && !id.ends_with("__") } /// Return `true` if the [`Stmt`] is an assignment to a dunder (like `__all__`). pub fn is_assignment_to_a_dunder(stmt: &Stmt) -> bool { // Check whether it's an assignment to a dunder, with or without a type // annotation. This is what pycodestyle (as of 2.9.1) does. match stmt { Stmt::Assign(ast::StmtAssign { targets, .. }) => { if let [Expr::Name(ast::ExprName { id, .. })] = targets.as_slice() { is_dunder(id) } else { false } } Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => { if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { is_dunder(id) } else { false } } _ => false, } } /// Return `true` if the [`Expr`] is a singleton (`None`, `True`, `False`, or /// `...`). const fn is_singleton(expr: &Expr) -> bool { matches!( expr, Expr::NoneLiteral(_) | Expr::BooleanLiteral(_) | Expr::EllipsisLiteral(_) ) } /// Return `true` if the [`Expr`] is a literal or tuple of literals. pub fn is_constant(expr: &Expr) -> bool { if let Expr::Tuple(tuple) = expr { tuple.iter().all(is_constant) } else { expr.is_literal_expr() } } /// Return `true` if the [`Expr`] is a non-singleton constant. pub fn is_constant_non_singleton(expr: &Expr) -> bool { is_constant(expr) && !is_singleton(expr) } /// Return `true` if an [`Expr`] is a literal `True`. pub const fn is_const_true(expr: &Expr) -> bool { matches!( expr, Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: true, .. }), ) } /// Return `true` if an [`Expr`] is a literal `False`. pub const fn is_const_false(expr: &Expr) -> bool { matches!( expr, Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: false, .. }), ) } /// Return `true` if the [`Expr`] is a mutable iterable initializer, like `{}` or `[]`. pub const fn is_mutable_iterable_initializer(expr: &Expr) -> bool { matches!( expr, Expr::Set(_) | Expr::SetComp(_) | Expr::List(_) | Expr::ListComp(_) | Expr::Dict(_) | Expr::DictComp(_) ) } /// Extract the names of all handled exceptions. pub fn extract_handled_exceptions(handlers: &[ExceptHandler]) -> Vec<&Expr> { let mut handled_exceptions = Vec::new(); for handler in handlers { match handler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) => { if let Some(type_) = type_ { if let Expr::Tuple(tuple) = &**type_ { for type_ in tuple { handled_exceptions.push(type_); } } else { handled_exceptions.push(type_); } } } } } handled_exceptions } /// 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. pub fn map_callable(decorator: &Expr) -> &Expr { if let Expr::Call(ast::ExprCall { func, .. }) = decorator { // Ex) `@decorator()` func } else { // Ex) `@decorator` decorator } } /// Given an [`Expr`] that can be a [`ExprSubscript`][ast::ExprSubscript] or not /// (like an annotation that may be generic or not), return the underlying expr. pub fn map_subscript(expr: &Expr) -> &Expr { if let Expr::Subscript(ast::ExprSubscript { value, .. }) = expr { // Ex) `Iterable[T]` => return `Iterable` value } else { // Ex) `Iterable` => return `Iterable` expr } } /// Given an [`Expr`] that can be starred, return the underlying starred expression. pub fn map_starred(expr: &Expr) -> &Expr { if let Expr::Starred(ast::ExprStarred { value, .. }) = expr { // Ex) `*args` value } else { // Ex) `args` expr } } /// Return `true` if the body uses `locals()`, `globals()`, `vars()`, `eval()`. /// /// Accepts a closure that determines whether a given name (e.g., `"list"`) is a Python builtin. pub fn uses_magic_variable_access(body: &[Stmt], is_builtin: F) -> bool where F: Fn(&str) -> bool, { any_over_body(body, |expr| { if let Expr::Call(ast::ExprCall { func, .. }) = expr { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if matches!(id.as_str(), "locals" | "globals" | "vars" | "exec" | "eval") { if is_builtin(id.as_str()) { return true; } } } } false }) } /// Format the module reference name for a relative import. /// /// # Examples /// /// ```rust /// # use ruff_python_ast::helpers::format_import_from; /// /// assert_eq!(format_import_from(0, None), "".to_string()); /// assert_eq!(format_import_from(1, None), ".".to_string()); /// assert_eq!(format_import_from(1, Some("foo")), ".foo".to_string()); /// ``` pub fn format_import_from(level: u32, module: Option<&str>) -> Cow<'_, str> { match (level, module) { (0, Some(module)) => Cow::Borrowed(module), (level, module) => { let mut module_name = String::with_capacity((level as usize) + module.map_or(0, str::len)); for _ in 0..level { module_name.push('.'); } if let Some(module) = module { module_name.push_str(module); } Cow::Owned(module_name) } } } /// Format the member reference name for a relative import. /// /// # Examples /// /// ```rust /// # use ruff_python_ast::helpers::format_import_from_member; /// /// assert_eq!(format_import_from_member(0, None, "bar"), "bar".to_string()); /// assert_eq!(format_import_from_member(1, None, "bar"), ".bar".to_string()); /// assert_eq!(format_import_from_member(1, Some("foo"), "bar"), ".foo.bar".to_string()); /// ``` pub fn format_import_from_member(level: u32, module: Option<&str>, member: &str) -> String { let mut qualified_name = String::with_capacity((level as usize) + module.map_or(0, str::len) + 1 + member.len()); if level > 0 { for _ in 0..level { qualified_name.push('.'); } } if let Some(module) = module { qualified_name.push_str(module); qualified_name.push('.'); } qualified_name.push_str(member); qualified_name } /// Create a module path from a (package, path) pair. /// /// For example, if the package is `foo/bar` and the path is `foo/bar/baz.py`, /// the call path is `["baz"]`. pub fn to_module_path(package: &Path, path: &Path) -> Option> { path.strip_prefix(package.parent()?) .ok()? .iter() .map(Path::new) .map(Path::file_stem) .map(|path| path.and_then(|path| path.to_os_string().into_string().ok())) .collect::>>() } /// Format the call path for a relative import. /// /// # Examples /// /// ```rust /// # use ruff_python_ast::helpers::collect_import_from_member; /// /// assert_eq!(collect_import_from_member(0, None, "bar").segments(), ["bar"]); /// assert_eq!(collect_import_from_member(1, None, "bar").segments(), [".", "bar"]); /// assert_eq!(collect_import_from_member(1, Some("foo"), "bar").segments(), [".", "foo", "bar"]); /// ``` pub fn collect_import_from_member<'a>( level: u32, module: Option<&'a str>, member: &'a str, ) -> QualifiedName<'a> { let mut qualified_name_builder = QualifiedNameBuilder::with_capacity( level as usize + module .map(|module| module.split('.').count()) .unwrap_or_default() + 1, ); // Include the dots as standalone segments. if level > 0 { for _ in 0..level { qualified_name_builder.push("."); } } // Add the remaining segments. if let Some(module) = module { qualified_name_builder.extend(module.split('.')); } // Add the member. qualified_name_builder.push(member); qualified_name_builder.build() } /// 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 qualified_name_builder = QualifiedNameBuilder::with_capacity(module.len() + import.len() + tail.len()); // Start with the module path. qualified_name_builder.extend(module.iter().map(String::as_str)); // Remove segments based on the number of dots. for segment in import { if *segment == "." { if qualified_name_builder.is_empty() { return None; } qualified_name_builder.pop(); } else { qualified_name_builder.push(segment); } } // Add the remaining segments. qualified_name_builder.extend_from_slice(tail); Some(qualified_name_builder.build()) } /// Given an imported module (based on its relative import level and module name), return the /// fully-qualified module path. pub fn resolve_imported_module_path<'a>( level: u32, module: Option<&'a str>, module_path: Option<&[String]>, ) -> Option> { if level == 0 { return Some(Cow::Borrowed(module.unwrap_or(""))); } let module_path = module_path?; if level as usize >= module_path.len() { return None; } let mut qualified_path = module_path[..module_path.len() - level as usize].join("."); if let Some(module) = module { if !qualified_path.is_empty() { qualified_path.push('.'); } qualified_path.push_str(module); } Some(Cow::Owned(qualified_path)) } /// A [`Visitor`] to collect all [`Expr::Name`] nodes in an AST. #[derive(Debug, Default)] pub struct NameFinder<'a> { /// A map from identifier to defining expression. pub names: FxHashMap<&'a str, &'a ast::ExprName>, } impl<'a> Visitor<'a> for NameFinder<'a> { fn visit_expr(&mut self, expr: &'a Expr) { if let Expr::Name(name) = expr { self.names.insert(&name.id, name); } crate::visitor::walk_expr(self, expr); } } /// A [`Visitor`] to collect all stored [`Expr::Name`] nodes in an AST. #[derive(Debug, Default)] pub struct StoredNameFinder<'a> { /// A map from identifier to defining expression. pub names: FxHashMap<&'a str, &'a ast::ExprName>, } impl<'a> Visitor<'a> for StoredNameFinder<'a> { fn visit_expr(&mut self, expr: &'a Expr) { if let Expr::Name(name) = expr { if name.ctx.is_store() { self.names.insert(&name.id, name); } } crate::visitor::walk_expr(self, expr); } } /// A [`Visitor`] that collects all `return` statements in a function or method. #[derive(Default)] pub struct ReturnStatementVisitor<'a> { pub returns: Vec<&'a ast::StmtReturn>, pub is_generator: bool, } impl<'a> Visitor<'a> for ReturnStatementVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt { Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } Stmt::Return(stmt) => self.returns.push(stmt), _ => crate::visitor::walk_stmt(self, stmt), } } fn visit_expr(&mut self, expr: &'a Expr) { if let Expr::Yield(_) | Expr::YieldFrom(_) = expr { self.is_generator = true; } else { crate::visitor::walk_expr(self, expr); } } } /// A [`StatementVisitor`] that collects all `raise` statements in a function or method. #[derive(Default)] pub struct RaiseStatementVisitor<'a> { pub raises: Vec<(TextRange, Option<&'a Expr>, Option<&'a Expr>)>, } impl<'a> StatementVisitor<'a> for RaiseStatementVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt { Stmt::Raise(ast::StmtRaise { exc, cause, range: _, node_index: _, }) => { self.raises .push((stmt.range(), exc.as_deref(), cause.as_deref())); } Stmt::ClassDef(_) | Stmt::FunctionDef(_) | Stmt::Try(_) => {} Stmt::If(ast::StmtIf { body, elif_else_clauses, .. }) => { crate::statement_visitor::walk_body(self, body); for clause in elif_else_clauses { self.visit_elif_else_clause(clause); } } Stmt::While(ast::StmtWhile { body, .. }) | Stmt::With(ast::StmtWith { body, .. }) | Stmt::For(ast::StmtFor { body, .. }) => { crate::statement_visitor::walk_body(self, body); } Stmt::Match(ast::StmtMatch { cases, .. }) => { for case in cases { crate::statement_visitor::walk_body(self, &case.body); } } _ => {} } } } /// A [`Visitor`] that detects the presence of `await` expressions in the current scope. #[derive(Debug, Default)] pub struct AwaitVisitor { pub seen_await: bool, } impl Visitor<'_> for AwaitVisitor { fn visit_stmt(&mut self, stmt: &Stmt) { match stmt { Stmt::FunctionDef(_) | Stmt::ClassDef(_) => (), Stmt::With(ast::StmtWith { is_async: true, .. }) => { self.seen_await = true; } Stmt::For(ast::StmtFor { is_async: true, .. }) => { self.seen_await = true; } _ => crate::visitor::walk_stmt(self, stmt), } } fn visit_expr(&mut self, expr: &Expr) { if let Expr::Await(ast::ExprAwait { .. }) = expr { self.seen_await = true; } else { crate::visitor::walk_expr(self, expr); } } fn visit_comprehension(&mut self, comprehension: &'_ crate::Comprehension) { if comprehension.is_async { self.seen_await = true; } else { crate::visitor::walk_comprehension(self, comprehension); } } } /// Return `true` if a `Stmt` is a docstring. pub fn is_docstring_stmt(stmt: &Stmt) -> bool { if let Stmt::Expr(ast::StmtExpr { value, range: _, node_index: _, }) = stmt { value.is_string_literal_expr() } else { false } } /// Returns `true` if all statements in `body` are `pass` or `...` (ellipsis) /// /// An empty body (`[]`) returns `false` pub fn is_stub_body(body: &[Stmt]) -> bool { !body.is_empty() && body.iter().all(|stmt| match stmt { Stmt::Pass(_) => true, Stmt::Expr(ast::StmtExpr { value, .. }) => value.is_ellipsis_literal_expr(), _ => false, }) } /// Returns `body` without its leading docstring statement, if present. pub fn body_without_leading_docstring(body: &[Stmt]) -> &[Stmt] { match body.split_first() { Some((first, rest)) if is_docstring_stmt(first) => rest, _ => body, } } /// 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: _, node_index: _, }) = parent { if value.is_if_expr() { return true; } } false }) } /// Check if a node is in a nested block. pub fn in_nested_block<'a>(mut parents: impl Iterator) -> bool { parents.any(|parent| { matches!( parent, Stmt::Try(_) | Stmt::If(_) | Stmt::With(_) | Stmt::Match(_) ) }) } /// Check if a node represents an unpacking assignment. pub fn is_unpacking_assignment(parent: &Stmt, child: &Expr) -> bool { match parent { Stmt::With(ast::StmtWith { items, .. }) => items.iter().any(|item| { if let Some(optional_vars) = &item.optional_vars { if optional_vars.is_tuple_expr() { if any_over_expr(optional_vars, |expr| expr == child) { return true; } } } false }), Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { // In `(a, b) = (1, 2)`, `(1, 2)` is the target, and it is a tuple. let value_is_tuple = matches!( value.as_ref(), Expr::Set(_) | Expr::List(_) | Expr::Tuple(_) ); // In `(a, b) = coords = (1, 2)`, `(a, b)` and `coords` are the targets, and // `(a, b)` is a tuple. (We use "tuple" as a placeholder for any // unpackable expression.) let targets_are_tuples = targets .iter() .all(|item| matches!(item, Expr::Set(_) | Expr::List(_) | Expr::Tuple(_))); // If we're looking at `a` in `(a, b) = coords = (1, 2)`, then we should // identify that the current expression is in a tuple. let child_in_tuple = targets_are_tuples || targets.iter().any(|item| { matches!(item, Expr::Set(_) | Expr::List(_) | Expr::Tuple(_)) && any_over_expr(item, |expr| expr == child) }); // If our child is a tuple, and value is not, it's always an unpacking // expression. Ex) `x, y = tup` if child_in_tuple && !value_is_tuple { return true; } // If our child isn't a tuple, but value is, it's never an unpacking expression. // Ex) `coords = (1, 2)` if !child_in_tuple && value_is_tuple { return false; } // If our target and the value are both tuples, then it's an unpacking // expression assuming there's at least one non-tuple child. // Ex) Given `(x, y) = coords = 1, 2`, `(x, y)` is considered an unpacking // expression. Ex) Given `(x, y) = (a, b) = 1, 2`, `(x, y)` isn't // considered an unpacking expression. if child_in_tuple && value_is_tuple { return !targets_are_tuples; } false } _ => false, } } #[derive(Copy, Clone, Debug, PartialEq, is_macro::Is)] pub enum Truthiness { /// The expression is `True`. True, /// The expression is `False`. False, /// The expression evaluates to a `False`-like value (e.g., `None`, `0`, `[]`, `""`). Falsey, /// The expression evaluates to a `True`-like value (e.g., `1`, `"foo"`). Truthy, /// The expression evaluates to `None`. None, /// The expression evaluates to an unknown value (e.g., a variable `x` of unknown type). Unknown, } impl Truthiness { /// Return the truthiness of an expression. pub fn from_expr(expr: &Expr, is_builtin: F) -> Self where F: Fn(&str) -> bool, { match expr { Expr::Lambda(_) => Self::Truthy, Expr::Generator(_) => Self::Truthy, Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => { if value.is_empty() { Self::Falsey } else { Self::Truthy } } Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => { if value.is_empty() { Self::Falsey } else { Self::Truthy } } Expr::NumberLiteral(ast::ExprNumberLiteral { value, .. }) => match value { ast::Number::Int(int) => { if *int == 0 { Self::Falsey } else { Self::Truthy } } ast::Number::Float(float) => { if *float == 0.0 { Self::Falsey } else { Self::Truthy } } ast::Number::Complex { real, imag, .. } => { if *real == 0.0 && *imag == 0.0 { Self::Falsey } else { Self::Truthy } } }, Expr::BooleanLiteral(ast::ExprBooleanLiteral { value, .. }) => { if *value { Self::True } else { Self::False } } Expr::NoneLiteral(_) => Self::None, Expr::EllipsisLiteral(_) => Self::Truthy, Expr::FString(f_string) => { if is_empty_f_string(f_string) { Self::Falsey } else if is_non_empty_f_string(f_string) { Self::Truthy } else { Self::Unknown } } Expr::TString(_) => Self::Truthy, Expr::List(ast::ExprList { elts, .. }) | Expr::Set(ast::ExprSet { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) => { if elts.is_empty() { return Self::Falsey; } if elts.iter().all(Expr::is_starred_expr) { // [*foo] / [*foo, *bar] Self::Unknown } else { Self::Truthy } } Expr::Dict(dict) => { if dict.is_empty() { return Self::Falsey; } // If the dict consists only of double-starred items (e.g., {**x, **y}), // consider its truthiness unknown. This matches lists/sets/tuples containing // only starred elements, which are also Unknown. if dict .items .iter() .all(|item| matches!(item, DictItem { key: None, .. })) { // {**foo} / {**foo, **bar} Self::Unknown } else { Self::Truthy } } Expr::Call(ast::ExprCall { func, arguments, .. }) => { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if is_iterable_initializer(id.as_str(), |id| is_builtin(id)) { if arguments.is_empty() { // Ex) `list()` Self::Falsey } else if let [argument] = &*arguments.args && arguments.keywords.is_empty() { // Ex) `list([1, 2, 3])` match argument { // Return Unknown for types with definite truthiness that might // result in empty iterables (t-strings and generators) or will // raise a type error (non-iterable types like numbers, booleans, // None, etc.). Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) | Expr::TString(_) | Expr::Lambda(_) | Expr::Generator(_) => Self::Unknown, // Recurse for all other types - collections, comprehensions, variables, etc. // StringLiteral, FString, and BytesLiteral recurse because Self::from_expr // correctly handles their truthiness (checking if empty or not). _ => Self::from_expr(argument, is_builtin), } } else { Self::Unknown } } else { Self::Unknown } } else { Self::Unknown } } _ => Self::Unknown, } } pub fn into_bool(self) -> Option { match self { Self::True | Self::Truthy => Some(true), Self::False | Self::Falsey => Some(false), Self::None => Some(false), Self::Unknown => None, } } } /// Returns `true` if the expression definitely resolves to a non-empty string, when used as an /// f-string expression, or `false` if the expression may resolve to an empty string. fn is_non_empty_f_string(expr: &ast::ExprFString) -> bool { fn inner(expr: &Expr) -> bool { match expr { // When stringified, these expressions are always non-empty. Expr::Lambda(_) => true, Expr::Dict(_) => true, Expr::Set(_) => true, Expr::ListComp(_) => true, Expr::SetComp(_) => true, Expr::DictComp(_) => true, Expr::NumberLiteral(_) => true, Expr::BooleanLiteral(_) => true, Expr::NoneLiteral(_) => true, Expr::EllipsisLiteral(_) => true, Expr::List(_) => true, Expr::Tuple(_) => true, Expr::TString(_) => true, // These expressions must resolve to the inner expression. Expr::If(ast::ExprIf { body, orelse, .. }) => inner(body) && inner(orelse), Expr::Named(ast::ExprNamed { value, .. }) => inner(value), // These expressions are complex. We can't determine whether they're empty or not. Expr::BoolOp(ast::ExprBoolOp { .. }) => false, Expr::BinOp(ast::ExprBinOp { .. }) => false, Expr::UnaryOp(ast::ExprUnaryOp { .. }) => false, // Rich comparison methods can return arbitrary objects. Expr::Compare(_) => false, Expr::Generator(_) => false, Expr::Await(_) => false, Expr::Yield(_) => false, Expr::YieldFrom(_) => false, Expr::Call(_) => false, Expr::Attribute(_) => false, Expr::Subscript(_) => false, Expr::Starred(_) => false, Expr::Name(_) => false, Expr::Slice(_) => false, Expr::IpyEscapeCommand(_) => false, // These literals may or may not be empty. Expr::FString(f_string) => is_non_empty_f_string(f_string), // These literals may or may not be empty. Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => !value.is_empty(), // Confusingly, f"{b""}" renders as the string 'b""', which is non-empty. // Therefore, any bytes interpolation is guaranteed non-empty when stringified. Expr::BytesLiteral(_) => true, } } expr.value.iter().any(|part| match part { ast::FStringPart::Literal(string_literal) => !string_literal.is_empty(), ast::FStringPart::FString(f_string) => { // The part is a concatenation of elements, so it's guaranteed non-empty if any element is f_string.elements.iter().any(|element| match element { InterpolatedStringElement::Literal(string_literal) => !string_literal.is_empty(), InterpolatedStringElement::Interpolation(f_string) => { f_string.debug_text.is_some() || (f_string.format_spec.is_none() && inner(&f_string.expression)) } }) } }) } /// Returns `true` if the expression definitely resolves to the empty string, when used as an f-string /// expression. pub fn is_empty_f_string(expr: &ast::ExprFString) -> bool { fn inner(expr: &Expr) -> bool { match expr { Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => value.is_empty(), // Confusingly, `bool(f"{b""}") == True` even though // `bool(b"") == False`. This is because `f"{b""}"` // evaluates as the string `'b""'` of length 3. Expr::BytesLiteral(_) => false, Expr::FString(ast::ExprFString { value, .. }) => { is_empty_interpolated_elements(value.elements()) } _ => false, } } fn is_empty_interpolated_elements<'a>( mut elements: impl Iterator, ) -> bool { elements.all(|element| match element { InterpolatedStringElement::Literal(ast::InterpolatedStringLiteralElement { value, .. }) => value.is_empty(), InterpolatedStringElement::Interpolation(f_string) => { f_string.debug_text.is_none() && f_string.conversion.is_none() && f_string.format_spec.is_none() && inner(&f_string.expression) } }) } expr.value.iter().all(|part| match part { ast::FStringPart::Literal(string_literal) => string_literal.is_empty(), ast::FStringPart::FString(f_string) => { is_empty_interpolated_elements(f_string.elements.iter()) } }) } pub fn generate_comparison( left: &Expr, ops: &[CmpOp], comparators: &[Expr], parent: AnyNodeRef, tokens: &Tokens, source: &str, ) -> String { let start = left.start(); let end = comparators.last().map_or_else(|| left.end(), Ranged::end); let mut contents = String::with_capacity(usize::from(end - start)); // Add the left side of the comparison. contents.push_str( &source[parenthesized_range(left.into(), parent, tokens).unwrap_or(left.range())], ); for (op, comparator) in ops.iter().zip(comparators) { // Add the operator. contents.push_str(match op { CmpOp::Eq => " == ", CmpOp::NotEq => " != ", CmpOp::Lt => " < ", CmpOp::LtE => " <= ", CmpOp::Gt => " > ", CmpOp::GtE => " >= ", CmpOp::In => " in ", CmpOp::NotIn => " not in ", CmpOp::Is => " is ", CmpOp::IsNot => " is not ", }); // Add the right side of the comparison. contents.push_str( &source[parenthesized_range(comparator.into(), parent, tokens) .unwrap_or(comparator.range())], ); } contents } /// Format the expression as a PEP 604-style optional. pub fn pep_604_optional(expr: &Expr) -> Expr { ast::ExprBinOp { left: Box::new(expr.clone()), op: Operator::BitOr, right: Box::new(Expr::NoneLiteral(ExprNoneLiteral::default())), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, } .into() } /// Format the expressions as a PEP 604-style union. pub fn pep_604_union(elts: &[Expr]) -> Expr { match elts { [] => Expr::Tuple(ast::ExprTuple { elts: vec![], ctx: ExprContext::Load, range: TextRange::default(), node_index: AtomicNodeIndex::NONE, parenthesized: true, }), [Expr::Tuple(ast::ExprTuple { elts, .. })] => pep_604_union(elts), [elt] => elt.clone(), [rest @ .., elt] => Expr::BinOp(ast::ExprBinOp { left: Box::new(pep_604_union(rest)), op: Operator::BitOr, right: Box::new(pep_604_union(std::slice::from_ref(elt))), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }), } } /// Format the expression as a `typing.Optional`-style optional. pub fn typing_optional(elt: Expr, binding: Name) -> Expr { Expr::Subscript(ast::ExprSubscript { value: Box::new(Expr::Name(ast::ExprName { id: binding, range: TextRange::default(), node_index: AtomicNodeIndex::NONE, ctx: ExprContext::Load, })), slice: Box::new(elt), ctx: ExprContext::Load, range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }) } /// Format the expressions as a `typing.Union`-style union. /// /// Note: It is a syntax error to have `Union[]` so the caller /// should ensure that the `elts` argument is nonempty. pub fn typing_union(elts: &[Expr], binding: Name) -> Expr { Expr::Subscript(ast::ExprSubscript { value: Box::new(Expr::Name(ast::ExprName { id: binding, range: TextRange::default(), node_index: AtomicNodeIndex::NONE, ctx: ExprContext::Load, })), slice: Box::new(Expr::Tuple(ast::ExprTuple { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, elts: elts.to_vec(), ctx: ExprContext::Load, parenthesized: false, })), ctx: ExprContext::Load, range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }) } /// Determine the indentation level of an own-line comment, defined as the minimum indentation of /// all comments between the preceding node and the comment, including the comment itself. In /// other words, we don't allow successive comments to ident _further_ than any preceding comments. /// /// For example, given: /// ```python /// if True: /// pass /// # comment /// ``` /// /// The indentation would be 4, as the comment is indented by 4 spaces. /// /// Given: /// ```python /// if True: /// pass /// # comment /// else: /// pass /// ``` /// /// The indentation would be 0, as the comment is not indented at all. /// /// Given: /// ```python /// if True: /// pass /// # comment /// # comment /// ``` /// /// Both comments would be marked as indented at 4 spaces, as the indentation of the first comment /// is used for the second comment. /// /// This logic avoids pathological cases like: /// ```python /// try: /// if True: /// if True: /// pass /// /// # a /// # b /// # c /// except Exception: /// pass /// ``` /// /// If we don't use the minimum indentation of any preceding comments, we would mark `# b` as /// indented to the same depth as `pass`, which could in turn lead to us treating it as a trailing /// comment of `pass`, despite there being a comment between them that "resets" the indentation. pub fn comment_indentation_after( preceding: AnyNodeRef, comment_range: TextRange, source: &str, ) -> TextSize { let tokenizer = SimpleTokenizer::new( source, TextRange::new(source.full_line_end(preceding.end()), comment_range.end()), ); tokenizer .filter_map(|token| { if token.kind() == SimpleTokenKind::Comment { indentation_at_offset(token.start(), source).map(TextLen::text_len) } else { None } }) .min() .unwrap_or_default() } pub fn is_dotted_name(expr: &ast::Expr) -> bool { match expr { ast::Expr::Name(_) => true, ast::Expr::Attribute(ast::ExprAttribute { value, .. }) => is_dotted_name(value), _ => false, } } #[cfg(test)] mod tests { use std::borrow::Cow; use std::cell::RefCell; use std::vec; use ruff_text_size::TextRange; use crate::helpers::{any_over_stmt, any_over_type_param, resolve_imported_module_path}; use crate::{ AtomicNodeIndex, Expr, ExprContext, ExprName, ExprNumberLiteral, Identifier, Int, Number, Stmt, StmtTypeAlias, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, }; #[test] fn resolve_import() { // Return the module directly. assert_eq!( resolve_imported_module_path(0, Some("foo"), None), Some(Cow::Borrowed("foo")) ); // Construct the module path from the calling module's path. assert_eq!( resolve_imported_module_path( 1, Some("foo"), Some(&["bar".to_string(), "baz".to_string()]) ), Some(Cow::Owned("bar.foo".to_string())) ); // We can't return the module if it's a relative import, and we don't know the calling // module's path. assert_eq!(resolve_imported_module_path(1, Some("foo"), None), None); // We can't return the module if it's a relative import, and the path goes beyond the // calling module's path. assert_eq!( resolve_imported_module_path(1, Some("foo"), Some(&["bar".to_string()])), None, ); assert_eq!( resolve_imported_module_path(2, Some("foo"), Some(&["bar".to_string()])), None ); } #[test] fn any_over_stmt_type_alias() { let seen = RefCell::new(Vec::new()); let name = Expr::Name(ExprName { id: "x".into(), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, ctx: ExprContext::Load, }); let constant_one = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::from(1u8)), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let constant_two = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::from(2u8)), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let constant_three = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::from(3u8)), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let type_var_one = TypeParam::TypeVar(TypeParamTypeVar { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, bound: Some(Box::new(constant_one.clone())), default: None, name: Identifier::new("x", TextRange::default()), }); let type_var_two = TypeParam::TypeVar(TypeParamTypeVar { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, bound: None, default: Some(Box::new(constant_two.clone())), name: Identifier::new("x", TextRange::default()), }); let type_alias = Stmt::TypeAlias(StmtTypeAlias { name: Box::new(name.clone()), type_params: Some(Box::new(TypeParams { type_params: vec![type_var_one, type_var_two], range: TextRange::default(), node_index: AtomicNodeIndex::NONE, })), value: Box::new(constant_three.clone()), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); assert!(!any_over_stmt(&type_alias, |expr| { seen.borrow_mut().push(expr.clone()); false })); assert_eq!( seen.take(), vec![name, constant_one, constant_two, constant_three] ); } #[test] fn any_over_type_param_type_var() { let type_var_no_bound = TypeParam::TypeVar(TypeParamTypeVar { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, bound: None, default: None, name: Identifier::new("x", TextRange::default()), }); assert!(!any_over_type_param(&type_var_no_bound, &mut |_expr| true)); let constant = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::ONE), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let type_var_with_bound = TypeParam::TypeVar(TypeParamTypeVar { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, bound: Some(Box::new(constant.clone())), default: None, name: Identifier::new("x", TextRange::default()), }); assert!( any_over_type_param(&type_var_with_bound, &mut |expr| { assert_eq!( *expr, constant, "the received expression should be the unwrapped bound" ); true }), "if true is returned from `func` it should be respected" ); let type_var_with_default = TypeParam::TypeVar(TypeParamTypeVar { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, default: Some(Box::new(constant.clone())), bound: None, name: Identifier::new("x", TextRange::default()), }); assert!( any_over_type_param(&type_var_with_default, &mut |expr| { assert_eq!( *expr, constant, "the received expression should be the unwrapped default" ); true }), "if true is returned from `func` it should be respected" ); } #[test] fn any_over_type_param_type_var_tuple() { let type_var_tuple = TypeParam::TypeVarTuple(TypeParamTypeVarTuple { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, name: Identifier::new("x", TextRange::default()), default: None, }); assert!( !any_over_type_param(&type_var_tuple, &mut |_expr| true), "this TypeVarTuple has no expressions to visit" ); let constant = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::ONE), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let type_var_tuple_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, default: Some(Box::new(constant.clone())), name: Identifier::new("x", TextRange::default()), }); assert!( any_over_type_param(&type_var_tuple_with_default, &mut |expr| { assert_eq!( *expr, constant, "the received expression should be the unwrapped default" ); true }), "if true is returned from `func` it should be respected" ); } #[test] fn any_over_type_param_param_spec() { let type_param_spec = TypeParam::ParamSpec(TypeParamParamSpec { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, name: Identifier::new("x", TextRange::default()), default: None, }); assert!( !any_over_type_param(&type_param_spec, &mut |_expr| true), "this ParamSpec has no expressions to visit" ); let constant = Expr::NumberLiteral(ExprNumberLiteral { value: Number::Int(Int::ONE), range: TextRange::default(), node_index: AtomicNodeIndex::NONE, }); let param_spec_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple { range: TextRange::default(), node_index: AtomicNodeIndex::NONE, default: Some(Box::new(constant.clone())), name: Identifier::new("x", TextRange::default()), }); assert!( any_over_type_param(¶m_spec_with_default, &mut |expr| { assert_eq!( *expr, constant, "the received expression should be the unwrapped default" ); true }), "if true is returned from `func` it should be respected" ); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/identifier.rs000064400000000000000000000165511046102023000213260ustar00//! Extract [`TextRange`] information from AST nodes. //! //! For example, given: //! ```python //! try: //! ... //! except Exception as e: //! ... //! ``` //! //! This module can be used to identify the [`TextRange`] of the `except` token. use crate::{self as ast, Alias, ExceptHandler, Parameter, ParameterWithDefault, Stmt}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_python_trivia::{Cursor, is_python_whitespace}; pub trait Identifier { /// Return the [`TextRange`] of the identifier in the given AST node. 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. /// /// For example, return the range of `f` in: /// ```python /// def f(): /// ... /// ``` fn identifier(&self) -> TextRange { match self { Stmt::ClassDef(class) => class.identifier(), Stmt::FunctionDef(function) => function.identifier(), _ => self.range(), } } } impl Identifier for Parameter { /// Return the [`TextRange`] for the identifier defining an [`Parameter`]. /// /// For example, return the range of `x` in: /// ```python /// def f(x: int): /// ... /// ``` fn identifier(&self) -> TextRange { self.name.range() } } impl Identifier for ParameterWithDefault { /// Return the [`TextRange`] for the identifier defining an [`ParameterWithDefault`]. /// /// For example, return the range of `x` in: /// ```python /// def f(x: int = 0): /// ... /// ``` fn identifier(&self) -> TextRange { self.parameter.identifier() } } impl Identifier for Alias { /// Return the [`TextRange`] for the identifier defining an [`Alias`]. /// /// For example, return the range of `x` in: /// ```python /// from foo import bar as x /// ``` fn identifier(&self) -> TextRange { self.asname .as_ref() .map_or_else(|| self.name.range(), Ranged::range) } } /// Return the [`TextRange`] of the `except` token in an [`ExceptHandler`]. pub fn except(handler: &ExceptHandler, source: &str) -> TextRange { IdentifierTokenizer::new(source, handler.range()) .next() .expect("Failed to find `except` token in `ExceptHandler`") } /// 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::While(ast::StmtWhile { body, orelse, .. })) = stmt else { return None; }; if orelse.is_empty() { return None; } IdentifierTokenizer::starts_at( body.last().expect("Expected body to be non-empty").end(), source, ) .next() } /// Return `true` if the given character starts a valid Python identifier. /// /// Python identifiers must start with an alphabetic character or an underscore. fn is_python_identifier_start(c: char) -> bool { c.is_alphabetic() || c == '_' } /// Return `true` if the given character is a valid Python identifier continuation character. /// /// Python identifiers can contain alphanumeric characters and underscores, but cannot start with a /// number. fn is_python_identifier_continue(c: char) -> bool { c.is_alphanumeric() || c == '_' } /// Simple zero allocation tokenizer for Python identifiers. /// /// The tokenizer must operate over a range that can only contain identifiers, keywords, and /// comments (along with whitespace and continuation characters). It does not support other tokens, /// like operators, literals, or delimiters. It also does not differentiate between keywords and /// identifiers, treating every valid token as an "identifier". /// /// This is useful for cases like, e.g., identifying the alias name in an aliased import (`bar` in /// `import foo as bar`), where we're guaranteed to only have identifiers and keywords in the /// relevant range. pub(crate) struct IdentifierTokenizer<'a> { cursor: Cursor<'a>, offset: TextSize, } impl<'a> IdentifierTokenizer<'a> { fn new(source: &'a str, range: TextRange) -> Self { Self { cursor: Cursor::new(&source[range]), offset: range.start(), } } fn starts_at(offset: TextSize, source: &'a str) -> Self { let range = TextRange::new(offset, source.text_len()); Self::new(source, range) } fn next_token(&mut self) -> Option { while let Some(c) = { self.offset += self.cursor.token_len(); self.cursor.start_token(); self.cursor.bump() } { match c { c if is_python_identifier_start(c) => { self.cursor.eat_while(is_python_identifier_continue); return Some(TextRange::at(self.offset, self.cursor.token_len())); } c if is_python_whitespace(c) => { self.cursor.eat_while(is_python_whitespace); } '#' => { self.cursor.eat_while(|c| !matches!(c, '\n' | '\r')); } '\r' => { self.cursor.eat_char('\n'); } '\n' => { // Nothing to do. } '\\' => { // Nothing to do. } _ => { // Nothing to do. } } } None } } impl Iterator for IdentifierTokenizer<'_> { type Item = TextRange; fn next(&mut self) -> Option { self.next_token() } } #[cfg(test)] mod tests { use super::IdentifierTokenizer; use ruff_text_size::{TextLen, TextRange, TextSize}; #[test] fn extract_global_names() { let contents = r"global X,Y, Z".trim(); let mut names = IdentifierTokenizer::new( contents, TextRange::new(TextSize::new(0), contents.text_len()), ); let range = names.next_token().unwrap(); assert_eq!(&contents[range], "global"); assert_eq!(range, TextRange::new(TextSize::from(0), TextSize::from(6))); let range = names.next_token().unwrap(); assert_eq!(&contents[range], "X"); assert_eq!(range, TextRange::new(TextSize::from(7), TextSize::from(8))); let range = names.next_token().unwrap(); assert_eq!(&contents[range], "Y"); assert_eq!(range, TextRange::new(TextSize::from(9), TextSize::from(10))); let range = names.next_token().unwrap(); assert_eq!(&contents[range], "Z"); assert_eq!( range, TextRange::new(TextSize::from(12), TextSize::from(13)) ); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/int.rs000064400000000000000000000145571046102023000200020ustar00use std::fmt::Debug; use std::str::FromStr; /// A Python integer literal. Represents both small (fits in an `i64`) and large integers. #[derive(Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Int(Number); impl FromStr for Int { type Err = std::num::ParseIntError; /// Parse an [`Int`] from a string. fn from_str(s: &str) -> Result { match s.parse::() { Ok(value) => Ok(Int::small(value)), Err(err) => { if matches!( err.kind(), std::num::IntErrorKind::PosOverflow | std::num::IntErrorKind::NegOverflow ) { Ok(Int::big(s)) } else { Err(err) } } } } } impl Int { pub const ZERO: Int = Int(Number::Small(0)); pub const ONE: Int = Int(Number::Small(1)); /// Create an [`Int`] to represent a value that can be represented as an `i64`. fn small(value: u64) -> Self { Self(Number::Small(value)) } /// Create an [`Int`] to represent a value that cannot be represented as an `i64`. fn big(value: impl Into>) -> Self { Self(Number::Big(value.into())) } /// Parse an [`Int`] from a string with a given radix, like `0x95D`. /// /// Takes, as input, the numerical portion (`95D`), the parsed base (`16`), and the entire /// token (`0x95D`). pub fn from_str_radix( number: &str, radix: u32, token: &str, ) -> Result { match u64::from_str_radix(number, radix) { Ok(value) => Ok(Int::small(value)), Err(err) => { if matches!( err.kind(), std::num::IntErrorKind::PosOverflow | std::num::IntErrorKind::NegOverflow ) { Ok(Int::big(token)) } else { Err(err) } } } } /// Return the [`Int`] as an u8, if it can be represented as that data type. pub fn as_u8(&self) -> Option { match &self.0 { Number::Small(small) => u8::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an u16, if it can be represented as that data type. pub fn as_u16(&self) -> Option { match &self.0 { Number::Small(small) => u16::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an u32, if it can be represented as that data type. fn as_u32(&self) -> Option { match &self.0 { Number::Small(small) => u32::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an u64, if it can be represented as that data type. pub const fn as_u64(&self) -> Option { match &self.0 { Number::Small(small) => Some(*small), Number::Big(_) => None, } } /// Return the [`Int`] as an usize, if it can be represented as that data type. pub fn as_usize(&self) -> Option { match &self.0 { Number::Small(small) => usize::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an i8, if it can be represented as that data type. pub fn as_i8(&self) -> Option { match &self.0 { Number::Small(small) => i8::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an i16, if it can be represented as that data type. fn as_i16(&self) -> Option { match &self.0 { Number::Small(small) => i16::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an i32, if it can be represented as that data type. pub fn as_i32(&self) -> Option { match &self.0 { Number::Small(small) => i32::try_from(*small).ok(), Number::Big(_) => None, } } /// Return the [`Int`] as an i64, if it can be represented as that data type. pub fn as_i64(&self) -> Option { match &self.0 { Number::Small(small) => i64::try_from(*small).ok(), Number::Big(_) => None, } } } impl std::fmt::Display for Int { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl Debug for Int { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self, f) } } impl PartialEq for Int { fn eq(&self, other: &u8) -> bool { self.as_u8() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &u16) -> bool { self.as_u16() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &u32) -> bool { self.as_u32() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &i8) -> bool { self.as_i8() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &i16) -> bool { self.as_i16() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &i32) -> bool { self.as_i32() == Some(*other) } } impl PartialEq for Int { fn eq(&self, other: &i64) -> bool { self.as_i64() == Some(*other) } } impl From for Int { fn from(value: u8) -> Self { Self::small(u64::from(value)) } } impl From for Int { fn from(value: u16) -> Self { Self::small(u64::from(value)) } } impl From for Int { fn from(value: u32) -> Self { Self::small(u64::from(value)) } } impl From for Int { fn from(value: u64) -> Self { Self::small(value) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum Number { /// A "small" number that can be represented as an `u64`. Small(u64), /// A "large" number that cannot be represented as an `u64`. Big(Box), } impl std::fmt::Display for Number { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Number::Small(value) => write!(f, "{value}"), Number::Big(value) => write!(f, "{value}"), } } } ast_serialize-0.13.1/crates/ruff_python_ast/src/lib.rs000064400000000000000000000104261046102023000177450ustar00use std::ffi::OsStr; use std::path::Path; pub use expression::*; pub use generated::*; pub use int::*; pub use node_index::*; pub use nodes::*; pub use operator_precedence::*; pub use python_version::*; pub mod comparable; pub mod docstrings; mod expression; pub mod find_node; mod generated; pub mod helpers; pub mod identifier; mod int; pub mod name; mod node; mod node_index; mod nodes; pub mod operator_precedence; pub mod parenthesize; mod python_version; pub mod relocate; pub mod script; pub mod statement_visitor; pub mod stmt_if; pub mod str; pub mod str_prefix; pub mod token; pub mod traversal; pub mod types; pub mod visitor; pub mod whitespace; /// The type of a source file. #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] pub enum SourceType { /// The file contains Python source code. Python(PySourceType), /// The file contains TOML. Toml(TomlSourceType), /// The file contains Markdown. Markdown, } impl SourceType { pub fn from_extension(ext: &str) -> Self { match ext { "toml" => Self::Toml(TomlSourceType::Unrecognized), "md" => Self::Markdown, _ => Self::Python(PySourceType::from_extension(ext)), } } } impl Default for SourceType { fn default() -> Self { Self::Python(PySourceType::Python) } } impl> From

for SourceType { fn from(path: P) -> Self { match path.as_ref().file_name() { Some(filename) if filename == "pyproject.toml" => Self::Toml(TomlSourceType::Pyproject), Some(filename) if filename == "Pipfile" => Self::Toml(TomlSourceType::Pipfile), Some(filename) if filename == "poetry.lock" => Self::Toml(TomlSourceType::Poetry), Some(filename) if filename == "ruff.toml" || filename == ".ruff.toml" => { Self::Toml(TomlSourceType::Ruff) } _ => Self::from_extension( path.as_ref() .extension() .and_then(OsStr::to_str) .unwrap_or(""), ), } } } #[derive(Clone, Copy, Debug, PartialEq, is_macro::Is)] pub enum TomlSourceType { /// The source is a `pyproject.toml`. Pyproject, /// The source is a `ruff.toml` or `.ruff.toml`. Ruff, /// The source is a `Pipfile`. Pipfile, /// The source is a `poetry.lock`. Poetry, /// The source is an unrecognized TOML file. Unrecognized, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum PySourceType { /// The source is a Python file (`.py`, `.pyw`). /// Note: `.pyw` files contain Python code, but do not represent importable namespaces. /// Consider adding a separate source type later if combining the two causes issues. #[default] Python, /// The source is a Python stub file (`.pyi`). Stub, /// The source is a Jupyter notebook (`.ipynb`). Ipynb, } impl PySourceType { /// Infers the source type from the file extension. /// /// Falls back to `Python` if the extension is not recognized. pub fn from_extension(extension: &str) -> Self { Self::try_from_extension(extension).unwrap_or_default() } /// Infers the source type from the file extension. pub fn try_from_extension(extension: &str) -> Option { let ty = match extension { "py" => Self::Python, "pyi" => Self::Stub, "pyw" => Self::Python, "ipynb" => Self::Ipynb, _ => return None, }; Some(ty) } pub fn try_from_path(path: impl AsRef) -> Option { path.as_ref() .extension() .and_then(OsStr::to_str) .and_then(Self::try_from_extension) } pub const fn is_py_file(self) -> bool { matches!(self, Self::Python) } pub const fn is_stub(self) -> bool { matches!(self, Self::Stub) } pub const fn is_py_file_or_stub(self) -> bool { matches!(self, Self::Python | Self::Stub) } pub const fn is_ipynb(self) -> bool { matches!(self, Self::Ipynb) } } impl> From

for PySourceType { fn from(path: P) -> Self { Self::try_from_path(path).unwrap_or_default() } } ast_serialize-0.13.1/crates/ruff_python_ast/src/name.rs000064400000000000000000000717351046102023000201310ustar00use std::borrow::{Borrow, Cow}; use std::fmt::{Debug, Display, Formatter, Write}; use std::hash::{Hash, Hasher}; use std::ops::Deref; use arrayvec::ArrayVec; use char_str::{CharStr, CharString}; use crate::Expr; use crate::generated::ExprName; /// An immutable name. /// /// # Choosing a string representation /// /// On 64-bit targets, [`CharStr`] occupies 16 bytes and stores up to 16 UTF-8 bytes inline. Longer /// values use an exactly-sized, reference-counted allocation, so cloning a heap-backed value /// reuses its allocation. [`compact_str::CompactString`] occupies 24 bytes, stores up to 24 bytes /// inline, and remains mutable; cloning a heap-backed value copies its contents into a new /// allocation. /// /// Prefer `CharStr` for immutable text that is retained densely or passed between owners, when /// either the smaller handle or structural sharing offsets the extra heap allocations for values /// between 17 and 24 bytes. Prefer `CompactString` for uniquely owned text, especially when it is /// built incrementally, mutated, or commonly falls in that 17-to-24-byte range. /// /// `Name` uses `CharStr` because names appear throughout the AST and repeated heap-backed parser /// names share an allocation. By contrast, [`crate::DebugText`] uses `CompactString` because it /// builds a uniquely owned buffer incrementally, and `ty_module_resolver::ModuleName` uses /// `CompactString` because module names can be extended in place. /// /// Converting a borrowed `&str` into `CharStr` creates a new value and does not preserve structural /// sharing. When an API retains text already held in a `CharStr` (including a `Name`), pass or clone /// the owned value rather than converting it through `&str`. This is especially relevant at Salsa /// interning boundaries. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[cfg_attr(feature = "salsa", derive(salsa::SalsaValue))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "cache", derive(ruff_macros::CacheKey))] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] #[cfg_attr( feature = "schemars", derive(schemars::JsonSchema), schemars(with = "String") )] pub struct Name(CharStr); impl Name { #[inline] pub fn empty() -> Self { Self(CharStr::new()) } #[inline] pub fn new(name: impl AsRef) -> Self { Self(CharStr::from(name.as_ref())) } /// Creates an inline name, returning `None` if `name` does not fit inline. #[inline] pub fn new_inline(name: impl AsRef) -> Option { CharStr::new_inline(name.as_ref()).map(Self) } /// Creates an exactly-sized, heap-allocated name. #[inline] pub fn new_heap(name: impl AsRef) -> Self { Self(CharStr::new_heap(name.as_ref())) } #[inline] pub const fn new_static(name: &'static str) -> Self { Self(CharStr::from_static_str(name)) } /// Creates an exactly-sized name by concatenating string slices. /// /// The combined length is computed up front, so heap storage is allocated at most once. #[inline] pub fn concat>(slices: &[T]) -> Self { Self(CharStr::concat(slices)) } /// Creates an exactly-sized name by joining string slices with a separator. /// /// Like [`Name::concat`], this computes the combined length up front, so heap storage is /// allocated at most once. For dynamically formatted names, use [`Name::from`] with /// [`format_char!`](char_str::format_char). If a [`CharStr`] is sufficient, use /// [`format_char_str!`](char_str::format_char_str) instead. #[inline] pub fn join>(slices: &[T], separator: &str) -> Self { Self(CharStr::join(slices, separator)) } #[inline] pub fn as_str(&self) -> &str { self.0.as_str() } } impl Debug for Name { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "Name({:?})", self.as_str()) } } impl AsRef for Name { #[inline] fn as_ref(&self) -> &str { self.as_str() } } impl Deref for Name { type Target = str; #[inline] fn deref(&self) -> &Self::Target { self.as_str() } } impl Borrow for Name { #[inline] fn borrow(&self) -> &str { self.as_str() } } impl<'a> From<&'a str> for Name { #[inline] fn from(s: &'a str) -> Self { Name::new(s) } } impl From for Name { #[inline] fn from(s: String) -> Self { Name(s.into()) } } impl<'a> From<&'a String> for Name { #[inline] fn from(s: &'a String) -> Self { Name::new(s) } } impl<'a> From> for Name { #[inline] fn from(cow: Cow<'a, str>) -> Self { Name(cow.into()) } } impl From> for Name { #[inline] fn from(b: Box) -> Self { Name(b.into()) } } #[cfg(feature = "salsa")] impl salsa::Lookup for &str { #[inline] fn into_owned(self) -> Name { Name::new(self) } } #[cfg(feature = "salsa")] impl salsa::HashEqLike<&str> for Name { #[inline] fn hash(&self, state: &mut H) { self.as_str().hash(state); } #[inline] fn eq(&self, data: &&str) -> bool { self.as_str() == *data } } impl From for String { #[inline] fn from(name: Name) -> Self { name.0.into() } } impl From for CharStr { #[inline] fn from(name: Name) -> Self { name.0 } } #[cfg(feature = "salsa")] impl salsa::Lookup for Name { #[inline] fn into_owned(self) -> compact_str::CompactString { compact_str::CompactString::new(self.as_str()) } } #[cfg(feature = "salsa")] impl salsa::Lookup for &Name { #[inline] fn into_owned(self) -> compact_str::CompactString { compact_str::CompactString::new(self.as_str()) } } #[cfg(feature = "salsa")] impl salsa::HashEqLike for compact_str::CompactString { #[inline] fn hash(&self, state: &mut H) { Hash::hash(self, state); } #[inline] fn eq(&self, data: &Name) -> bool { self.as_str() == data.as_str() } } #[cfg(feature = "salsa")] impl salsa::HashEqLike<&Name> for compact_str::CompactString { #[inline] fn hash(&self, state: &mut H) { Hash::hash(self, state); } #[inline] fn eq(&self, data: &&Name) -> bool { self.as_str() == data.as_str() } } impl From for Name { #[inline] fn from(name: CharString) -> Self { Self(name.freeze()) } } impl FromIterator for Name { fn from_iter>(iter: I) -> Self { Self(iter.into_iter().collect()) } } impl std::fmt::Display for Name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(self.as_str()) } } impl PartialEq for Name { #[inline] fn eq(&self, other: &str) -> bool { self.as_str() == other } } impl PartialEq for str { #[inline] fn eq(&self, other: &Name) -> bool { other == self } } impl PartialEq<&str> for Name { #[inline] fn eq(&self, other: &&str) -> bool { self.as_str() == *other } } impl PartialEq for &str { #[inline] fn eq(&self, other: &Name) -> bool { other == self } } impl PartialEq for Name { fn eq(&self, other: &String) -> bool { self == other.as_str() } } impl PartialEq for String { #[inline] fn eq(&self, other: &Name) -> bool { other == self } } impl PartialEq<&String> for Name { #[inline] fn eq(&self, other: &&String) -> bool { self.as_str() == *other } } impl PartialEq for &String { #[inline] fn eq(&self, other: &Name) -> bool { other == self } } /// A representation of a qualified name, like `typing.List`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct QualifiedName<'a>(SegmentsVec<'a>); impl<'a> QualifiedName<'a> { /// Create a [`QualifiedName`] from a dotted name. /// /// ```rust /// # use ruff_python_ast::name::QualifiedName; /// /// assert_eq!(QualifiedName::from_dotted_name("typing.List").segments(), ["typing", "List"]); /// assert_eq!(QualifiedName::from_dotted_name("list").segments(), ["", "list"]); /// ``` #[inline] pub fn from_dotted_name(name: &'a str) -> Self { if let Some(dot) = name.find('.') { let mut builder = QualifiedNameBuilder::default(); builder.push(&name[..dot]); builder.extend(name[dot + 1..].split('.')); builder.build() } else { Self::builtin(name) } } /// Creates a name that's guaranteed not be a built in #[inline] pub fn user_defined(name: &'a str) -> Self { name.split('.').collect() } /// Creates a qualified name for a built in #[inline] pub fn builtin(name: &'a str) -> Self { debug_assert!(!name.contains('.')); Self(SegmentsVec::from_slice(&["", name])) } #[inline] pub fn segments(&self) -> &[&'a str] { self.0.as_slice() } /// If the first segment is empty, the `CallPath` represents a "builtin binding". /// /// A builtin binding is the binding that a symbol has if it was part of Python's /// global scope without any imports taking place. However, if builtin members are /// accessed explicitly via the `builtins` module, they will not have a /// "builtin binding", so this method will return `false`. /// /// Ex) `["", "bool"]` -> `"bool"` fn is_builtin(&self) -> bool { matches!(self.segments(), ["", ..]) } /// If the call path is dot-prefixed, it's an unresolved relative import. /// Ex) `[".foo", "bar"]` -> `".foo.bar"` pub fn is_unresolved_import(&self) -> bool { matches!(self.segments(), [".", ..]) } pub fn starts_with(&self, other: &QualifiedName<'_>) -> bool { self.segments().starts_with(other.segments()) } /// Appends a member to the qualified name. #[must_use] pub fn append_member(self, member: &'a str) -> Self { let mut inner = self.0; inner.push(member); Self(inner) } /// Extends the qualified name using the given members. #[must_use] pub fn extend_members>(self, members: T) -> Self { let mut inner = self.0; inner.extend(members); Self(inner) } } impl Display for QualifiedName<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let segments = self.segments(); if self.is_unresolved_import() { let mut iter = segments.iter(); for segment in iter.by_ref() { if *segment == "." { f.write_char('.')?; } else { f.write_str(segment)?; break; } } for segment in iter { f.write_char('.')?; f.write_str(segment)?; } } else { let segments = if self.is_builtin() { &segments[1..] } else { segments }; let mut first = true; for segment in segments { if !first { f.write_char('.')?; } f.write_str(segment)?; first = false; } } Ok(()) } } impl<'a> FromIterator<&'a str> for QualifiedName<'a> { fn from_iter>(iter: T) -> Self { Self(SegmentsVec::from_iter(iter)) } } #[derive(Debug, Clone, Default)] pub struct QualifiedNameBuilder<'a> { segments: SegmentsVec<'a>, } impl<'a> QualifiedNameBuilder<'a> { pub fn with_capacity(capacity: usize) -> Self { Self { segments: SegmentsVec::with_capacity(capacity), } } #[inline] pub(crate) fn is_empty(&self) -> bool { self.segments.is_empty() } #[inline] pub fn push(&mut self, segment: &'a str) { self.segments.push(segment); } #[inline] pub(crate) fn pop(&mut self) { self.segments.pop(); } #[inline] pub fn extend(&mut self, segments: impl IntoIterator) { self.segments.extend(segments); } #[inline] pub(crate) fn extend_from_slice(&mut self, segments: &[&'a str]) { self.segments.extend_from_slice(segments); } pub fn build(self) -> QualifiedName<'a> { QualifiedName(self.segments) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UnqualifiedName<'a>(SegmentsVec<'a>); impl<'a> UnqualifiedName<'a> { /// Convert an `Expr` to its [`UnqualifiedName`] (like `["typing", "List"]`). pub fn from_expr(expr: &'a Expr) -> Option { // Unroll the loop up to eight times, to match the maximum number of expected attributes. // In practice, unrolling appears to give about a 4x speed-up on this hot path. let attr1 = match expr { Expr::Attribute(attr1) => attr1, // Ex) `foo` Expr::Name(ExprName { id, .. }) => return Some(Self::from_slice(&[id.as_str()])), _ => return None, }; let attr2 = match attr1.value.as_ref() { Expr::Attribute(attr2) => attr2, // Ex) `foo.bar` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[id.as_str(), attr1.attr.as_str()])); } _ => return None, }; let attr3 = match attr2.value.as_ref() { Expr::Attribute(attr3) => attr3, // Ex) `foo.bar.baz` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[ id.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ])); } _ => return None, }; let attr4 = match attr3.value.as_ref() { Expr::Attribute(attr4) => attr4, // Ex) `foo.bar.baz.bop` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[ id.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ])); } _ => return None, }; let attr5 = match attr4.value.as_ref() { Expr::Attribute(attr5) => attr5, // Ex) `foo.bar.baz.bop.bap` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[ id.as_str(), attr4.attr.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ])); } _ => return None, }; let attr6 = match attr5.value.as_ref() { Expr::Attribute(attr6) => attr6, // Ex) `foo.bar.baz.bop.bap.bab` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[ id.as_str(), attr5.attr.as_str(), attr4.attr.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ])); } _ => return None, }; let attr7 = match attr6.value.as_ref() { Expr::Attribute(attr7) => attr7, // Ex) `foo.bar.baz.bop.bap.bab.bob` Expr::Name(ExprName { id, .. }) => { return Some(Self::from_slice(&[ id.as_str(), attr6.attr.as_str(), attr5.attr.as_str(), attr4.attr.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ])); } _ => return None, }; let attr8 = match attr7.value.as_ref() { Expr::Attribute(attr8) => attr8, // Ex) `foo.bar.baz.bop.bap.bab.bob.bib` Expr::Name(ExprName { id, .. }) => { return Some(Self(SegmentsVec::from([ id.as_str(), attr7.attr.as_str(), attr6.attr.as_str(), attr5.attr.as_str(), attr4.attr.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ]))); } _ => return None, }; let mut segments = Vec::with_capacity(SMALL_LEN * 2); let mut current = &*attr8.value; loop { current = match current { Expr::Attribute(attr) => { segments.push(attr.attr.as_str()); &*attr.value } Expr::Name(ExprName { id, .. }) => { segments.push(id.as_str()); break; } _ => { return None; } } } segments.reverse(); // Append the attributes we visited before calling into the recursion. segments.extend_from_slice(&[ attr8.attr.as_str(), attr7.attr.as_str(), attr6.attr.as_str(), attr5.attr.as_str(), attr4.attr.as_str(), attr3.attr.as_str(), attr2.attr.as_str(), attr1.attr.as_str(), ]); Some(Self(SegmentsVec::from(segments))) } #[inline] fn from_slice(segments: &[&'a str]) -> Self { Self(SegmentsVec::from_slice(segments)) } pub fn segments(&self) -> &[&'a str] { self.0.as_slice() } } impl Display for UnqualifiedName<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut first = true; for segment in self.segments() { if !first { f.write_char('.')?; } f.write_str(segment)?; first = false; } Ok(()) } } impl<'a> FromIterator<&'a str> for UnqualifiedName<'a> { #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect()) } } /// A smallvec like storage for qualified and unqualified name segments. /// /// Stores up to 8 segments inline, and falls back to a heap-allocated vector for names with more segments. /// /// ## Note /// The inline variant uses `ArrayVec` rather than `SmallVec` v1 because `SmallVec`'s type /// definition has a variance problem. The incorrect variance leads lifetime inference in the /// `SemanticModel` astray, causing all sorts of "strange" lifetime errors. #[derive(Clone)] enum SegmentsVec<'a> { Stack(SegmentsStack<'a>), Heap(Vec<&'a str>), } impl<'a> SegmentsVec<'a> { /// Creates an empty segment vec. fn new() -> Self { Self::Stack(SegmentsStack::default()) } /// Creates a segment vec that has reserved storage for up to `capacity` items. fn with_capacity(capacity: usize) -> Self { if capacity <= SMALL_LEN { Self::new() } else { Self::Heap(Vec::with_capacity(capacity)) } } #[cfg(test)] const fn is_spilled(&self) -> bool { matches!(self, SegmentsVec::Heap(_)) } /// Initializes the segments from a slice. #[inline] fn from_slice(slice: &[&'a str]) -> Self { match SegmentsStack::try_from(slice) { Ok(stack) => SegmentsVec::Stack(stack), Err(_) => SegmentsVec::Heap(slice.to_vec()), } } /// Returns the segments as a slice. #[inline] fn as_slice(&self) -> &[&'a str] { match self { Self::Stack(stack) => stack.as_slice(), Self::Heap(heap) => heap.as_slice(), } } /// Pushes `name` to the end of the segments. /// /// Spills to the heap if the segments are stored on the stack and the 9th segment is pushed. #[inline] fn push(&mut self, name: &'a str) { match self { SegmentsVec::Stack(stack) => { if let Err(error) = stack.try_push(name) { let mut segments = Vec::with_capacity(stack.len() * 2); segments.extend(stack.iter().copied()); segments.push(error.element()); *self = SegmentsVec::Heap(segments); } } SegmentsVec::Heap(heap) => { heap.push(name); } } } /// Pops the last segment from the end and returns it. /// /// Returns `None` if the vector is empty. #[inline] fn pop(&mut self) -> Option<&'a str> { match self { SegmentsVec::Stack(stack) => stack.pop(), SegmentsVec::Heap(heap) => heap.pop(), } } #[inline] fn extend_from_slice(&mut self, slice: &[&'a str]) { match self { SegmentsVec::Stack(stack) => { if stack.try_extend_from_slice(slice).is_err() { let mut segments = Vec::with_capacity(stack.len() + slice.len()); segments.extend(stack.iter().copied()); segments.extend_from_slice(slice); *self = SegmentsVec::Heap(segments); } } SegmentsVec::Heap(heap) => heap.extend_from_slice(slice), } } } impl Default for SegmentsVec<'_> { fn default() -> Self { Self::new() } } impl Debug for SegmentsVec<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_list().entries(self.as_slice()).finish() } } impl<'a> Deref for SegmentsVec<'a> { type Target = [&'a str]; fn deref(&self) -> &Self::Target { self.as_slice() } } impl<'b> PartialEq> for SegmentsVec<'_> { fn eq(&self, other: &SegmentsVec<'b>) -> bool { self.as_slice() == other.as_slice() } } impl Eq for SegmentsVec<'_> {} impl Hash for SegmentsVec<'_> { fn hash(&self, state: &mut H) { self.as_slice().hash(state); } } impl<'a> FromIterator<&'a str> for SegmentsVec<'a> { #[inline] fn from_iter>(iter: T) -> Self { let mut segments = SegmentsVec::default(); segments.extend(iter); segments } } impl<'a> From<[&'a str; 8]> for SegmentsVec<'a> { #[inline] fn from(segments: [&'a str; 8]) -> Self { SegmentsVec::Stack(SegmentsStack::from(segments)) } } impl<'a> From> for SegmentsVec<'a> { #[inline] fn from(segments: Vec<&'a str>) -> Self { SegmentsVec::Heap(segments) } } impl<'a> Extend<&'a str> for SegmentsVec<'a> { #[inline] fn extend>(&mut self, iter: T) { match self { SegmentsVec::Stack(stack) => { let mut iter = iter.into_iter(); let (lower, _) = iter.size_hint(); if lower > stack.remaining_capacity() { let mut segments = Vec::with_capacity(stack.len() + lower); segments.extend(stack.iter().copied()); segments.extend(iter); *self = SegmentsVec::Heap(segments); return; } while let Some(name) = iter.next() { if let Err(error) = stack.try_push(name) { let mut segments = Vec::with_capacity(stack.len() * 2); segments.extend(stack.iter().copied()); segments.push(error.element()); segments.extend(iter); *self = SegmentsVec::Heap(segments); return; } } } SegmentsVec::Heap(heap) => { heap.extend(iter); } } } } const SMALL_LEN: usize = 8; type SegmentsStack<'a> = ArrayVec<&'a str, SMALL_LEN>; #[cfg(test)] mod tests { #[cfg(feature = "salsa")] use std::hash::{DefaultHasher, Hash, Hasher}; #[cfg(feature = "salsa")] use crate::name::Name; use crate::name::SegmentsVec; #[cfg(feature = "salsa")] #[test] fn salsa_lookup_name_from_str() { let name = Name::new("member"); let lookup = "member"; let mut name_hasher = DefaultHasher::new(); salsa::HashEqLike::<&str>::hash(&name, &mut name_hasher); let mut lookup_hasher = DefaultHasher::new(); lookup.hash(&mut lookup_hasher); assert_eq!(name_hasher.finish(), lookup_hasher.finish()); assert!(salsa::HashEqLike::<&str>::eq(&name, &lookup)); assert_eq!(salsa::Lookup::::into_owned(lookup), name); } #[test] fn empty_vec() { let empty = SegmentsVec::new(); assert_eq!(empty.as_slice(), &[] as &[&str]); assert!(!empty.is_spilled()); } #[test] fn from_slice_stack() { let stack = SegmentsVec::from_slice(&["a", "b", "c"]); assert_eq!(stack.as_slice(), &["a", "b", "c"]); assert!(!stack.is_spilled()); } #[test] fn from_slice_stack_capacity() { let stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h"]); assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h"]); assert!(!stack.is_spilled()); } #[test] fn from_slice_heap() { let heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]); assert_eq!( heap.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i"] ); assert!(heap.is_spilled()); } #[test] fn push_stack() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]); stack.push("d"); stack.push("e"); assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e"]); assert!(!stack.is_spilled()); } #[test] fn push_stack_spill() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g"]); stack.push("h"); assert!(!stack.is_spilled()); stack.push("i"); assert_eq!( stack.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i"] ); assert!(stack.is_spilled()); } #[test] fn pop_stack() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e"]); assert_eq!(stack.pop(), Some("e")); assert_eq!(stack.pop(), Some("d")); assert_eq!(stack.pop(), Some("c")); assert_eq!(stack.pop(), Some("b")); assert_eq!(stack.pop(), Some("a")); assert_eq!(stack.pop(), None); assert!(!stack.is_spilled()); } #[test] fn pop_heap() { let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]); assert_eq!(heap.pop(), Some("i")); assert_eq!(heap.pop(), Some("h")); assert_eq!(heap.pop(), Some("g")); assert!(heap.is_spilled()); } #[test] fn extend_from_slice_stack() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]); stack.extend_from_slice(&["d", "e", "f"]); assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f"]); assert!(!stack.is_spilled()); } #[test] fn extend_from_slice_stack_spill() { let mut spilled = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f"]); spilled.extend_from_slice(&["g", "h", "i", "j"]); assert_eq!( spilled.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] ); assert!(spilled.is_spilled()); } #[test] fn extend_from_slice_heap() { let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]); assert!(heap.is_spilled()); heap.extend_from_slice(&["j", "k", "l"]); assert_eq!( heap.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"] ); } #[test] fn extend_stack() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]); stack.extend(["d", "e", "f"]); assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f"]); assert!(!stack.is_spilled()); } #[test] fn extend_stack_spilled() { let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f"]); stack.extend(["g", "h", "i", "j"]); assert_eq!( stack.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] ); assert!(stack.is_spilled()); } #[test] fn extend_heap() { let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]); assert!(heap.is_spilled()); heap.extend(["j", "k", "l"]); assert_eq!( heap.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"] ); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/node.rs000064400000000000000000000513051046102023000201250ustar00use ruff_text_size::Ranged; use crate::visitor::source_order::SourceOrderVisitor; use crate::{ self as ast, Alias, AnyNodeRef, AnyParameterRef, ArgOrKeyword, MatchCase, PatternKeyword, }; impl ast::ElifElseClause { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ElifElseClause { range: _, node_index: _, test, body, } = self; if let Some(test) = test { visitor.visit_expr(test); } visitor.visit_body(body); } } impl ast::ExprDict { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprDict { items, range: _, node_index: _, } = self; for ast::DictItem { key, value } in items { if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); } } } impl ast::ExprBoolOp { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprBoolOp { op, values, range: _, node_index: _, } = 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 ast::ExprCompare { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprCompare { left, ops, comparators, range: _, node_index: _, } = self; visitor.visit_expr(left); for (op, comparator) in ops.iter().zip(comparators) { visitor.visit_cmp_op(op); visitor.visit_expr(comparator); } } } impl ast::InterpolatedStringFormatSpec { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { for element in &self.elements { visitor.visit_interpolated_string_element(element); } } } impl ast::InterpolatedElement { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::InterpolatedElement { expression, format_spec, .. } = self; visitor.visit_expr(expression); if let Some(format_spec) = format_spec { for spec_part in &format_spec.elements { visitor.visit_interpolated_string_element(spec_part); } } } } impl ast::InterpolatedStringLiteralElement { pub(crate) fn visit_source_order<'a, V>(&'a self, _visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::InterpolatedStringLiteralElement { range: _, node_index: _, value: _, } = self; } } impl ast::ExprFString { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprFString { value, range: _, node_index: _, } = self; for f_string_part in value { match f_string_part { ast::FStringPart::Literal(string_literal) => { visitor.visit_string_literal(string_literal); } ast::FStringPart::FString(f_string) => { visitor.visit_f_string(f_string); } } } } } impl ast::ExprTString { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprTString { value, range: _, node_index: _, } = self; for t_string in value { visitor.visit_t_string(t_string); } } } impl ast::ExprStringLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprStringLiteral { value, range: _, node_index: _, } = self; for string_literal in value { visitor.visit_string_literal(string_literal); } } } impl ast::ExprBytesLiteral { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExprBytesLiteral { value, range: _, node_index: _, } = self; for bytes_literal in value { visitor.visit_bytes_literal(bytes_literal); } } } impl ast::ExceptHandlerExceptHandler { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ExceptHandlerExceptHandler { range: _, node_index: _, type_, name, body, } = self; if let Some(expr) = type_ { visitor.visit_expr(expr); } if let Some(name) = name { visitor.visit_identifier(name); } visitor.visit_body(body); } } impl ast::PatternMatchMapping { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::PatternMatchMapping { keys, patterns, rest, range: _, node_index: _, } = self; let mut rest = rest.as_ref(); for (key, pattern) in keys.iter().zip(patterns) { if let Some(rest_identifier) = rest { if rest_identifier.start() < key.start() { visitor.visit_identifier(rest_identifier); rest = None; } } visitor.visit_expr(key); visitor.visit_pattern(pattern); } if let Some(rest) = rest { visitor.visit_identifier(rest); } } } impl ast::PatternArguments { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { for pattern_or_keyword in self.iter_source_order() { match pattern_or_keyword { crate::PatternOrKeyword::Pattern(pattern) => visitor.visit_pattern(pattern), crate::PatternOrKeyword::Keyword(keyword) => { visitor.visit_pattern_keyword(keyword); } } } } } impl ast::PatternKeyword { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let PatternKeyword { range: _, node_index: _, attr, pattern, } = self; visitor.visit_identifier(attr); visitor.visit_pattern(pattern); } } impl ast::Comprehension { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Comprehension { range: _, node_index: _, target, iter, ifs, is_async: _, } = self; visitor.visit_expr(target); visitor.visit_expr(iter); for expr in ifs { visitor.visit_expr(expr); } } } impl ast::Arguments { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { for arg_or_keyword in self.iter_source_order() { match arg_or_keyword { ArgOrKeyword::Arg(arg) => visitor.visit_expr(arg), ArgOrKeyword::Keyword(keyword) => visitor.visit_keyword(keyword), } } } } impl ast::Parameters { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { for parameter in self.iter_source_order() { match parameter { AnyParameterRef::NonVariadic(parameter_with_default) => { visitor.visit_parameter_with_default(parameter_with_default); } AnyParameterRef::Variadic(parameter) => visitor.visit_parameter(parameter), } } } } impl ast::Parameter { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Parameter { range: _, node_index: _, name, annotation, } = self; visitor.visit_identifier(name); if let Some(expr) = annotation { visitor.visit_annotation(expr); } } } impl ast::ParameterWithDefault { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::ParameterWithDefault { range: _, node_index: _, parameter, default, } = self; visitor.visit_parameter(parameter); if let Some(expr) = default { visitor.visit_expr(expr); } } } impl ast::Keyword { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Keyword { range: _, node_index: _, arg, value, } = self; if let Some(arg) = arg { visitor.visit_identifier(arg); } visitor.visit_expr(value); } } impl Alias { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Alias { range: _, node_index: _, name, asname, } = self; visitor.visit_identifier(name); if let Some(asname) = asname { visitor.visit_identifier(asname); } } } impl ast::WithItem { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::WithItem { range: _, node_index: _, context_expr, optional_vars, } = self; visitor.visit_expr(context_expr); if let Some(expr) = optional_vars { visitor.visit_expr(expr); } } } impl ast::MatchCase { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::MatchCase { range: _, node_index: _, pattern, guard, body, } = self; visitor.visit_pattern(pattern); if let Some(expr) = guard { visitor.visit_expr(expr); } visitor.visit_body(body); } } impl ast::Decorator { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Decorator { range: _, node_index: _, expression, } = self; visitor.visit_expr(expression); } } impl ast::TypeParams { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::TypeParams { range: _, node_index: _, type_params, } = self; for type_param in type_params { visitor.visit_type_param(type_param); } } } impl ast::FString { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::FString { elements, range: _, node_index: _, flags: _, } = self; for fstring_element in elements { visitor.visit_interpolated_string_element(fstring_element); } } } impl ast::TString { pub(crate) fn visit_source_order<'a, V>(&'a self, visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::TString { elements, range: _, node_index: _, flags: _, } = self; for tstring_element in elements { visitor.visit_interpolated_string_element(tstring_element); } } } impl ast::StringLiteral { #[inline] pub(crate) fn visit_source_order<'a, V>(&'a self, _visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::StringLiteral { range: _, node_index: _, value: _, flags: _, } = self; } } impl ast::BytesLiteral { #[inline] pub(crate) fn visit_source_order<'a, V>(&'a self, _visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::BytesLiteral { range: _, node_index: _, value: _, flags: _, } = self; } } impl ast::Identifier { #[inline] pub(crate) fn visit_source_order<'a, V>(&'a self, _visitor: &mut V) where V: SourceOrderVisitor<'a> + ?Sized, { let ast::Identifier { range: _, node_index: _, id: _, } = self; } } impl<'a> AnyNodeRef<'a> { /// Compares two any node refs by their pointers (referential equality). pub fn ptr_eq(self, other: AnyNodeRef) -> bool { self.as_ptr().eq(&other.as_ptr()) && self.kind() == other.kind() } /// In our AST, only some alternative branches are represented as a node. This has historical /// reasons, e.g. we added a node for elif/else in if statements which was not originally /// present in the parser. pub const fn is_alternative_branch_with_node(self) -> bool { matches!( self, AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::ElifElseClause(_) ) } /// The last child of the last branch, if the node has multiple branches. pub fn last_child_in_body(&self) -> Option> { let body = match self { AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) | AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) | AnyNodeRef::MatchCase(MatchCase { body, .. }) | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) | AnyNodeRef::ElifElseClause(ast::ElifElseClause { body, .. }) => body, AnyNodeRef::StmtIf(ast::StmtIf { body, elif_else_clauses, .. }) => elif_else_clauses.last().map_or(body, |clause| &clause.body), AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { if orelse.is_empty() { body } else { orelse } } AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => { return cases.last().map(AnyNodeRef::from); } AnyNodeRef::StmtTry(ast::StmtTry { body, handlers, orelse, finalbody, .. }) => { if finalbody.is_empty() { if orelse.is_empty() { if handlers.is_empty() { body } else { return handlers.last().map(AnyNodeRef::from); } } else { orelse } } else { finalbody } } // Not a node that contains an indented child node. _ => return None, }; body.last().map(AnyNodeRef::from) } /// Check if the given statement is the first statement after the colon of a branch, be it in if /// statements, for statements, after each part of a try-except-else-finally or function/class /// definitions. /// /// /// ```python /// if True: <- has body /// a <- first statement /// b /// elif b: <- has body /// c <- first statement /// d /// else: <- has body /// e <- first statement /// f /// /// class: <- has body /// a: int <- first statement /// b: int /// /// ``` /// /// For nodes with multiple bodies, we check all bodies that don't have their own node. For /// try-except-else-finally, each except branch has it's own node, so for the `StmtTry`, we check /// the `try:`, `else:` and `finally:`, bodies, while `ExceptHandlerExceptHandler` has it's own /// check. For for-else and while-else, we check both branches for the whole statement. /// /// ```python /// try: <- has body (a) /// 6/8 <- first statement (a) /// 1/0 /// except: <- has body (b) /// a <- first statement (b) /// b /// else: /// c <- first statement (a) /// d /// finally: /// e <- first statement (a) /// f /// ``` pub fn is_first_statement_in_body(&self, body: AnyNodeRef) -> bool { match body { AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { are_same_optional(*self, body.first()) || are_same_optional(*self, orelse.first()) } AnyNodeRef::StmtTry(ast::StmtTry { body, orelse, finalbody, .. }) => { are_same_optional(*self, body.first()) || are_same_optional(*self, orelse.first()) || are_same_optional(*self, finalbody.first()) } AnyNodeRef::StmtIf(ast::StmtIf { body, .. }) | AnyNodeRef::ElifElseClause(ast::ElifElseClause { body, .. }) | AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) | AnyNodeRef::MatchCase(MatchCase { body, .. }) | AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) => { are_same_optional(*self, body.first()) } AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => { are_same_optional(*self, cases.first()) } _ => false, } } /// Returns `true` if `statement` is the first statement in an alternate `body` (e.g. the else of an if statement) pub fn is_first_statement_in_alternate_body(&self, body: AnyNodeRef) -> bool { match body { AnyNodeRef::StmtFor(ast::StmtFor { orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { orelse, .. }) => { are_same_optional(*self, orelse.first()) } AnyNodeRef::StmtTry(ast::StmtTry { handlers, orelse, finalbody, .. }) => { are_same_optional(*self, handlers.first()) || are_same_optional(*self, orelse.first()) || are_same_optional(*self, finalbody.first()) } AnyNodeRef::StmtIf(ast::StmtIf { elif_else_clauses, .. }) => are_same_optional(*self, elif_else_clauses.first()), _ => false, } } } /// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal. fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option) -> bool where T: Into>, { right.is_some_and(|right| left.ptr_eq(right.into())) } ast_serialize-0.13.1/crates/ruff_python_ast/src/node_index.rs000064400000000000000000000200361046102023000213110ustar00use std::num::NonZeroU32; use std::sync::atomic::{AtomicU32, Ordering}; /// An AST node that has an index. pub trait HasNodeIndex { /// Returns the [`AtomicNodeIndex`] for this node. fn node_index(&self) -> &AtomicNodeIndex; } impl HasNodeIndex for &T where T: HasNodeIndex, { fn node_index(&self) -> &AtomicNodeIndex { T::node_index(*self) } } /// A unique index for a node within an AST. /// /// Our encoding of 32-bit AST node indices is as follows: /// /// * `u32::MAX` (1111...1) is reserved as a forbidden value (mapped to 0 for `NonZero`) /// * `u32::MAX - 1` (1111...0) is reserved for `NodeIndex::NONE` /// * The top two bits encode the sub-AST level: /// * 00 is top-level AST /// * 01 is sub-AST (string annotation) /// * 10 is sub-sub-AST (string annotation in string annotation) /// * 11 is forbidden (well, it only appears in the above reserved values) /// * The remaining 30 bits are the real (sub)-AST node index /// /// To get the first sub-index of a node's sub-AST we: /// /// * increment the sub-AST level in the high-bits /// * at level 1, multiply the real index by 256 /// * at level 2, multiply the real index by 8 /// /// The multiplication gives each node a reserved space of 256 nodes for its sub-AST /// to work with ("should be enough for anybody"), and 8 nodes for a sub-sub-AST /// (enough for an identifier and maybe some simple unions). /// /// Here are some implications: /// /// * We have 2^30 top-level AST nodes (1 billion) /// * To have a string annotation, the parent node needs to be multiplied by 256 without /// overflowing 30 bits, so string annotations cannot be used after 2^22 nodes (4 million), /// which would be like, a million lines of code. /// * To have a sub-string annotation, the top-level node needs to be multiplied /// by 256 * 8, so sub-string annotations cannot be used after 2^19 nodes (500 thousand), /// or about 100k lines of code. /// /// This feels like a pretty reasonable compromise that will work well in practice, /// although it creates some very wonky boundary conditions that will be very unpleasant /// if someone runs into them. /// /// That said, string annotations are in many regards "legacy" and so new code ideally /// doesn't have to use them, and there's never a real reason to use sub-annotation /// let-alone a sub-sub-annotation. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct NodeIndex(NonZeroU32); impl NodeIndex { /// A placeholder `NodeIndex`. const NONE: NodeIndex = NodeIndex(NonZeroU32::new(NodeIndex::_NONE).unwrap()); // Note that the index `u32::MAX` is reserved for the `NonZeroU32` niche, and // this placeholder also reserves the second highest index. const _NONE: u32 = u32::MAX - 1; /// Returns the index as a `u32`. or `None` for `NodeIndex::NONE`. pub fn as_u32(self) -> Option { if self == NodeIndex::NONE { None } else { Some(self.0.get() - 1) } } } #[derive(Debug, Copy, Clone)] pub enum NodeIndexError { NoParent, TooNested, ExhaustedSubIndices, ExhaustedSubSubIndices, OverflowedIndices, OverflowedSubIndices, } const MAX_LEVEL: u32 = 2; const LEVEL_BITS: u32 = 32 - MAX_LEVEL.leading_zeros(); const LEVEL_SHIFT: u32 = 32 - LEVEL_BITS; const LEVEL_MASK: u32 = ((LEVEL_BITS << 1) - 1) << LEVEL_SHIFT; const SUB_NODES: u32 = 256; const SUB_SUB_NODES: u32 = 8; pub const MAX_REAL_INDEX: u32 = (1 << LEVEL_SHIFT) - 1; /// sub-AST level is stored in the top two bits pub fn sub_ast_level(index: u32) -> u32 { (index & LEVEL_MASK) >> LEVEL_SHIFT } /// Get the first and last index of the sub-AST of the input pub fn sub_indices(index: u32) -> Result<(u32, u32), NodeIndexError> { let level = sub_ast_level(index); if level >= MAX_LEVEL { return Err(NodeIndexError::TooNested); } let next_level = (level + 1) << LEVEL_SHIFT; let without_level = index & !LEVEL_MASK; let (nodes_in_level, error_kind) = if level == 0 { (SUB_NODES, NodeIndexError::OverflowedIndices) } else if level == 1 { (SUB_SUB_NODES, NodeIndexError::OverflowedSubIndices) } else { unreachable!( "Someone made a mistake updating the encoding of node indices: {index:08X} had level {level}" ); }; // If this overflows the file has hundreds of thousands of lines of code, // but that *can* happen (we just can't support string annotations that deep) let sub_index_without_level = without_level .checked_mul(nodes_in_level) .ok_or(error_kind)?; if sub_index_without_level > MAX_REAL_INDEX { return Err(error_kind); } let first_index = sub_index_without_level | next_level; // Can't overflow by construction let last_index = first_index + nodes_in_level - 1; Ok((first_index, last_index)) } impl From for NodeIndex { fn from(value: u32) -> Self { match NonZeroU32::new(value + 1).map(NodeIndex) { None | Some(NodeIndex::NONE) => panic!("exceeded maximum `NodeIndex`"), Some(index) => index, } } } impl std::fmt::Debug for NodeIndex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if *self == Self::NONE { f.debug_tuple("NodeIndex(None)").finish() } else { f.debug_tuple("NodeIndex").field(&self.0).finish() } } } /// A unique index for a node within an AST. /// /// This type is interiorly mutable to allow assigning node indices /// on-demand after parsing. #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct AtomicNodeIndex(AtomicU32); #[expect(clippy::declare_interior_mutable_const)] impl AtomicNodeIndex { /// A placeholder `AtomicNodeIndex`. pub const NONE: AtomicNodeIndex = AtomicNodeIndex(AtomicU32::new(NodeIndex::_NONE)); /// Load the current value of the `AtomicNodeIndex`. pub fn load(&self) -> NodeIndex { let index = NonZeroU32::new(self.0.load(Ordering::Relaxed)) .expect("value stored was a valid `NodeIndex`"); NodeIndex(index) } /// Set the value of the `AtomicNodeIndex`. pub fn set(&self, index: NodeIndex) { self.0.store(index.0.get(), Ordering::Relaxed); } } impl Default for AtomicNodeIndex { fn default() -> Self { Self::NONE } } impl std::fmt::Debug for AtomicNodeIndex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Debug::fmt(&self.load(), f) } } impl std::hash::Hash for AtomicNodeIndex { fn hash(&self, state: &mut H) { self.load().hash(state); } } impl PartialOrd for AtomicNodeIndex { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for AtomicNodeIndex { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.load().cmp(&other.load()) } } impl Eq for AtomicNodeIndex {} impl PartialEq for AtomicNodeIndex { fn eq(&self, other: &Self) -> bool { self.load() == other.load() } } impl PartialEq for AtomicNodeIndex { fn eq(&self, other: &NodeIndex) -> bool { self.load() == *other } } impl PartialEq for NodeIndex { fn eq(&self, other: &AtomicNodeIndex) -> bool { *self == other.load() } } impl Clone for AtomicNodeIndex { fn clone(&self) -> Self { Self(AtomicU32::from(self.0.load(Ordering::Relaxed))) } } #[cfg(test)] mod tests { use super::{AtomicNodeIndex, NodeIndex}; #[test] fn test_node_index() { let index = AtomicNodeIndex::NONE; assert_eq!(index.load(), NodeIndex::NONE); assert_eq!(format!("{index:?}"), "NodeIndex(None)"); index.set(NodeIndex::from(1)); assert_eq!(index.load(), NodeIndex::from(1)); assert_eq!(index.load().as_u32(), Some(1)); let index = NodeIndex::from(0); assert_eq!(index.as_u32(), Some(0)); let index = NodeIndex::NONE; assert_eq!(index.as_u32(), None); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/nodes.rs000064400000000000000000003776261046102023000203310ustar00#![allow(clippy::derive_partial_eq_without_eq)] use crate::AtomicNodeIndex; use crate::generated::{ ExprBytesLiteral, ExprCall, ExprDict, ExprFString, ExprList, ExprName, ExprSet, ExprStringLiteral, ExprTString, ExprTuple, PatternMatchAs, PatternMatchOr, StmtClassDef, }; use std::borrow::Cow; use std::fmt; use std::fmt::Debug; use std::iter::FusedIterator; use std::ops::{Deref, DerefMut}; use std::slice::{Iter, IterMut}; use std::sync::OnceLock; use bitflags::bitflags; use thin_vec::ThinVec; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use crate::str_prefix::{ AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix, TStringPrefix, }; use crate::{ Expr, ExprRef, InterpolatedStringElement, LiteralExpressionRef, OperatorPrecedence, Pattern, Stmt, TypeParam, int, name::Name, str::{Quote, TripleQuotes}, }; impl StmtClassDef { /// Return an iterator over the bases of the class. pub fn bases(&self) -> &[Expr] { match &self.arguments { Some(arguments) => &arguments.args, None => &[], } } /// Return an iterator over the metaclass keywords of the class. pub fn keywords(&self) -> &[Keyword] { match &self.arguments { Some(arguments) => &arguments.keywords, None => &[], } } } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ElifElseClause { pub range: TextRange, pub node_index: AtomicNodeIndex, pub test: Option, pub body: Suite, } impl Expr { /// Returns `true` if the expression is a literal expression. /// /// A literal expression is either a string literal, bytes literal, /// integer, float, complex number, boolean, `None`, or ellipsis (`...`). pub fn is_literal_expr(&self) -> bool { matches!( self, Expr::StringLiteral(_) | Expr::BytesLiteral(_) | Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) ) } /// Returns [`LiteralExpressionRef`] if the expression is a literal expression. pub fn as_literal_expr(&self) -> Option> { match self { Expr::StringLiteral(expr) => Some(LiteralExpressionRef::StringLiteral(expr)), Expr::BytesLiteral(expr) => Some(LiteralExpressionRef::BytesLiteral(expr)), Expr::NumberLiteral(expr) => Some(LiteralExpressionRef::NumberLiteral(expr)), Expr::BooleanLiteral(expr) => Some(LiteralExpressionRef::BooleanLiteral(expr)), Expr::NoneLiteral(expr) => Some(LiteralExpressionRef::NoneLiteral(expr)), Expr::EllipsisLiteral(expr) => Some(LiteralExpressionRef::EllipsisLiteral(expr)), _ => None, } } /// Return the value expression after peeling off any nested named expressions. /// /// For example, this returns the `x` expression for both `x` and `(y := x)`. pub fn expression_value(&self) -> &Self { let mut expr = self; while let Expr::Named(named) = expr { expr = &named.value; } expr } /// Return the [`OperatorPrecedence`] of this expression pub fn precedence(&self) -> OperatorPrecedence { OperatorPrecedence::from(self) } } impl ExprRef<'_> { /// See [`Expr::is_literal_expr`]. pub fn is_literal_expr(&self) -> bool { matches!( self, ExprRef::StringLiteral(_) | ExprRef::BytesLiteral(_) | ExprRef::NumberLiteral(_) | ExprRef::BooleanLiteral(_) | ExprRef::NoneLiteral(_) | ExprRef::EllipsisLiteral(_) ) } pub fn precedence(&self) -> OperatorPrecedence { OperatorPrecedence::from(*self) } } /// Represents an item in a [dictionary literal display][1]. /// /// Consider the following Python dictionary literal: /// ```python /// {key1: value1, **other_dictionary} /// ``` /// /// In our AST, this would be represented using an `ExprDict` node containing /// two `DictItem` nodes inside it: /// ```ignore /// [ /// DictItem { /// key: Some(Expr::Name(ExprName { id: "key1" })), /// value: Expr::Name(ExprName { id: "value1" }), /// }, /// DictItem { /// key: None, /// value: Expr::Name(ExprName { id: "other_dictionary" }), /// } /// ] /// ``` /// /// [1]: https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct DictItem { pub key: Option, pub value: Expr, } impl DictItem { fn key(&self) -> Option<&Expr> { self.key.as_ref() } fn value(&self) -> &Expr { &self.value } } impl Ranged for DictItem { fn range(&self) -> TextRange { TextRange::new( self.key.as_ref().map_or(self.value.start(), Ranged::start), self.value.end(), ) } } impl ExprDict { /// Returns an `Iterator` over the AST nodes representing the /// dictionary's keys. pub fn iter_keys(&self) -> DictKeyIterator<'_> { DictKeyIterator::new(&self.items) } /// Returns an `Iterator` over the AST nodes representing the /// dictionary's values. pub fn iter_values(&self) -> DictValueIterator<'_> { DictValueIterator::new(&self.items) } /// Returns the AST node representing the *n*th key of this /// dictionary. /// /// Panics: If the index `n` is out of bounds. pub fn key(&self, n: usize) -> Option<&Expr> { self.items[n].key() } /// Returns the AST node representing the *n*th value of this /// dictionary. /// /// Panics: If the index `n` is out of bounds. pub fn value(&self, n: usize) -> &Expr { self.items[n].value() } pub fn iter(&self) -> std::slice::Iter<'_, DictItem> { self.items.iter() } pub fn len(&self) -> usize { self.items.len() } pub fn is_empty(&self) -> bool { self.items.is_empty() } } impl<'a> IntoIterator for &'a ExprDict { type IntoIter = std::slice::Iter<'a, DictItem>; type Item = &'a DictItem; fn into_iter(self) -> Self::IntoIter { self.iter() } } #[derive(Debug, Clone)] pub struct DictKeyIterator<'a> { items: Iter<'a, DictItem>, } impl<'a> DictKeyIterator<'a> { fn new(items: &'a [DictItem]) -> Self { Self { items: items.iter(), } } pub fn is_empty(&self) -> bool { self.len() == 0 } } impl<'a> Iterator for DictKeyIterator<'a> { type Item = Option<&'a Expr>; fn next(&mut self) -> Option { self.items.next().map(DictItem::key) } fn last(mut self) -> Option { self.next_back() } fn size_hint(&self) -> (usize, Option) { self.items.size_hint() } } impl DoubleEndedIterator for DictKeyIterator<'_> { fn next_back(&mut self) -> Option { self.items.next_back().map(DictItem::key) } } impl FusedIterator for DictKeyIterator<'_> {} impl ExactSizeIterator for DictKeyIterator<'_> {} #[derive(Debug, Clone)] pub struct DictValueIterator<'a> { items: Iter<'a, DictItem>, } impl<'a> DictValueIterator<'a> { fn new(items: &'a [DictItem]) -> Self { Self { items: items.iter(), } } pub fn is_empty(&self) -> bool { self.len() == 0 } } impl<'a> Iterator for DictValueIterator<'a> { type Item = &'a Expr; fn next(&mut self) -> Option { self.items.next().map(DictItem::value) } fn last(mut self) -> Option { self.next_back() } fn size_hint(&self) -> (usize, Option) { self.items.size_hint() } } impl DoubleEndedIterator for DictValueIterator<'_> { fn next_back(&mut self) -> Option { self.items.next_back().map(DictItem::value) } } impl FusedIterator for DictValueIterator<'_> {} impl ExactSizeIterator for DictValueIterator<'_> {} impl ExprSet { pub fn iter(&self) -> std::slice::Iter<'_, Expr> { self.elts.iter() } pub fn len(&self) -> usize { self.elts.len() } pub fn is_empty(&self) -> bool { self.elts.is_empty() } } impl<'a> IntoIterator for &'a ExprSet { type IntoIter = std::slice::Iter<'a, Expr>; type Item = &'a Expr; fn into_iter(self) -> Self::IntoIter { self.iter() } } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct InterpolatedStringFormatSpec { pub range: TextRange, pub node_index: AtomicNodeIndex, pub elements: InterpolatedStringElements, } /// See also [FormattedValue](https://docs.python.org/3/library/ast.html#ast.FormattedValue) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct InterpolatedElement { pub range: TextRange, pub node_index: AtomicNodeIndex, pub expression: Box, pub debug_text: Option, pub conversion: ConversionFlag, pub format_spec: Option>, } /// An `FStringLiteralElement` with an empty `value` is an invalid f-string element. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct InterpolatedStringLiteralElement { pub range: TextRange, pub node_index: AtomicNodeIndex, pub value: Box, } impl InterpolatedStringLiteralElement { pub fn is_valid(&self) -> bool { !self.value.is_empty() } } impl Deref for InterpolatedStringLiteralElement { type Target = str; fn deref(&self) -> &Self::Target { &self.value } } /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] #[repr(i8)] #[expect(clippy::cast_possible_wrap)] pub enum ConversionFlag { /// No conversion None = -1, // CPython uses -1 /// Converts by calling `str()`. Str = b's' as i8, /// Converts by calling `ascii()`. Ascii = b'a' as i8, /// Converts by calling `repr()`. Repr = b'r' as i8, } impl ConversionFlag { pub fn to_byte(&self) -> Option { match self { Self::None => None, flag => Some(*flag as u8), } } pub fn to_char(&self) -> Option { Some(self.to_byte()? as char) } } /// The debug text of a self-documenting f-string expression (e.g., `f"{x=}"`). /// /// Stores the concatenation of leading text, expression source, and trailing text as a single /// [`CompactString`], with byte offsets to split them. The offsets are needed because the leading /// and trailing portions can contain non-whitespace characters (grouping parentheses, comments in /// triple-quoted f-strings) that cannot be distinguished from expression content by scanning. /// /// [`CompactString`]: compact_str::CompactString #[derive(Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct DebugText { /// The full text between the `{` and the conversion / `format_spec` / `}`. text: compact_str::CompactString, /// Byte offset where the expression source begins. expression_start: u32, /// Byte offset where the expression source ends. expression_end: u32, } impl std::fmt::Debug for DebugText { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DebugText") .field("leading", &self.leading()) .field("expression", &self.expression()) .field("trailing", &self.trailing()) .finish() } } impl DebugText { pub fn new(leading: &str, expression: &str, trailing: &str) -> Self { let expression_start = leading.text_len().to_u32(); let expression_end = expression_start + expression.text_len().to_u32(); let mut buf = compact_str::CompactString::with_capacity( leading.len() + expression.len() + trailing.len(), ); buf.push_str(leading); buf.push_str(expression); buf.push_str(trailing); Self { text: buf, expression_start, expression_end, } } /// The full debug text between the `{` and the conversion / `format_spec` / `}`. pub fn as_str(&self) -> &str { &self.text } /// The text between the `{` and the expression node. pub fn leading(&self) -> &str { &self.text[..self.expression_start as usize] } /// The source text of the expression (e.g., `0x0` in `f"{0x0=}"`). pub fn expression(&self) -> &str { &self.text[self.expression_start as usize..self.expression_end as usize] } /// The text between the expression and the conversion, the `format_spec`, or the `}`. pub fn trailing(&self) -> &str { &self.text[self.expression_end as usize..] } } impl ExprFString { /// Returns the single [`FString`] if the f-string isn't implicitly concatenated, [`None`] /// otherwise. pub const fn as_single_part_fstring(&self) -> Option<&FString> { match &self.value.inner { FStringValueInner::Single(FStringPart::FString(fstring)) => Some(fstring), _ => None, } } } /// The value representing an [`ExprFString`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct FStringValue { inner: FStringValueInner, } impl FStringValue { /// Creates a new f-string literal with a single [`FString`] part. pub fn single(value: FString) -> Self { Self { inner: FStringValueInner::Single(FStringPart::FString(value)), } } /// Creates a new f-string with the given values that represents an implicitly /// concatenated f-string. /// /// # Panics /// /// Panics if `values` has less than 2 elements. /// Use [`FStringValue::single`] instead. pub fn concatenated(values: Vec) -> Self { assert!( values.len() > 1, "Use `FStringValue::single` to create single-part f-strings" ); Self { inner: FStringValueInner::Concatenated(values), } } /// Returns `true` if the f-string is implicitly concatenated, `false` otherwise. pub fn is_implicit_concatenated(&self) -> bool { matches!(self.inner, FStringValueInner::Concatenated(_)) } /// Returns a slice of all the [`FStringPart`]s contained in this value. pub fn as_slice(&self) -> &[FStringPart] { match &self.inner { FStringValueInner::Single(part) => std::slice::from_ref(part), FStringValueInner::Concatenated(parts) => parts, } } /// Returns a mutable slice of all the [`FStringPart`]s contained in this value. fn as_mut_slice(&mut self) -> &mut [FStringPart] { match &mut self.inner { FStringValueInner::Single(part) => std::slice::from_mut(part), FStringValueInner::Concatenated(parts) => parts, } } /// Returns an iterator over all the [`FStringPart`]s contained in this value. pub fn iter(&self) -> Iter<'_, FStringPart> { self.as_slice().iter() } /// Returns an iterator over all the [`FStringPart`]s contained in this value /// that allows modification. pub fn iter_mut(&mut self) -> IterMut<'_, FStringPart> { self.as_mut_slice().iter_mut() } /// Returns an iterator over the [`StringLiteral`] parts contained in this value. /// /// Note that this doesn't recurse into the f-string parts. For example, /// /// ```python /// "foo" f"bar {x}" "baz" f"qux" /// ``` /// /// Here, the string literal parts returned would be `"foo"` and `"baz"`. pub fn literals(&self) -> impl Iterator { self.iter().filter_map(|part| part.as_literal()) } /// Returns an iterator over the [`FString`] parts contained in this value. /// /// Note that this doesn't recurse into the f-string parts. For example, /// /// ```python /// "foo" f"bar {x}" "baz" f"qux" /// ``` /// /// Here, the f-string parts returned would be `f"bar {x}"` and `f"qux"`. pub fn f_strings(&self) -> impl Iterator { self.iter().filter_map(|part| part.as_f_string()) } /// Returns an iterator over all the [`InterpolatedStringElement`] contained in this value. /// /// An f-string element is what makes up an [`FString`] i.e., it is either a /// string literal or an expression. In the following example, /// /// ```python /// "foo" f"bar {x}" "baz" f"qux" /// ``` /// /// The f-string elements returned would be string literal (`"bar "`), /// expression (`x`) and string literal (`"qux"`). pub fn elements(&self) -> impl Iterator { self.f_strings().flat_map(|fstring| fstring.elements.iter()) } /// Returns `true` if the node represents an empty f-string literal. /// /// Note that a [`FStringValue`] node will always have >= 1 [`FStringPart`]s inside it. /// This method checks whether the value of the concatenated parts is equal to the empty /// f-string, not whether the f-string has 0 parts inside it. pub fn is_empty_literal(&self) -> bool { match &self.inner { FStringValueInner::Single(fstring_part) => fstring_part.is_empty_literal(), FStringValueInner::Concatenated(fstring_parts) => { fstring_parts.iter().all(FStringPart::is_empty_literal) } } } } impl<'a> IntoIterator for &'a FStringValue { type Item = &'a FStringPart; type IntoIter = Iter<'a, FStringPart>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut FStringValue { type Item = &'a mut FStringPart; type IntoIter = IterMut<'a, FStringPart>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } /// An internal representation of [`FStringValue`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum FStringValueInner { /// A single f-string i.e., `f"foo"`. /// /// This is always going to be `FStringPart::FString` variant which is /// maintained by the `FStringValue::single` constructor. Single(FStringPart), /// An implicitly concatenated f-string i.e., `"foo" f"bar {x}"`. Concatenated(Vec), } /// An f-string part which is either a string literal or an f-string. #[derive(Clone, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum FStringPart { Literal(StringLiteral), FString(FString), } impl FStringPart { pub fn quote_style(&self) -> Quote { match self { Self::Literal(string_literal) => string_literal.flags.quote_style(), Self::FString(f_string) => f_string.flags.quote_style(), } } pub fn is_empty_literal(&self) -> bool { match &self { FStringPart::Literal(string_literal) => string_literal.value.is_empty(), FStringPart::FString(f_string) => f_string.elements.is_empty(), } } } impl Ranged for FStringPart { fn range(&self) -> TextRange { match self { FStringPart::Literal(string_literal) => string_literal.range(), FStringPart::FString(f_string) => f_string.range(), } } } impl ExprTString { /// Returns the single [`TString`] if the t-string isn't implicitly concatenated, [`None`] /// otherwise. pub const fn as_single_part_tstring(&self) -> Option<&TString> { match &self.value.inner { TStringValueInner::Single(tstring) => Some(tstring), TStringValueInner::Concatenated(_) => None, } } } /// The value representing an [`ExprTString`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TStringValue { inner: TStringValueInner, } impl TStringValue { /// Creates a new t-string literal with a single [`TString`] part. pub fn single(value: TString) -> Self { Self { inner: TStringValueInner::Single(value), } } /// Creates a new t-string with the given values that represents an implicitly /// concatenated t-string. /// /// # Panics /// /// Panics if `values` has less than 2 elements. /// Use [`TStringValue::single`] instead. pub fn concatenated(values: Vec) -> Self { assert!( values.len() > 1, "Use `TStringValue::single` to create single-part t-strings" ); Self { inner: TStringValueInner::Concatenated(values), } } /// Returns `true` if the t-string is implicitly concatenated, `false` otherwise. pub fn is_implicit_concatenated(&self) -> bool { matches!(self.inner, TStringValueInner::Concatenated(_)) } /// Returns a slice of all the [`TString`]s contained in this value. pub fn as_slice(&self) -> &[TString] { match &self.inner { TStringValueInner::Single(part) => std::slice::from_ref(part), TStringValueInner::Concatenated(parts) => parts, } } /// Returns a mutable slice of all the [`TString`]s contained in this value. fn as_mut_slice(&mut self) -> &mut [TString] { match &mut self.inner { TStringValueInner::Single(part) => std::slice::from_mut(part), TStringValueInner::Concatenated(parts) => parts, } } /// Returns an iterator over all the [`TString`]s contained in this value. pub fn iter(&self) -> Iter<'_, TString> { self.as_slice().iter() } /// Returns an iterator over all the [`TString`]s contained in this value /// that allows modification. pub fn iter_mut(&mut self) -> IterMut<'_, TString> { self.as_mut_slice().iter_mut() } /// Returns an iterator over all the [`InterpolatedStringElement`] contained in this value. /// /// An interpolated string element is what makes up an [`TString`] i.e., it is either a /// string literal or an interpolation. In the following example, /// /// ```python /// t"foo" t"bar {x}" t"baz" t"qux" /// ``` /// /// The interpolated string elements returned would be string literal (`"bar "`), /// interpolation (`x`) and string literal (`"qux"`). pub fn elements(&self) -> impl Iterator { self.iter().flat_map(|tstring| tstring.elements.iter()) } /// Returns `true` if the node represents an empty t-string in the /// sense that `__iter__` returns an empty iterable. /// /// Beware that empty t-strings are still truthy, i.e. `bool(t"") == True`. /// /// Note that a [`TStringValue`] node will always contain at least one /// [`TString`] node. This method checks whether each of the constituent /// t-strings (in an implicitly concatenated t-string) are empty /// in the above sense. pub fn is_empty_iterable(&self) -> bool { match &self.inner { TStringValueInner::Single(tstring) => tstring.is_empty(), TStringValueInner::Concatenated(tstrings) => tstrings.iter().all(TString::is_empty), } } } impl<'a> IntoIterator for &'a TStringValue { type Item = &'a TString; type IntoIter = Iter<'a, TString>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut TStringValue { type Item = &'a mut TString; type IntoIter = IterMut<'a, TString>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } /// An internal representation of [`TStringValue`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum TStringValueInner { /// A single t-string i.e., `t"foo"`. Single(TString), /// An implicitly concatenated t-string i.e., `t"foo" t"bar {x}"`. Concatenated(Vec), } pub trait StringFlags: Copy { /// Does the string use single or double quotes in its opener and closer? fn quote_style(self) -> Quote; fn triple_quotes(self) -> TripleQuotes; fn prefix(self) -> AnyStringPrefix; fn is_unclosed(self) -> bool; /// Is the string triple-quoted, i.e., /// does it begin and end with three consecutive quote characters? fn is_triple_quoted(self) -> bool { self.triple_quotes().is_yes() } /// A `str` representation of the quotes used to start and close. /// This does not include any prefixes the string has in its opener. fn quote_str(self) -> &'static str { match (self.triple_quotes(), self.quote_style()) { (TripleQuotes::Yes, Quote::Single) => "'''", (TripleQuotes::Yes, Quote::Double) => r#"""""#, (TripleQuotes::No, Quote::Single) => "'", (TripleQuotes::No, Quote::Double) => "\"", } } /// The length of the quotes used to start and close the string. /// This does not include the length of any prefixes the string has /// in its opener. fn quote_len(self) -> TextSize { if self.is_triple_quoted() { TextSize::new(3) } else { TextSize::new(1) } } /// The total length of the string's opener, /// i.e., the length of the prefixes plus the length /// of the quotes used to open the string. fn opener_len(self) -> TextSize { self.prefix().text_len() + self.quote_len() } /// The total length of the string's closer. /// This is always equal to `self.quote_len()`, except when the string is unclosed, /// in which case the length is zero. fn closer_len(self) -> TextSize { if self.is_unclosed() { TextSize::default() } else { self.quote_len() } } fn as_any_string_flags(self) -> AnyStringFlags { AnyStringFlags::new(self.prefix(), self.quote_style(), self.triple_quotes()) .with_unclosed(self.is_unclosed()) } fn display_contents(self, contents: &str) -> DisplayFlags<'_> { DisplayFlags { flags: self.as_any_string_flags(), contents, } } } pub struct DisplayFlags<'a> { flags: AnyStringFlags, contents: &'a str, } impl std::fmt::Display for DisplayFlags<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{prefix}{quote}{contents}{quote}", prefix = self.flags.prefix(), quote = self.flags.quote_str(), contents = self.contents ) } } bitflags! { #[derive(Default, Copy, Clone, PartialEq, Eq, Hash)] struct InterpolatedStringFlagsInner: u8 { /// The f-string uses double quotes (`"`) for its opener and closer. /// If this flag is not set, the f-string uses single quotes (`'`) /// for its opener and closer. const DOUBLE = 1 << 0; /// The f-string is triple-quoted: /// it begins and ends with three consecutive quote characters. /// For example: `f"""{bar}"""`. const TRIPLE_QUOTED = 1 << 1; /// The f-string has an `r` prefix, meaning it is a raw f-string /// with a lowercase 'r'. For example: `rf"{bar}"` const R_PREFIX_LOWER = 1 << 2; /// The f-string has an `R` prefix, meaning it is a raw f-string /// with an uppercase 'r'. For example: `Rf"{bar}"`. /// See https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings /// for why we track the casing of the `r` prefix, /// but not for any other prefix const R_PREFIX_UPPER = 1 << 3; /// The f-string is unclosed, meaning it is missing a closing quote. /// For example: `f"{bar` const UNCLOSED = 1 << 4; } } #[cfg(feature = "get-size")] impl get_size2::GetSize for InterpolatedStringFlagsInner {} /// Flags that can be queried to obtain information /// regarding the prefixes and quotes used for an f-string. /// /// Note: This is identical to [`TStringFlags`] except that /// the implementation of the `prefix` method of the /// [`StringFlags`] trait returns a variant of /// `AnyStringPrefix::Format`. /// /// ## Notes on usage /// /// If you're using a `Generator` from the `ruff_python_codegen` crate to generate a lint-rule fix /// from an existing f-string literal, consider passing along the [`FString::flags`] field. If you /// don't have an existing literal but have a `Checker` from the `ruff_linter` crate available, /// consider using `Checker::default_fstring_flags` to create instances of this struct; this method /// will properly handle nested f-strings. For usage that doesn't fit into one of these categories, /// the public constructor [`FStringFlags::empty`] can be used. #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct FStringFlags(InterpolatedStringFlagsInner); impl FStringFlags { /// Construct a new [`FStringFlags`] with **no flags set**. /// /// See [`FStringFlags::with_quote_style`], [`FStringFlags::with_triple_quotes`], and /// [`FStringFlags::with_prefix`] for ways of setting the quote style (single or double), /// enabling triple quotes, and adding prefixes (such as `r`), respectively. /// /// See the documentation for [`FStringFlags`] for additional caveats on this constructor, and /// situations in which alternative ways to construct this struct should be used, especially /// when writing lint rules. pub fn empty() -> Self { Self(InterpolatedStringFlagsInner::empty()) } #[must_use] pub fn with_quote_style(mut self, quote_style: Quote) -> Self { self.0.set( InterpolatedStringFlagsInner::DOUBLE, quote_style.is_double(), ); self } #[must_use] pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self { self.0.set( InterpolatedStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes(), ); self } #[must_use] pub fn with_unclosed(mut self, unclosed: bool) -> Self { self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed); self } #[must_use] pub fn with_prefix(mut self, prefix: FStringPrefix) -> Self { match prefix { FStringPrefix::Regular => Self( self.0 - InterpolatedStringFlagsInner::R_PREFIX_LOWER - InterpolatedStringFlagsInner::R_PREFIX_UPPER, ), FStringPrefix::Raw { uppercase_r } => { self.0 .set(InterpolatedStringFlagsInner::R_PREFIX_UPPER, uppercase_r); self.0 .set(InterpolatedStringFlagsInner::R_PREFIX_LOWER, !uppercase_r); self } } } pub const fn prefix(self) -> FStringPrefix { if self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_LOWER) { debug_assert!( !self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER) ); FStringPrefix::Raw { uppercase_r: false } } else if self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER) { FStringPrefix::Raw { uppercase_r: true } } else { FStringPrefix::Regular } } } // TODO(dylan): the documentation about using // `Checker::default_tstring_flags` is not yet // correct. This method does not yet exist because // introducing it would emit a dead code warning // until we call it in lint rules. /// Flags that can be queried to obtain information /// regarding the prefixes and quotes used for an f-string. /// /// Note: This is identical to [`FStringFlags`] except that /// the implementation of the `prefix` method of the /// [`StringFlags`] trait returns a variant of /// `AnyStringPrefix::Template`. /// /// ## Notes on usage /// /// If you're using a `Generator` from the `ruff_python_codegen` crate to generate a lint-rule fix /// from an existing t-string literal, consider passing along the [`FString::flags`] field. If you /// don't have an existing literal but have a `Checker` from the `ruff_linter` crate available, /// consider using `Checker::default_tstring_flags` to create instances of this struct; this method /// will properly handle nested t-strings. For usage that doesn't fit into one of these categories, /// the public constructor [`TStringFlags::empty`] can be used. #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TStringFlags(InterpolatedStringFlagsInner); impl TStringFlags { /// Construct a new [`TStringFlags`] with **no flags set**. /// /// See [`TStringFlags::with_quote_style`], [`TStringFlags::with_triple_quotes`], and /// [`TStringFlags::with_prefix`] for ways of setting the quote style (single or double), /// enabling triple quotes, and adding prefixes (such as `r`), respectively. /// /// See the documentation for [`TStringFlags`] for additional caveats on this constructor, and /// situations in which alternative ways to construct this struct should be used, especially /// when writing lint rules. pub fn empty() -> Self { Self(InterpolatedStringFlagsInner::empty()) } #[must_use] pub fn with_quote_style(mut self, quote_style: Quote) -> Self { self.0.set( InterpolatedStringFlagsInner::DOUBLE, quote_style.is_double(), ); self } #[must_use] pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self { self.0.set( InterpolatedStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes(), ); self } #[must_use] pub fn with_unclosed(mut self, unclosed: bool) -> Self { self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed); self } #[must_use] pub fn with_prefix(mut self, prefix: TStringPrefix) -> Self { match prefix { TStringPrefix::Regular => Self( self.0 - InterpolatedStringFlagsInner::R_PREFIX_LOWER - InterpolatedStringFlagsInner::R_PREFIX_UPPER, ), TStringPrefix::Raw { uppercase_r } => { self.0 .set(InterpolatedStringFlagsInner::R_PREFIX_UPPER, uppercase_r); self.0 .set(InterpolatedStringFlagsInner::R_PREFIX_LOWER, !uppercase_r); self } } } pub const fn prefix(self) -> TStringPrefix { if self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_LOWER) { debug_assert!( !self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER) ); TStringPrefix::Raw { uppercase_r: false } } else if self .0 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER) { TStringPrefix::Raw { uppercase_r: true } } else { TStringPrefix::Regular } } } impl StringFlags for FStringFlags { /// Return `true` if the f-string is triple-quoted, i.e., /// it begins and ends with three consecutive quote characters. /// For example: `f"""{bar}"""` fn triple_quotes(self) -> TripleQuotes { if self.0.contains(InterpolatedStringFlagsInner::TRIPLE_QUOTED) { TripleQuotes::Yes } else { TripleQuotes::No } } /// Return the quoting style (single or double quotes) /// used by the f-string's opener and closer: /// - `f"{"a"}"` -> `QuoteStyle::Double` /// - `f'{"a"}'` -> `QuoteStyle::Single` fn quote_style(self) -> Quote { if self.0.contains(InterpolatedStringFlagsInner::DOUBLE) { Quote::Double } else { Quote::Single } } fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Format(self.prefix()) } fn is_unclosed(self) -> bool { self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED) } } impl fmt::Debug for FStringFlags { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FStringFlags") .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("unclosed", &self.is_unclosed()) .finish() } } impl StringFlags for TStringFlags { /// Return `true` if the t-string is triple-quoted, i.e., /// it begins and ends with three consecutive quote characters. /// For example: `t"""{bar}"""` fn triple_quotes(self) -> TripleQuotes { if self.0.contains(InterpolatedStringFlagsInner::TRIPLE_QUOTED) { TripleQuotes::Yes } else { TripleQuotes::No } } /// Return the quoting style (single or double quotes) /// used by the t-string's opener and closer: /// - `t"{"a"}"` -> `QuoteStyle::Double` /// - `t'{"a"}'` -> `QuoteStyle::Single` fn quote_style(self) -> Quote { if self.0.contains(InterpolatedStringFlagsInner::DOUBLE) { Quote::Double } else { Quote::Single } } fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Template(self.prefix()) } fn is_unclosed(self) -> bool { self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED) } } impl fmt::Debug for TStringFlags { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TStringFlags") .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("unclosed", &self.is_unclosed()) .finish() } } /// An AST node that represents a single f-string which is part of an [`ExprFString`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct FString { pub range: TextRange, pub node_index: AtomicNodeIndex, pub elements: InterpolatedStringElements, pub flags: FStringFlags, } impl From for Expr { fn from(payload: FString) -> Self { ExprFString { node_index: payload.node_index.clone(), range: payload.range, value: FStringValue::single(payload), } .into() } } /// A newtype wrapper around a list of [`InterpolatedStringElement`]. #[derive(Clone, Default, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct InterpolatedStringElements(Vec); impl InterpolatedStringElements { /// Returns an iterator over all the [`InterpolatedStringLiteralElement`] nodes contained in this f-string. pub fn literals(&self) -> impl Iterator { self.iter().filter_map(|element| element.as_literal()) } /// Returns an iterator over all the [`InterpolatedElement`] nodes contained in this f-string. pub fn interpolations(&self) -> impl Iterator { self.iter().filter_map(|element| element.as_interpolation()) } } impl From> for InterpolatedStringElements { fn from(elements: Vec) -> Self { InterpolatedStringElements(elements) } } impl<'a> IntoIterator for &'a InterpolatedStringElements { type IntoIter = Iter<'a, InterpolatedStringElement>; type Item = &'a InterpolatedStringElement; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut InterpolatedStringElements { type IntoIter = IterMut<'a, InterpolatedStringElement>; type Item = &'a mut InterpolatedStringElement; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl Deref for InterpolatedStringElements { type Target = [InterpolatedStringElement]; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for InterpolatedStringElements { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl fmt::Debug for InterpolatedStringElements { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } /// An AST node that represents a single t-string which is part of an [`ExprTString`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TString { pub range: TextRange, pub node_index: AtomicNodeIndex, pub elements: InterpolatedStringElements, pub flags: TStringFlags, } impl TString { pub fn quote_style(&self) -> Quote { self.flags.quote_style() } pub fn is_empty(&self) -> bool { self.elements.is_empty() } } impl From for Expr { fn from(payload: TString) -> Self { ExprTString { node_index: payload.node_index.clone(), range: payload.range, value: TStringValue::single(payload), } .into() } } impl ExprStringLiteral { /// Return `Some(literal)` if the string only consists of a single `StringLiteral` part /// (indicating that it is not implicitly concatenated). Otherwise, return `None`. pub fn as_single_part_string(&self) -> Option<&StringLiteral> { match &self.value.inner { StringLiteralValueInner::Single(value) => Some(value), StringLiteralValueInner::Concatenated(_) => None, } } } impl Ranged for ExprCall { fn range(&self) -> TextRange { TextRange::new(self.range_start, self.arguments.end()) } } #[expect( clippy::missing_fields_in_debug, reason = "`range_start` is represented by the reconstructed `range` field" )] impl fmt::Debug for ExprCall { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter .debug_struct("ExprCall") .field("node_index", &self.node_index) .field("range", &self.range()) .field("func", &self.func) .field("arguments", &self.arguments) .finish() } } /// The value representing a [`ExprStringLiteral`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StringLiteralValue { inner: StringLiteralValueInner, } impl StringLiteralValue { /// Creates a new string literal with a single [`StringLiteral`] part. pub fn single(string: StringLiteral) -> Self { Self { inner: StringLiteralValueInner::Single(string), } } /// Returns the [`StringLiteralFlags`] associated with this string literal. /// /// For an implicitly concatenated string, it returns the flags for the first literal. pub fn first_literal_flags(&self) -> StringLiteralFlags { self.iter() .next() .expect( "There should always be at least one string literal in an `ExprStringLiteral` node", ) .flags } /// Creates a new string literal with the given values that represents an /// implicitly concatenated strings. /// /// # Panics /// /// Panics if `strings` has less than 2 elements. /// Use [`StringLiteralValue::single`] instead. pub fn concatenated(strings: Vec) -> Self { assert!( strings.len() > 1, "Use `StringLiteralValue::single` to create single-part strings" ); Self { inner: StringLiteralValueInner::Concatenated(Box::new(ConcatenatedStringLiteral { strings, value: OnceLock::new(), })), } } /// Returns `true` if the string literal is implicitly concatenated. pub const fn is_implicit_concatenated(&self) -> bool { matches!(self.inner, StringLiteralValueInner::Concatenated(_)) } /// Returns `true` if the string literal has a `u` prefix, e.g. `u"foo"`. /// /// Although all strings in Python 3 are valid unicode (and the `u` prefix /// is only retained for backwards compatibility), these strings are known as /// "unicode strings". /// /// For an implicitly concatenated string, it returns `true` only if the first /// [`StringLiteral`] has the `u` prefix. pub fn is_unicode(&self) -> bool { self.iter() .next() .is_some_and(|part| part.flags.prefix().is_unicode()) } /// Returns a slice of all the [`StringLiteral`] parts contained in this value. pub fn as_slice(&self) -> &[StringLiteral] { match &self.inner { StringLiteralValueInner::Single(value) => std::slice::from_ref(value), StringLiteralValueInner::Concatenated(value) => value.strings.as_slice(), } } /// Returns a mutable slice of all the [`StringLiteral`] parts contained in this value. fn as_mut_slice(&mut self) -> &mut [StringLiteral] { match &mut self.inner { StringLiteralValueInner::Single(value) => std::slice::from_mut(value), StringLiteralValueInner::Concatenated(value) => value.strings.as_mut_slice(), } } /// Returns an iterator over all the [`StringLiteral`] parts contained in this value. pub fn iter(&self) -> Iter<'_, StringLiteral> { self.as_slice().iter() } /// Returns an iterator over all the [`StringLiteral`] parts contained in this value /// that allows modification. pub fn iter_mut(&mut self) -> IterMut<'_, StringLiteral> { self.as_mut_slice().iter_mut() } /// Returns `true` if the node represents an empty string. /// /// Note that a [`StringLiteralValue`] node will always have >=1 [`StringLiteral`] parts /// inside it. This method checks whether the value of the concatenated parts is equal /// to the empty string, not whether the string has 0 parts inside it. pub fn is_empty(&self) -> bool { self.len() == 0 } /// Returns the total length of the string literal value, in bytes, not /// [`char`]s or graphemes. pub fn len(&self) -> usize { self.iter().fold(0, |acc, part| acc + part.value.len()) } /// Returns an iterator over the [`char`]s of each string literal part. pub fn chars(&self) -> impl Iterator + Clone + '_ { self.iter().flat_map(|part| part.value.chars()) } /// Returns the concatenated string value as a [`str`]. /// /// Note that this will perform an allocation on the first invocation if the /// string value is implicitly concatenated. pub fn to_str(&self) -> &str { match &self.inner { StringLiteralValueInner::Single(value) => value.as_str(), StringLiteralValueInner::Concatenated(value) => value.to_str(), } } } impl<'a> IntoIterator for &'a StringLiteralValue { type Item = &'a StringLiteral; type IntoIter = Iter<'a, StringLiteral>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut StringLiteralValue { type Item = &'a mut StringLiteral; type IntoIter = IterMut<'a, StringLiteral>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl PartialEq for StringLiteralValue { fn eq(&self, other: &str) -> bool { if self.len() != other.len() { return false; } // The `zip` here is safe because we have checked the length of both parts. self.chars().zip(other.chars()).all(|(c1, c2)| c1 == c2) } } impl fmt::Display for StringLiteralValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.to_str()) } } /// An internal representation of [`StringLiteralValue`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum StringLiteralValueInner { /// A single string literal i.e., `"foo"`. Single(StringLiteral), /// An implicitly concatenated string literals i.e., `"foo" "bar"`. Concatenated(Box), } bitflags! { #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)] struct StringLiteralFlagsInner: u8 { /// The string uses double quotes (e.g. `"foo"`). /// If this flag is not set, the string uses single quotes (`'foo'`). const DOUBLE = 1 << 0; /// The string is triple-quoted (`"""foo"""`): /// it begins and ends with three consecutive quote characters. const TRIPLE_QUOTED = 1 << 1; /// The string has a `u` or `U` prefix, e.g. `u"foo"`. /// While this prefix is a no-op at runtime, /// strings with this prefix can have no other prefixes set; /// it is therefore invalid for this flag to be set /// if `R_PREFIX` is also set. const U_PREFIX = 1 << 2; /// The string has an `r` prefix, meaning it is a raw string /// with a lowercase 'r' (e.g. `r"foo\."`). /// It is invalid to set this flag if `U_PREFIX` is also set. const R_PREFIX_LOWER = 1 << 3; /// The string has an `R` prefix, meaning it is a raw string /// with an uppercase 'R' (e.g. `R'foo\d'`). /// See https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings /// for why we track the casing of the `r` prefix, /// but not for any other prefix const R_PREFIX_UPPER = 1 << 4; /// The string was deemed invalid by the parser. const INVALID = 1 << 5; /// The string literal misses the matching closing quote(s). const UNCLOSED = 1 << 6; } } #[cfg(feature = "get-size")] impl get_size2::GetSize for StringLiteralFlagsInner {} /// Flags that can be queried to obtain information /// regarding the prefixes and quotes used for a string literal. /// /// ## Notes on usage /// /// If you're using a `Generator` from the `ruff_python_codegen` crate to generate a lint-rule fix /// from an existing string literal, consider passing along the [`StringLiteral::flags`] field or /// the result of the [`StringLiteralValue::first_literal_flags`] method. If you don't have an /// existing string but have a `Checker` from the `ruff_linter` crate available, consider using /// `Checker::default_string_flags` to create instances of this struct; this method will properly /// handle surrounding f-strings. For usage that doesn't fit into one of these categories, the /// public constructor [`StringLiteralFlags::empty`] can be used. #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StringLiteralFlags(StringLiteralFlagsInner); impl StringLiteralFlags { /// Construct a new [`StringLiteralFlags`] with **no flags set**. /// /// See [`StringLiteralFlags::with_quote_style`], [`StringLiteralFlags::with_triple_quotes`], /// and [`StringLiteralFlags::with_prefix`] for ways of setting the quote style (single or /// double), enabling triple quotes, and adding prefixes (such as `r` or `u`), respectively. /// /// See the documentation for [`StringLiteralFlags`] for additional caveats on this constructor, /// and situations in which alternative ways to construct this struct should be used, especially /// when writing lint rules. pub fn empty() -> Self { Self(StringLiteralFlagsInner::empty()) } #[must_use] pub fn with_quote_style(mut self, quote_style: Quote) -> Self { self.0 .set(StringLiteralFlagsInner::DOUBLE, quote_style.is_double()); self } #[must_use] pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self { self.0.set( StringLiteralFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes(), ); self } #[must_use] pub fn with_unclosed(mut self, unclosed: bool) -> Self { self.0.set(StringLiteralFlagsInner::UNCLOSED, unclosed); self } #[must_use] pub fn with_prefix(self, prefix: StringLiteralPrefix) -> Self { let StringLiteralFlags(flags) = self; match prefix { StringLiteralPrefix::Empty => Self( flags - StringLiteralFlagsInner::R_PREFIX_LOWER - StringLiteralFlagsInner::R_PREFIX_UPPER - StringLiteralFlagsInner::U_PREFIX, ), StringLiteralPrefix::Raw { uppercase: false } => Self( (flags | StringLiteralFlagsInner::R_PREFIX_LOWER) - StringLiteralFlagsInner::R_PREFIX_UPPER - StringLiteralFlagsInner::U_PREFIX, ), StringLiteralPrefix::Raw { uppercase: true } => Self( (flags | StringLiteralFlagsInner::R_PREFIX_UPPER) - StringLiteralFlagsInner::R_PREFIX_LOWER - StringLiteralFlagsInner::U_PREFIX, ), StringLiteralPrefix::Unicode => Self( (flags | StringLiteralFlagsInner::U_PREFIX) - StringLiteralFlagsInner::R_PREFIX_LOWER - StringLiteralFlagsInner::R_PREFIX_UPPER, ), } } #[must_use] pub fn with_invalid(mut self) -> Self { self.0 |= StringLiteralFlagsInner::INVALID; self } /// Returns `true` if the parser deemed the string literal invalid. pub const fn is_invalid(self) -> bool { self.0.contains(StringLiteralFlagsInner::INVALID) } pub const fn prefix(self) -> StringLiteralPrefix { if self.0.contains(StringLiteralFlagsInner::U_PREFIX) { debug_assert!( !self.0.intersects( StringLiteralFlagsInner::R_PREFIX_LOWER .union(StringLiteralFlagsInner::R_PREFIX_UPPER) ) ); StringLiteralPrefix::Unicode } else if self.0.contains(StringLiteralFlagsInner::R_PREFIX_LOWER) { debug_assert!(!self.0.contains(StringLiteralFlagsInner::R_PREFIX_UPPER)); StringLiteralPrefix::Raw { uppercase: false } } else if self.0.contains(StringLiteralFlagsInner::R_PREFIX_UPPER) { StringLiteralPrefix::Raw { uppercase: true } } else { StringLiteralPrefix::Empty } } } impl StringFlags for StringLiteralFlags { /// Return the quoting style (single or double quotes) /// used by the string's opener and closer: /// - `"a"` -> `QuoteStyle::Double` /// - `'a'` -> `QuoteStyle::Single` fn quote_style(self) -> Quote { if self.0.contains(StringLiteralFlagsInner::DOUBLE) { Quote::Double } else { Quote::Single } } /// Return `true` if the string is triple-quoted, i.e., /// it begins and ends with three consecutive quote characters. /// For example: `"""bar"""` fn triple_quotes(self) -> TripleQuotes { if self.0.contains(StringLiteralFlagsInner::TRIPLE_QUOTED) { TripleQuotes::Yes } else { TripleQuotes::No } } fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Regular(self.prefix()) } fn is_unclosed(self) -> bool { self.0.intersects(StringLiteralFlagsInner::UNCLOSED) } } impl fmt::Debug for StringLiteralFlags { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("StringLiteralFlags") .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("unclosed", &self.is_unclosed()) .finish() } } /// An AST node that represents a single string literal which is part of an /// [`ExprStringLiteral`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct StringLiteral { pub range: TextRange, pub node_index: AtomicNodeIndex, pub value: Box, pub flags: StringLiteralFlags, } impl Deref for StringLiteral { type Target = str; fn deref(&self) -> &Self::Target { &self.value } } impl StringLiteral { /// Extracts a string slice containing the entire `String`. pub fn as_str(&self) -> &str { self } /// Creates an invalid string literal with the given range. pub fn invalid(range: TextRange) -> Self { Self { range, value: "".into(), node_index: AtomicNodeIndex::NONE, flags: StringLiteralFlags::empty().with_invalid(), } } /// The range of the string literal's contents. /// /// This excludes any prefixes, opening quotes or closing quotes. pub fn content_range(&self) -> TextRange { TextRange::new( self.start() + self.flags.opener_len(), self.end() - self.flags.closer_len(), ) } } impl From for Expr { fn from(payload: StringLiteral) -> Self { ExprStringLiteral { range: payload.range, node_index: AtomicNodeIndex::NONE, value: StringLiteralValue::single(payload), } .into() } } /// An internal representation of [`StringLiteral`] that represents an /// implicitly concatenated string. #[derive(Clone)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] struct ConcatenatedStringLiteral { /// The individual [`StringLiteral`] parts that make up the concatenated string. strings: Vec, /// The concatenated string value. value: OnceLock>, } impl ConcatenatedStringLiteral { /// Extracts a string slice containing the entire concatenated string. fn to_str(&self) -> &str { self.value.get_or_init(|| { let concatenated: String = self.strings.iter().map(StringLiteral::as_str).collect(); concatenated.into_boxed_str() }) } } impl PartialEq for ConcatenatedStringLiteral { fn eq(&self, other: &Self) -> bool { if self.strings.len() != other.strings.len() { return false; } // The `zip` here is safe because we have checked the length of both parts. self.strings .iter() .zip(&other.strings) .all(|(s1, s2)| s1 == s2) } } impl Debug for ConcatenatedStringLiteral { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ConcatenatedStringLiteral") .field("strings", &self.strings) .field("value", &self.to_str()) .finish() } } impl ExprBytesLiteral { /// Return `Some(literal)` if the bytestring only consists of a single `BytesLiteral` part /// (indicating that it is not implicitly concatenated). Otherwise, return `None`. pub const fn as_single_part_bytestring(&self) -> Option<&BytesLiteral> { match &self.value.inner { BytesLiteralValueInner::Single(value) => Some(value), BytesLiteralValueInner::Concatenated(_) => None, } } } /// The value representing a [`ExprBytesLiteral`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct BytesLiteralValue { inner: BytesLiteralValueInner, } impl BytesLiteralValue { /// Create a new bytestring literal with a single [`BytesLiteral`] part. pub fn single(value: BytesLiteral) -> Self { Self { inner: BytesLiteralValueInner::Single(value), } } /// Creates a new bytestring literal with the given values that represents an /// implicitly concatenated bytestring. /// /// # Panics /// /// Panics if `values` has less than 2 elements. /// Use [`BytesLiteralValue::single`] instead. pub fn concatenated(values: Vec) -> Self { assert!( values.len() > 1, "Use `BytesLiteralValue::single` to create single-part bytestrings" ); Self { inner: BytesLiteralValueInner::Concatenated(values), } } /// Returns `true` if the bytestring is implicitly concatenated. pub const fn is_implicit_concatenated(&self) -> bool { matches!(self.inner, BytesLiteralValueInner::Concatenated(_)) } /// Returns a slice of all the [`BytesLiteral`] parts contained in this value. pub fn as_slice(&self) -> &[BytesLiteral] { match &self.inner { BytesLiteralValueInner::Single(value) => std::slice::from_ref(value), BytesLiteralValueInner::Concatenated(value) => value.as_slice(), } } /// Returns a mutable slice of all the [`BytesLiteral`] parts contained in this value. fn as_mut_slice(&mut self) -> &mut [BytesLiteral] { match &mut self.inner { BytesLiteralValueInner::Single(value) => std::slice::from_mut(value), BytesLiteralValueInner::Concatenated(value) => value.as_mut_slice(), } } /// Returns an iterator over all the [`BytesLiteral`] parts contained in this value. pub fn iter(&self) -> Iter<'_, BytesLiteral> { self.as_slice().iter() } /// Returns an iterator over all the [`BytesLiteral`] parts contained in this value /// that allows modification. pub fn iter_mut(&mut self) -> IterMut<'_, BytesLiteral> { self.as_mut_slice().iter_mut() } /// Return `true` if the node represents an empty bytestring. /// /// Note that a [`BytesLiteralValue`] node will always have >=1 [`BytesLiteral`] parts /// inside it. This method checks whether the value of the concatenated parts is equal /// to the empty bytestring, not whether the bytestring has 0 parts inside it. pub fn is_empty(&self) -> bool { self.iter().all(|part| part.is_empty()) } /// Returns the length of the concatenated bytestring. pub fn len(&self) -> usize { self.iter().map(|part| part.len()).sum() } /// Returns an iterator over the bytes of the concatenated bytestring. pub fn bytes(&self) -> impl Iterator + '_ { self.iter().flat_map(|part| part.as_slice().iter().copied()) } } impl<'a> IntoIterator for &'a BytesLiteralValue { type Item = &'a BytesLiteral; type IntoIter = Iter<'a, BytesLiteral>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut BytesLiteralValue { type Item = &'a mut BytesLiteral; type IntoIter = IterMut<'a, BytesLiteral>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl PartialEq<[u8]> for BytesLiteralValue { fn eq(&self, other: &[u8]) -> bool { if self.len() != other.len() { return false; } // The `zip` here is safe because we have checked the length of both parts. self.bytes() .zip(other.iter().copied()) .all(|(b1, b2)| b1 == b2) } } impl<'a> From<&'a BytesLiteralValue> for Cow<'a, [u8]> { fn from(value: &'a BytesLiteralValue) -> Self { match &value.inner { BytesLiteralValueInner::Single(BytesLiteral { value: bytes_value, .. }) => Cow::from(bytes_value.as_ref()), BytesLiteralValueInner::Concatenated(bytes_literal_vec) => Cow::Owned( bytes_literal_vec .iter() .flat_map(|bytes_literal| bytes_literal.value.to_vec()) .collect::>(), ), } } } /// An internal representation of [`BytesLiteralValue`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum BytesLiteralValueInner { /// A single-part bytestring literal i.e., `b"foo"`. Single(BytesLiteral), /// An implicitly concatenated bytestring literal i.e., `b"foo" b"bar"`. Concatenated(Vec), } bitflags! { #[derive(Default, Copy, Clone, PartialEq, Eq, Hash)] struct BytesLiteralFlagsInner: u8 { /// The bytestring uses double quotes (e.g. `b"foo"`). /// If this flag is not set, the bytestring uses single quotes (e.g. `b'foo'`). const DOUBLE = 1 << 0; /// The bytestring is triple-quoted (e.g. `b"""foo"""`): /// it begins and ends with three consecutive quote characters. const TRIPLE_QUOTED = 1 << 1; /// The bytestring has an `r` prefix (e.g. `rb"foo"`), /// meaning it is a raw bytestring with a lowercase 'r'. const R_PREFIX_LOWER = 1 << 2; /// The bytestring has an `R` prefix (e.g. `Rb"foo"`), /// meaning it is a raw bytestring with an uppercase 'R'. /// See https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings /// for why we track the casing of the `r` prefix, but not for any other prefix const R_PREFIX_UPPER = 1 << 3; /// The bytestring was deemed invalid by the parser. const INVALID = 1 << 4; /// The byte string misses the matching closing quote(s). const UNCLOSED = 1 << 5; } } #[cfg(feature = "get-size")] impl get_size2::GetSize for BytesLiteralFlagsInner {} /// Flags that can be queried to obtain information /// regarding the prefixes and quotes used for a bytes literal. /// /// ## Notes on usage /// /// If you're using a `Generator` from the `ruff_python_codegen` crate to generate a lint-rule fix /// from an existing bytes literal, consider passing along the [`BytesLiteral::flags`] field. If /// you don't have an existing literal but have a `Checker` from the `ruff_linter` crate available, /// consider using `Checker::default_bytes_flags` to create instances of this struct; this method /// will properly handle surrounding f-strings. For usage that doesn't fit into one of these /// categories, the public constructor [`BytesLiteralFlags::empty`] can be used. #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct BytesLiteralFlags(BytesLiteralFlagsInner); impl BytesLiteralFlags { /// Construct a new [`BytesLiteralFlags`] with **no flags set**. /// /// See [`BytesLiteralFlags::with_quote_style`], [`BytesLiteralFlags::with_triple_quotes`], and /// [`BytesLiteralFlags::with_prefix`] for ways of setting the quote style (single or double), /// enabling triple quotes, and adding prefixes (such as `r`), respectively. /// /// See the documentation for [`BytesLiteralFlags`] for additional caveats on this constructor, /// and situations in which alternative ways to construct this struct should be used, especially /// when writing lint rules. pub fn empty() -> Self { Self(BytesLiteralFlagsInner::empty()) } #[must_use] pub fn with_quote_style(mut self, quote_style: Quote) -> Self { self.0 .set(BytesLiteralFlagsInner::DOUBLE, quote_style.is_double()); self } #[must_use] pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self { self.0.set( BytesLiteralFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes(), ); self } #[must_use] pub fn with_unclosed(mut self, unclosed: bool) -> Self { self.0.set(BytesLiteralFlagsInner::UNCLOSED, unclosed); self } #[must_use] pub fn with_prefix(mut self, prefix: ByteStringPrefix) -> Self { match prefix { ByteStringPrefix::Regular => { self.0 -= BytesLiteralFlagsInner::R_PREFIX_LOWER; self.0 -= BytesLiteralFlagsInner::R_PREFIX_UPPER; } ByteStringPrefix::Raw { uppercase_r } => { self.0 .set(BytesLiteralFlagsInner::R_PREFIX_UPPER, uppercase_r); self.0 .set(BytesLiteralFlagsInner::R_PREFIX_LOWER, !uppercase_r); } } self } #[must_use] pub fn with_invalid(mut self) -> Self { self.0 |= BytesLiteralFlagsInner::INVALID; self } /// Returns `true` if the parser deemed the bytes literal invalid. pub const fn is_invalid(self) -> bool { self.0.contains(BytesLiteralFlagsInner::INVALID) } pub const fn prefix(self) -> ByteStringPrefix { if self.0.contains(BytesLiteralFlagsInner::R_PREFIX_LOWER) { debug_assert!(!self.0.contains(BytesLiteralFlagsInner::R_PREFIX_UPPER)); ByteStringPrefix::Raw { uppercase_r: false } } else if self.0.contains(BytesLiteralFlagsInner::R_PREFIX_UPPER) { ByteStringPrefix::Raw { uppercase_r: true } } else { ByteStringPrefix::Regular } } } impl StringFlags for BytesLiteralFlags { /// Return `true` if the bytestring is triple-quoted, i.e., /// it begins and ends with three consecutive quote characters. /// For example: `b"""{bar}"""` fn triple_quotes(self) -> TripleQuotes { if self.0.contains(BytesLiteralFlagsInner::TRIPLE_QUOTED) { TripleQuotes::Yes } else { TripleQuotes::No } } /// Return the quoting style (single or double quotes) /// used by the bytestring's opener and closer: /// - `b"a"` -> `QuoteStyle::Double` /// - `b'a'` -> `QuoteStyle::Single` fn quote_style(self) -> Quote { if self.0.contains(BytesLiteralFlagsInner::DOUBLE) { Quote::Double } else { Quote::Single } } fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Bytes(self.prefix()) } fn is_unclosed(self) -> bool { self.0.intersects(BytesLiteralFlagsInner::UNCLOSED) } } impl fmt::Debug for BytesLiteralFlags { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("BytesLiteralFlags") .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("unclosed", &self.is_unclosed()) .finish() } } /// An AST node that represents a single bytes literal which is part of an /// [`ExprBytesLiteral`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct BytesLiteral { pub range: TextRange, pub node_index: AtomicNodeIndex, pub value: Box<[u8]>, pub flags: BytesLiteralFlags, } impl Deref for BytesLiteral { type Target = [u8]; fn deref(&self) -> &Self::Target { &self.value } } impl BytesLiteral { /// Extracts a byte slice containing the entire [`BytesLiteral`]. pub fn as_slice(&self) -> &[u8] { self } /// Creates a new invalid bytes literal with the given range. pub fn invalid(range: TextRange) -> Self { Self { range, value: Box::new([]), node_index: AtomicNodeIndex::NONE, flags: BytesLiteralFlags::empty().with_invalid(), } } /// The range of the byte literal's contents. /// /// This excludes any prefixes, opening quotes or closing quotes. pub fn content_range(&self) -> TextRange { TextRange::new( self.start() + self.flags.opener_len(), self.end() - self.flags.closer_len(), ) } } impl From for Expr { fn from(payload: BytesLiteral) -> Self { ExprBytesLiteral { range: payload.range, node_index: AtomicNodeIndex::NONE, value: BytesLiteralValue::single(payload), } .into() } } bitflags! { /// Flags that can be queried to obtain information /// regarding the prefixes and quotes used for a string literal. /// /// Note that not all of these flags can be validly combined -- e.g., /// it is invalid to combine the `U_PREFIX` flag with any other /// of the `*_PREFIX` flags. As such, the recommended way to set the /// prefix flags is by calling the `as_flags()` method on the /// `StringPrefix` enum. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] struct AnyStringFlagsInner: u16 { /// The string uses double quotes (`"`). /// If this flag is not set, the string uses single quotes (`'`). const DOUBLE = 1 << 0; /// The string is triple-quoted: /// it begins and ends with three consecutive quote characters. const TRIPLE_QUOTED = 1 << 1; /// The string has a `u` or `U` prefix. /// While this prefix is a no-op at runtime, /// strings with this prefix can have no other prefixes set. const U_PREFIX = 1 << 2; /// The string has a `b` or `B` prefix. /// This means that the string is a sequence of `int`s at runtime, /// rather than a sequence of `str`s. /// Strings with this flag can also be raw strings, /// but can have no other prefixes. const B_PREFIX = 1 << 3; /// The string has a `f` or `F` prefix, meaning it is an f-string. /// F-strings can also be raw strings, /// but can have no other prefixes. const F_PREFIX = 1 << 4; /// The string has a `t` or `T` prefix, meaning it is a t-string. /// T-strings can also be raw strings, /// but can have no other prefixes. const T_PREFIX = 1 << 5; /// The string has an `r` prefix, meaning it is a raw string. /// F-strings and byte-strings can be raw, /// as can strings with no other prefixes. /// U-strings cannot be raw. const R_PREFIX_LOWER = 1 << 6; /// The string has an `R` prefix, meaning it is a raw string. /// The casing of the `r`/`R` has no semantic significance at runtime; /// see https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings /// for why we track the casing of the `r` prefix, /// but not for any other prefix const R_PREFIX_UPPER = 1 << 7; /// String without matching closing quote(s). const UNCLOSED = 1 << 8; } } #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct AnyStringFlags(AnyStringFlagsInner); impl AnyStringFlags { #[must_use] pub fn with_prefix(mut self, prefix: AnyStringPrefix) -> Self { self.0 |= match prefix { // regular strings AnyStringPrefix::Regular(StringLiteralPrefix::Empty) => AnyStringFlagsInner::empty(), AnyStringPrefix::Regular(StringLiteralPrefix::Unicode) => AnyStringFlagsInner::U_PREFIX, AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }) => { AnyStringFlagsInner::R_PREFIX_LOWER } AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: true }) => { AnyStringFlagsInner::R_PREFIX_UPPER } // bytestrings AnyStringPrefix::Bytes(ByteStringPrefix::Regular) => AnyStringFlagsInner::B_PREFIX, AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: false }) => { AnyStringFlagsInner::B_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER) } AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: true }) => { AnyStringFlagsInner::B_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER) } // f-strings AnyStringPrefix::Format(FStringPrefix::Regular) => AnyStringFlagsInner::F_PREFIX, AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: false }) => { AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER) } AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: true }) => { AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER) } // t-strings AnyStringPrefix::Template(TStringPrefix::Regular) => AnyStringFlagsInner::T_PREFIX, AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: false }) => { AnyStringFlagsInner::T_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER) } AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: true }) => { AnyStringFlagsInner::T_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER) } }; self } pub fn new(prefix: AnyStringPrefix, quotes: Quote, triple_quotes: TripleQuotes) -> Self { Self(AnyStringFlagsInner::empty()) .with_prefix(prefix) .with_quote_style(quotes) .with_triple_quotes(triple_quotes) } /// Does the string have a `u` or `U` prefix? pub const fn is_u_string(self) -> bool { self.0.contains(AnyStringFlagsInner::U_PREFIX) } /// Does the string have an `r` or `R` prefix? pub const fn is_raw_string(self) -> bool { self.0.intersects( AnyStringFlagsInner::R_PREFIX_LOWER.union(AnyStringFlagsInner::R_PREFIX_UPPER), ) } /// Does the string have an `f`,`F`,`t`, or `T` prefix? pub const fn is_interpolated_string(self) -> bool { self.0 .intersects(AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::T_PREFIX)) } /// Does the string have a `b` or `B` prefix? pub const fn is_byte_string(self) -> bool { self.0.contains(AnyStringFlagsInner::B_PREFIX) } #[must_use] pub fn with_quote_style(mut self, quotes: Quote) -> Self { match quotes { Quote::Double => self.0 |= AnyStringFlagsInner::DOUBLE, Quote::Single => self.0 -= AnyStringFlagsInner::DOUBLE, } self } #[must_use] pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self { self.0 .set(AnyStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes()); self } #[must_use] pub fn with_unclosed(mut self, unclosed: bool) -> Self { self.0.set(AnyStringFlagsInner::UNCLOSED, unclosed); self } } impl StringFlags for AnyStringFlags { /// Does the string use single or double quotes in its opener and closer? fn quote_style(self) -> Quote { if self.0.contains(AnyStringFlagsInner::DOUBLE) { Quote::Double } else { Quote::Single } } fn triple_quotes(self) -> TripleQuotes { if self.0.contains(AnyStringFlagsInner::TRIPLE_QUOTED) { TripleQuotes::Yes } else { TripleQuotes::No } } fn prefix(self) -> AnyStringPrefix { let AnyStringFlags(flags) = self; // f-strings if flags.contains(AnyStringFlagsInner::F_PREFIX) { if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) { return AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: false }); } if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) { return AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: true }); } return AnyStringPrefix::Format(FStringPrefix::Regular); } // t-strings if flags.contains(AnyStringFlagsInner::T_PREFIX) { if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) { return AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: false }); } if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) { return AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: true }); } return AnyStringPrefix::Template(TStringPrefix::Regular); } // bytestrings if flags.contains(AnyStringFlagsInner::B_PREFIX) { if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) { return AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: false }); } if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) { return AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: true }); } return AnyStringPrefix::Bytes(ByteStringPrefix::Regular); } // all other strings if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) { return AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }); } if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) { return AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: true }); } if flags.contains(AnyStringFlagsInner::U_PREFIX) { return AnyStringPrefix::Regular(StringLiteralPrefix::Unicode); } AnyStringPrefix::Regular(StringLiteralPrefix::Empty) } fn is_unclosed(self) -> bool { self.0.intersects(AnyStringFlagsInner::UNCLOSED) } } impl fmt::Debug for AnyStringFlags { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AnyStringFlags") .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("quote_style", &self.quote_style()) .field("unclosed", &self.is_unclosed()) .finish() } } impl From for StringLiteralFlags { fn from(value: AnyStringFlags) -> StringLiteralFlags { let AnyStringPrefix::Regular(prefix) = value.prefix() else { unreachable!( "Should never attempt to convert {} into a regular string", value.prefix() ) }; StringLiteralFlags::empty() .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) .with_unclosed(value.is_unclosed()) } } impl From for AnyStringFlags { fn from(value: StringLiteralFlags) -> Self { value.as_any_string_flags() } } impl From for BytesLiteralFlags { fn from(value: AnyStringFlags) -> BytesLiteralFlags { let AnyStringPrefix::Bytes(bytestring_prefix) = value.prefix() else { unreachable!( "Should never attempt to convert {} into a bytestring", value.prefix() ) }; BytesLiteralFlags::empty() .with_quote_style(value.quote_style()) .with_prefix(bytestring_prefix) .with_triple_quotes(value.triple_quotes()) .with_unclosed(value.is_unclosed()) } } impl From for AnyStringFlags { fn from(value: BytesLiteralFlags) -> Self { value.as_any_string_flags() } } impl From for FStringFlags { fn from(value: AnyStringFlags) -> FStringFlags { let AnyStringPrefix::Format(prefix) = value.prefix() else { unreachable!( "Should never attempt to convert {} into an f-string", value.prefix() ) }; FStringFlags::empty() .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) .with_unclosed(value.is_unclosed()) } } impl From for AnyStringFlags { fn from(value: FStringFlags) -> Self { value.as_any_string_flags() } } impl From for TStringFlags { fn from(value: AnyStringFlags) -> TStringFlags { let AnyStringPrefix::Template(prefix) = value.prefix() else { unreachable!( "Should never attempt to convert {} into a t-string", value.prefix() ) }; TStringFlags::empty() .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) .with_unclosed(value.is_unclosed()) } } impl From for AnyStringFlags { fn from(value: TStringFlags) -> Self { value.as_any_string_flags() } } #[derive(Clone, Debug, PartialEq, is_macro::Is)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Number { Int(int::Int), Float(f64), Complex { real: f64, imag: f64 }, } impl ExprName { pub fn id(&self) -> &Name { &self.id } /// Returns `true` if this node represents an invalid name i.e., the `ctx` is [`Invalid`]. /// /// [`Invalid`]: ExprContext::Invalid pub const fn is_invalid(&self) -> bool { matches!(self.ctx, ExprContext::Invalid) } } impl ExprList { pub fn iter(&self) -> std::slice::Iter<'_, Expr> { self.elts.iter() } pub fn len(&self) -> usize { self.elts.len() } pub fn is_empty(&self) -> bool { self.elts.is_empty() } } impl<'a> IntoIterator for &'a ExprList { type IntoIter = std::slice::Iter<'a, Expr>; type Item = &'a Expr; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl ExprTuple { pub fn iter(&self) -> std::slice::Iter<'_, Expr> { self.elts.iter() } pub fn len(&self) -> usize { self.elts.len() } pub fn is_empty(&self) -> bool { self.elts.is_empty() } } impl<'a> IntoIterator for &'a ExprTuple { type IntoIter = std::slice::Iter<'a, Expr>; type Item = &'a Expr; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// See also [expr_context](https://docs.python.org/3/library/ast.html#ast.expr_context) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum ExprContext { Load, Store, Del, Invalid, } /// See also [boolop](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum BoolOp { And, Or, } impl BoolOp { pub const fn as_str(&self) -> &'static str { match self { BoolOp::And => "and", BoolOp::Or => "or", } } } impl fmt::Display for BoolOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// See also [operator](https://docs.python.org/3/library/ast.html#ast.operator) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Operator { Add, Sub, Mult, MatMult, Div, Mod, Pow, LShift, RShift, BitOr, BitXor, BitAnd, FloorDiv, } impl Operator { pub const fn as_str(&self) -> &'static str { match self { Operator::Add => "+", Operator::Sub => "-", Operator::Mult => "*", Operator::MatMult => "@", Operator::Div => "/", Operator::Mod => "%", Operator::Pow => "**", Operator::LShift => "<<", Operator::RShift => ">>", Operator::BitOr => "|", Operator::BitXor => "^", Operator::BitAnd => "&", Operator::FloorDiv => "//", } } /// Returns the dunder method name for the operator. pub const fn dunder(self) -> &'static str { match self { Operator::Add => "__add__", Operator::Sub => "__sub__", Operator::Mult => "__mul__", Operator::MatMult => "__matmul__", Operator::Div => "__truediv__", Operator::Mod => "__mod__", Operator::Pow => "__pow__", Operator::LShift => "__lshift__", Operator::RShift => "__rshift__", Operator::BitOr => "__or__", Operator::BitXor => "__xor__", Operator::BitAnd => "__and__", Operator::FloorDiv => "__floordiv__", } } /// Returns the in-place dunder method name for the operator. pub const fn in_place_dunder(self) -> &'static str { match self { Operator::Add => "__iadd__", Operator::Sub => "__isub__", Operator::Mult => "__imul__", Operator::MatMult => "__imatmul__", Operator::Div => "__itruediv__", Operator::Mod => "__imod__", Operator::Pow => "__ipow__", Operator::LShift => "__ilshift__", Operator::RShift => "__irshift__", Operator::BitOr => "__ior__", Operator::BitXor => "__ixor__", Operator::BitAnd => "__iand__", Operator::FloorDiv => "__ifloordiv__", } } /// Returns the reflected dunder method name for the operator. pub const fn reflected_dunder(self) -> &'static str { match self { Operator::Add => "__radd__", Operator::Sub => "__rsub__", Operator::Mult => "__rmul__", Operator::MatMult => "__rmatmul__", Operator::Div => "__rtruediv__", Operator::Mod => "__rmod__", Operator::Pow => "__rpow__", Operator::LShift => "__rlshift__", Operator::RShift => "__rrshift__", Operator::BitOr => "__ror__", Operator::BitXor => "__rxor__", Operator::BitAnd => "__rand__", Operator::FloorDiv => "__rfloordiv__", } } } impl fmt::Display for Operator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// See also [unaryop](https://docs.python.org/3/library/ast.html#ast.unaryop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum UnaryOp { Invert, Not, UAdd, USub, } impl UnaryOp { pub const fn as_str(&self) -> &'static str { match self { UnaryOp::Invert => "~", UnaryOp::Not => "not", UnaryOp::UAdd => "+", UnaryOp::USub => "-", } } } impl fmt::Display for UnaryOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// See also [cmpop](https://docs.python.org/3/library/ast.html#ast.cmpop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum CmpOp { Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot, In, NotIn, } impl CmpOp { pub const fn as_str(&self) -> &'static str { match self { CmpOp::Eq => "==", CmpOp::NotEq => "!=", CmpOp::Lt => "<", CmpOp::LtE => "<=", CmpOp::Gt => ">", CmpOp::GtE => ">=", CmpOp::Is => "is", CmpOp::IsNot => "is not", CmpOp::In => "in", CmpOp::NotIn => "not in", } } #[must_use] pub const fn negate(&self) -> Self { match self { CmpOp::Eq => CmpOp::NotEq, CmpOp::NotEq => CmpOp::Eq, CmpOp::Lt => CmpOp::GtE, CmpOp::LtE => CmpOp::Gt, CmpOp::Gt => CmpOp::LtE, CmpOp::GtE => CmpOp::Lt, CmpOp::Is => CmpOp::IsNot, CmpOp::IsNot => CmpOp::Is, CmpOp::In => CmpOp::NotIn, CmpOp::NotIn => CmpOp::In, } } } impl fmt::Display for CmpOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// See also [comprehension](https://docs.python.org/3/library/ast.html#ast.comprehension) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Comprehension { pub range: TextRange, pub node_index: AtomicNodeIndex, pub target: Expr, pub iter: Expr, pub ifs: Vec, pub is_async: bool, } /// See also [ExceptHandler](https://docs.python.org/3/library/ast.html#ast.ExceptHandler) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ExceptHandlerExceptHandler { pub range: TextRange, pub node_index: AtomicNodeIndex, pub type_: Option>, pub name: Option, pub body: Suite, } /// See also [arg](https://docs.python.org/3/library/ast.html#ast.arg) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Parameter { pub range: TextRange, pub node_index: AtomicNodeIndex, pub name: Identifier, pub annotation: Option>, } impl Parameter { pub const fn name(&self) -> &Identifier { &self.name } pub fn annotation(&self) -> Option<&Expr> { self.annotation.as_deref() } } /// See also [keyword](https://docs.python.org/3/library/ast.html#ast.keyword) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Keyword { pub range: TextRange, pub node_index: AtomicNodeIndex, pub arg: Option, pub value: Expr, } /// See also [alias](https://docs.python.org/3/library/ast.html#ast.alias) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Alias { pub range: TextRange, pub node_index: AtomicNodeIndex, pub name: Identifier, pub asname: Option, } /// See also [withitem](https://docs.python.org/3/library/ast.html#ast.withitem) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct WithItem { pub range: TextRange, pub node_index: AtomicNodeIndex, pub context_expr: Expr, pub optional_vars: Option>, } /// See also [match_case](https://docs.python.org/3/library/ast.html#ast.match_case) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct MatchCase { pub range: TextRange, pub node_index: AtomicNodeIndex, pub pattern: Pattern, pub guard: Option>, pub body: Suite, } impl Pattern { /// Checks if the [`Pattern`] is an [irrefutable pattern]. /// /// [irrefutable pattern]: https://peps.python.org/pep-0634/#irrefutable-case-blocks pub fn is_irrefutable(&self) -> bool { self.irrefutable_pattern().is_some() } /// Return `Some(IrrefutablePattern)` if `self` is irrefutable or `None` otherwise. pub fn irrefutable_pattern(&self) -> Option { match self { Pattern::MatchAs(PatternMatchAs { pattern, name, range, node_index, }) => match pattern { Some(pattern) => pattern.irrefutable_pattern(), None => match name { Some(name) => Some(IrrefutablePattern { kind: IrrefutablePatternKind::Name(name.id.clone()), range: *range, node_index: node_index.clone(), }), None => Some(IrrefutablePattern { kind: IrrefutablePatternKind::Wildcard, range: *range, node_index: node_index.clone(), }), }, }, Pattern::MatchOr(PatternMatchOr { patterns, .. }) => { patterns.iter().find_map(Pattern::irrefutable_pattern) } _ => None, } } /// Checks if the [`Pattern`] is a [wildcard pattern]. /// /// The following are wildcard patterns: /// ```python /// match subject: /// case _ as x: ... /// case _ | _: ... /// case _: ... /// ``` /// /// [wildcard pattern]: https://docs.python.org/3/reference/compound_stmts.html#wildcard-patterns pub fn is_wildcard(&self) -> bool { match self { Pattern::MatchAs(PatternMatchAs { pattern, .. }) => { pattern.as_deref().is_none_or(Pattern::is_wildcard) } Pattern::MatchOr(PatternMatchOr { patterns, .. }) => { patterns.iter().all(Pattern::is_wildcard) } _ => false, } } } pub struct IrrefutablePattern { pub kind: IrrefutablePatternKind, pub range: TextRange, pub node_index: AtomicNodeIndex, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum IrrefutablePatternKind { Name(Name), Wildcard, } /// An AST node to represent the arguments to a [`crate::PatternMatchClass`], i.e., the /// parenthesized contents in `case Point(1, x=0, y=0)`. /// /// Like [`Arguments`], but for [`crate::PatternMatchClass`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternArguments { pub range: TextRange, pub node_index: AtomicNodeIndex, pub patterns: ThinVec, pub keywords: Vec, } /// An AST node to represent the keyword arguments to a [`crate::PatternMatchClass`], i.e., the /// `x=0` and `y=0` in `case Point(x=0, y=0)`. /// /// Like [`Keyword`], but for [`crate::PatternMatchClass`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PatternKeyword { pub range: TextRange, pub node_index: AtomicNodeIndex, pub attr: Identifier, pub pattern: Pattern, } impl PatternArguments { /// Returns an iterator over the patterns and keywords in source order. pub fn iter_source_order(&self) -> PatternArgumentsSourceOrder<'_> { PatternArgumentsSourceOrder { patterns: &self.patterns, keywords: &self.keywords, next_pattern: 0, next_keyword: 0, } } } /// The iterator returned by [`PatternArguments::iter_source_order`]. #[derive(Clone)] pub struct PatternArgumentsSourceOrder<'a> { patterns: &'a [Pattern], keywords: &'a [PatternKeyword], next_pattern: usize, next_keyword: usize, } /// An entry in the argument list of a class pattern. #[derive(Copy, Clone, Debug, PartialEq)] pub enum PatternOrKeyword<'a> { Pattern(&'a Pattern), Keyword(&'a PatternKeyword), } impl<'a> Iterator for PatternArgumentsSourceOrder<'a> { type Item = PatternOrKeyword<'a>; fn next(&mut self) -> Option { let pattern = self.patterns.get(self.next_pattern); let keyword = self.keywords.get(self.next_keyword); if let Some(pattern) = pattern && keyword.is_none_or(|keyword| pattern.start() <= keyword.start()) { self.next_pattern += 1; Some(PatternOrKeyword::Pattern(pattern)) } else if let Some(keyword) = keyword { self.next_keyword += 1; Some(PatternOrKeyword::Keyword(keyword)) } else { None } } } impl FusedIterator for PatternArgumentsSourceOrder<'_> {} impl TypeParam { pub const fn name(&self) -> &Identifier { match self { Self::TypeVar(x) => &x.name, Self::ParamSpec(x) => &x.name, Self::TypeVarTuple(x) => &x.name, } } pub fn default(&self) -> Option<&Expr> { match self { Self::TypeVar(x) => x.default.as_deref(), Self::ParamSpec(x) => x.default.as_deref(), Self::TypeVarTuple(x) => x.default.as_deref(), } } } /// See also [decorator](https://docs.python.org/3/library/ast.html#ast.decorator) #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Decorator { pub range: TextRange, pub node_index: AtomicNodeIndex, pub expression: Expr, } /// Enumeration of the two kinds of parameter #[derive(Debug, PartialEq, Clone, Copy)] pub enum AnyParameterRef<'a> { /// Variadic parameters cannot have default values, /// e.g. both `*args` and `**kwargs` in the following function: /// /// ```python /// def foo(*args, **kwargs): pass /// ``` Variadic(&'a Parameter), /// Non-variadic parameters can have default values, /// though they won't necessarily always have them: /// /// ```python /// def bar(a=1, /, b=2, *, c=3): pass /// ``` NonVariadic(&'a ParameterWithDefault), } impl<'a> AnyParameterRef<'a> { pub const fn as_parameter(self) -> &'a Parameter { match self { Self::NonVariadic(param) => ¶m.parameter, Self::Variadic(param) => param, } } pub const fn name(self) -> &'a Identifier { &self.as_parameter().name } pub const fn is_variadic(self) -> bool { matches!(self, Self::Variadic(_)) } pub fn annotation(self) -> Option<&'a Expr> { self.as_parameter().annotation.as_deref() } pub fn default(self) -> Option<&'a Expr> { match self { Self::NonVariadic(param) => param.default.as_deref(), Self::Variadic(_) => None, } } } impl Ranged for AnyParameterRef<'_> { fn range(&self) -> TextRange { match self { Self::NonVariadic(param) => param.range, Self::Variadic(param) => param.range, } } } /// 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 [`ParameterWithDefault`] typed argument. /// `vararg` and `kwarg` are still typed as `arg` because they never can have a default value. /// /// The original Python-style AST type orders `kwonlyargs` fields by default existence; [Parameters] has location-ordered `kwonlyargs` fields. /// /// 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, Default)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Parameters { pub range: TextRange, pub node_index: AtomicNodeIndex, pub posonlyargs: ThinVec, pub args: ThinVec, pub vararg: Option>, pub kwonlyargs: ThinVec, pub kwarg: Option>, } impl Parameters { /// Returns an iterator over all non-variadic parameters included in this [`Parameters`] node. /// /// The variadic parameters (`.vararg` and `.kwarg`) can never have default values; /// non-variadic parameters sometimes will. pub fn iter_non_variadic_params(&self) -> impl Iterator { self.posonlyargs .iter() .chain(&self.args) .chain(&self.kwonlyargs) } /// Returns the [`ParameterWithDefault`] with the given name, or `None` if no such [`ParameterWithDefault`] exists. pub fn find(&self, name: &str) -> Option<&ParameterWithDefault> { self.iter_non_variadic_params() .find(|arg| arg.parameter.name.as_str() == name) } /// Returns the index of the parameter with the given name pub fn index(&self, name: &str) -> Option { self.iter_non_variadic_params() .position(|arg| arg.parameter.name.as_str() == name) } /// Returns an iterator over all parameters included in this [`Parameters`] node. pub fn iter(&self) -> ParametersIterator<'_> { ParametersIterator::new(self) } /// Returns the total number of parameters included in this [`Parameters`] node. pub fn len(&self) -> usize { let Parameters { range: _, node_index: _, posonlyargs, args, vararg, kwonlyargs, kwarg, } = self; // Safety: a Python function can have an arbitrary number of parameters, // so theoretically this could be a number that wouldn't fit into a usize, // which would lead to a panic. A Python function with that many parameters // is extremely unlikely outside of generated code, however, and it's even // more unlikely that we'd find a function with that many parameters in a // source-code file <=4GB large (Ruff's maximum). posonlyargs .len() .checked_add(args.len()) .and_then(|length| length.checked_add(usize::from(vararg.is_some()))) .and_then(|length| length.checked_add(kwonlyargs.len())) .and_then(|length| length.checked_add(usize::from(kwarg.is_some()))) .expect("Failed to fit the number of parameters into a usize") } /// Returns `true` if a parameter with the given name is included in this [`Parameters`]. pub fn includes(&self, name: &str) -> bool { self.iter().any(|param| param.name() == name) } /// Returns `true` if the [`Parameters`] is empty. pub fn is_empty(&self) -> bool { self.posonlyargs.is_empty() && self.args.is_empty() && self.kwonlyargs.is_empty() && self.vararg.is_none() && self.kwarg.is_none() } /// Returns an iterator over all parameters in source order. /// /// This differs from [`Parameters::iter`] which returns parameters /// in type-based order (positional-only, regular, variadic, keyword-only, /// keyword). For well-formed Python the two orderings are identical, but /// error recovery can produce ASTs where variadic parameters appear before /// non-variadic ones (e.g. `def foo(**kwargs, a):`). pub fn iter_source_order(&self) -> ParametersSourceOrderIterator<'_> { let mut variadics = [self.vararg.as_deref(), self.kwarg.as_deref()]; variadics.sort_by_key(|param| param.map_or(TextSize::new(u32::MAX), Ranged::start)); ParametersSourceOrderIterator { next_non_variadic_peeked: None, posonlyargs: self.posonlyargs.iter(), args: self.args.iter(), kwonlyargs: self.kwonlyargs.iter(), variadics, next_variadic: 0, } } } pub struct ParametersIterator<'a> { posonlyargs: Iter<'a, ParameterWithDefault>, args: Iter<'a, ParameterWithDefault>, vararg: Option<&'a Parameter>, kwonlyargs: Iter<'a, ParameterWithDefault>, kwarg: Option<&'a Parameter>, } impl<'a> ParametersIterator<'a> { fn new(parameters: &'a Parameters) -> Self { let Parameters { range: _, node_index: _, posonlyargs, args, vararg, kwonlyargs, kwarg, } = parameters; Self { posonlyargs: posonlyargs.iter(), args: args.iter(), vararg: vararg.as_deref(), kwonlyargs: kwonlyargs.iter(), kwarg: kwarg.as_deref(), } } } impl<'a> Iterator for ParametersIterator<'a> { type Item = AnyParameterRef<'a>; fn next(&mut self) -> Option { let ParametersIterator { posonlyargs, args, vararg, kwonlyargs, kwarg, } = self; if let Some(param) = posonlyargs.next() { return Some(AnyParameterRef::NonVariadic(param)); } if let Some(param) = args.next() { return Some(AnyParameterRef::NonVariadic(param)); } if let Some(param) = vararg.take() { return Some(AnyParameterRef::Variadic(param)); } if let Some(param) = kwonlyargs.next() { return Some(AnyParameterRef::NonVariadic(param)); } kwarg.take().map(AnyParameterRef::Variadic) } fn size_hint(&self) -> (usize, Option) { let ParametersIterator { posonlyargs, args, vararg, kwonlyargs, kwarg, } = self; let posonlyargs_len = posonlyargs.len(); let args_len = args.len(); let vararg_len = usize::from(vararg.is_some()); let kwonlyargs_len = kwonlyargs.len(); let kwarg_len = usize::from(kwarg.is_some()); let lower = posonlyargs_len .saturating_add(args_len) .saturating_add(vararg_len) .saturating_add(kwonlyargs_len) .saturating_add(kwarg_len); let upper = posonlyargs_len .checked_add(args_len) .and_then(|length| length.checked_add(vararg_len)) .and_then(|length| length.checked_add(kwonlyargs_len)) .and_then(|length| length.checked_add(kwarg_len)); (lower, upper) } fn last(mut self) -> Option { self.next_back() } } impl DoubleEndedIterator for ParametersIterator<'_> { fn next_back(&mut self) -> Option { let ParametersIterator { posonlyargs, args, vararg, kwonlyargs, kwarg, } = self; if let Some(param) = kwarg.take() { return Some(AnyParameterRef::Variadic(param)); } if let Some(param) = kwonlyargs.next_back() { return Some(AnyParameterRef::NonVariadic(param)); } if let Some(param) = vararg.take() { return Some(AnyParameterRef::Variadic(param)); } if let Some(param) = args.next_back() { return Some(AnyParameterRef::NonVariadic(param)); } posonlyargs.next_back().map(AnyParameterRef::NonVariadic) } } impl FusedIterator for ParametersIterator<'_> {} /// We rely on the same invariants outlined in the comment above `Parameters::len()` /// in order to implement `ExactSizeIterator` here impl ExactSizeIterator for ParametersIterator<'_> {} impl<'a> IntoIterator for &'a Parameters { type IntoIter = ParametersIterator<'a>; type Item = AnyParameterRef<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a Box { type IntoIter = ParametersIterator<'a>; type Item = AnyParameterRef<'a>; fn into_iter(self) -> Self::IntoIter { (&**self).into_iter() } } /// The iterator returned by [`Parameters::iter_source_order`]. pub struct ParametersSourceOrderIterator<'a> { next_non_variadic_peeked: Option<&'a ParameterWithDefault>, posonlyargs: Iter<'a, ParameterWithDefault>, args: Iter<'a, ParameterWithDefault>, kwonlyargs: Iter<'a, ParameterWithDefault>, variadics: [Option<&'a Parameter>; 2], next_variadic: usize, } impl<'a> ParametersSourceOrderIterator<'a> { /// Returns the next variadic parameter that appears before `before`, if any. fn next_variadic_before(&mut self, before: TextSize) -> Option<&'a Parameter> { let param = self.variadics.get(self.next_variadic).copied().flatten()?; if param.start() < before { self.next_variadic += 1; Some(param) } else { None } } fn next_non_variadic(&mut self) -> Option<&'a ParameterWithDefault> { self.next_non_variadic_peeked .take() .or_else(|| self.posonlyargs.next()) .or_else(|| self.args.next()) .or_else(|| self.kwonlyargs.next()) } fn peek_next_non_variadic(&mut self) -> Option<&'a ParameterWithDefault> { let next = self.next_non_variadic()?; self.next_non_variadic_peeked = Some(next); Some(next) } } impl<'a> Iterator for ParametersSourceOrderIterator<'a> { type Item = AnyParameterRef<'a>; fn next(&mut self) -> Option { // If there's a variadic parameter that comes before the next // non-variadic parameter, emit it first. let next_non_variadic_start = self .peek_next_non_variadic() .map_or(TextSize::new(u32::MAX), Ranged::start); if let Some(variadic) = self.next_variadic_before(next_non_variadic_start) { return Some(AnyParameterRef::Variadic(variadic)); } if let Some(non_variadic) = self.next_non_variadic() { return Some(AnyParameterRef::NonVariadic(non_variadic)); } // Drain remaining variadics. self.next_variadic_before(TextSize::new(u32::MAX)) .map(AnyParameterRef::Variadic) } } impl FusedIterator for ParametersSourceOrderIterator<'_> {} /// An alternative type of AST `arg`. This is used for each function argument that might have a default value. /// Used by `Arguments` original type. /// /// NOTE: This type is different from original Python AST. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct ParameterWithDefault { pub range: TextRange, pub node_index: AtomicNodeIndex, pub parameter: Parameter, pub default: Option>, } impl ParameterWithDefault { pub fn default(&self) -> Option<&Expr> { self.default.as_deref() } pub const fn name(&self) -> &Identifier { self.parameter.name() } pub fn annotation(&self) -> Option<&Expr> { self.parameter.annotation() } /// Return `true` if the parameter name uses the pre-PEP-570 convention /// (specified in PEP 484) to indicate to a type checker that it should be treated /// as positional-only. pub fn uses_pep_484_positional_only_convention(&self) -> bool { let name = self.name(); name.starts_with("__") && !name.ends_with("__") } } /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Arguments { pub range: TextRange, pub node_index: AtomicNodeIndex, pub args: Box<[Expr]>, pub keywords: ThinVec, } /// An entry in the argument list of a function call. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ArgOrKeyword<'a> { Arg(&'a Expr), Keyword(&'a Keyword), } impl<'a> ArgOrKeyword<'a> { pub const fn value(self) -> &'a Expr { match self { ArgOrKeyword::Arg(argument) => argument, ArgOrKeyword::Keyword(keyword) => &keyword.value, } } pub const fn is_variadic(self) -> bool { match self { ArgOrKeyword::Arg(expr) => expr.is_starred_expr(), ArgOrKeyword::Keyword(keyword) => keyword.arg.is_none(), } } pub const fn as_variadic(self) -> Option<&'a Keyword> { match self { ArgOrKeyword::Keyword(keyword) if keyword.arg.is_none() => Some(keyword), _ => None, } } pub const fn as_keyword(self) -> Option<&'a Keyword> { match self { ArgOrKeyword::Keyword(keyword) => Some(keyword), ArgOrKeyword::Arg(_) => None, } } } impl<'a> From<&'a Expr> for ArgOrKeyword<'a> { fn from(arg: &'a Expr) -> Self { Self::Arg(arg) } } impl<'a> From<&'a Keyword> for ArgOrKeyword<'a> { fn from(keyword: &'a Keyword) -> Self { Self::Keyword(keyword) } } impl Ranged for ArgOrKeyword<'_> { fn range(&self) -> TextRange { match self { Self::Arg(arg) => arg.range(), Self::Keyword(keyword) => keyword.range(), } } } 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 value for the argument with the given name or at the given position, or `None` if no such /// argument exists. Used to retrieve argument values that can be provided _either_ as keyword or /// positional arguments. pub fn find_argument_value(&self, name: &str, position: usize) -> Option<&Expr> { self.find_argument(name, position).map(ArgOrKeyword::value) } /// 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> { self.find_keyword(name) .map(ArgOrKeyword::from) .or_else(|| self.find_positional(position).map(ArgOrKeyword::from)) } /// Iterates over the positional and keyword arguments in the order of declaration. /// /// Positional arguments are generally before keyword arguments, but star arguments are an /// exception: /// ```python /// class A(*args, a=2, *args2, **kwargs): /// pass /// /// f(*args, a=2, *args2, **kwargs) /// ``` /// where `*args` and `args2` are `args` while `a=1` and `kwargs` are `keywords`. /// /// If you would just chain `args` and `keywords` the call would get reordered which we don't /// want. This function instead "merge sorts" them into the correct order. /// /// Note that the order of evaluation is always first `args`, then `keywords`: /// ```python /// def f(*args, **kwargs): /// pass /// /// def g(x): /// print(x) /// return x /// /// /// f(*g([1]), a=g(2), *g([3]), **g({"4": 5})) /// ``` /// Output: /// ```text /// [1] /// [3] /// 2 /// {'4': 5} /// ``` pub fn iter_source_order(&self) -> ArgumentsSourceOrder<'_> { ArgumentsSourceOrder { args: &self.args, keywords: &self.keywords, next_arg: 0, next_keyword: 0, } } pub fn inner_range(&self) -> TextRange { TextRange::new(self.l_paren_range().end(), self.r_paren_range().start()) } pub fn l_paren_range(&self) -> TextRange { TextRange::at(self.start(), '('.text_len()) } pub fn r_paren_range(&self) -> TextRange { TextRange::new(self.end() - ')'.text_len(), self.end()) } } /// The iterator returned by [`Arguments::iter_source_order`]. #[derive(Clone)] pub struct ArgumentsSourceOrder<'a> { args: &'a [Expr], keywords: &'a [Keyword], next_arg: usize, next_keyword: usize, } impl<'a> Iterator for ArgumentsSourceOrder<'a> { type Item = ArgOrKeyword<'a>; fn next(&mut self) -> Option { let arg = self.args.get(self.next_arg); let keyword = self.keywords.get(self.next_keyword); if let Some(arg) = arg && keyword.is_none_or(|keyword| arg.start() <= keyword.start()) { self.next_arg += 1; Some(ArgOrKeyword::Arg(arg)) } else if let Some(keyword) = keyword { self.next_keyword += 1; Some(ArgOrKeyword::Keyword(keyword)) } else { None } } } impl FusedIterator for ArgumentsSourceOrder<'_> {} /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TypeParams { pub range: TextRange, pub node_index: AtomicNodeIndex, pub type_params: Vec, } impl Deref for TypeParams { type Target = [TypeParam]; fn deref(&self) -> &Self::Target { &self.type_params } } impl<'a> IntoIterator for &'a TypeParams { type Item = &'a TypeParam; type IntoIter = std::slice::Iter<'a, TypeParam>; fn into_iter(self) -> Self::IntoIter { self.type_params.iter() } } /// A suite represents a sequence of [`Stmt`]. /// /// See: pub type Suite = ThinVec; pub type DecoratorList = ThinVec; pub type Patterns = ThinVec; pub type PatternKeys = ThinVec; pub type ParameterWithDefaults = ThinVec; /// 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)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum IpyEscapeKind { /// Send line to underlying system shell (`!`). Shell, /// Send line to system shell and capture output (`!!`). ShCap, /// Show help on object (`?`). Help, /// Show help on object, with extra verbosity (`??`). Help2, /// Call magic function (`%`). Magic, /// Call cell magic function (`%%`). Magic2, /// Call first argument with rest of line as arguments after splitting on whitespace /// and quote each as string (`,`). Quote, /// 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 (`/`). Paren, } impl TryFrom for IpyEscapeKind { type Error = String; fn try_from(ch: char) -> Result { match ch { '!' => 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 IpyEscapeKind { type Error = String; fn try_from(ch: [char; 2]) -> Result { match ch { ['!', '!'] => Ok(IpyEscapeKind::ShCap), ['?', '?'] => Ok(IpyEscapeKind::Help2), ['%', '%'] => Ok(IpyEscapeKind::Magic2), [c1, c2] => Err(format!("Unexpected magic escape: {c1}{c2}")), } } } impl fmt::Display for IpyEscapeKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } impl IpyEscapeKind { /// 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 => "/", } } } /// An `Identifier` with an empty `id` is invalid. /// /// For example, in the following code `id` will be empty. /// ```python /// def 1(): /// ... /// ``` #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Identifier { pub id: Name, pub range: TextRange, pub node_index: AtomicNodeIndex, } impl Identifier { #[inline] pub fn new(id: impl Into, range: TextRange) -> Self { Self { id: id.into(), node_index: AtomicNodeIndex::NONE, range, } } pub fn id(&self) -> &Name { &self.id } pub fn is_valid(&self) -> bool { !self.id.is_empty() } } impl Identifier { #[inline] pub fn as_str(&self) -> &str { self.id.as_str() } } impl PartialEq for Identifier { #[inline] fn eq(&self, other: &str) -> bool { self.id == other } } impl PartialEq for Identifier { #[inline] fn eq(&self, other: &String) -> bool { self.id == other } } impl std::ops::Deref for Identifier { type Target = str; #[inline] fn deref(&self) -> &Self::Target { self.id.as_str() } } impl AsRef for Identifier { #[inline] fn as_ref(&self) -> &str { self.id.as_str() } } impl std::fmt::Display for Identifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.id, f) } } impl From for Name { #[inline] fn from(identifier: Identifier) -> Name { identifier.id } } #[derive(Clone, Copy, Debug, Hash, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum Singleton { None, True, False, } impl From for Singleton { fn from(value: bool) -> Self { if value { Singleton::True } else { Singleton::False } } } #[cfg(test)] mod tests { use crate::generated::*; use crate::{Arguments, Mod, Parameters}; #[test] #[cfg(target_pointer_width = "64")] fn size() { assert_eq!(std::mem::size_of::(), 88); assert_eq!(std::mem::size_of::(), 88); assert_eq!(std::mem::size_of::(), 80); assert_eq!(std::mem::size_of::(), 64); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 72); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 64); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 24); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 16); assert_eq!(std::mem::size_of::(), 48); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 12); assert_eq!(std::mem::size_of::(), 56); assert_eq!(std::mem::size_of::(), 48); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 48); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 12); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 48); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 24); assert_eq!(std::mem::size_of::(), 48); assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 24); assert_eq!(std::mem::size_of::(), 24); assert_eq!(std::mem::size_of::(), 24); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/operator_precedence.rs000064400000000000000000000156311046102023000232120ustar00use crate::{BoolOp, Expr, ExprRef, Operator, UnaryOp}; /// Represents the precedence levels for Python expressions. /// Variants at the top have lower precedence and variants at the bottom have /// higher precedence. /// /// See: #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum OperatorPrecedence { /// The lowest (virtual) precedence level None, /// Precedence of `yield` and `yield from` expressions. Yield, /// Precedence of assignment expressions (`name := expr`). Assign, /// Precedence of starred expressions (`*expr`). Starred, /// Precedence of lambda expressions (`lambda args: expr`). Lambda, /// Precedence of if/else expressions (`expr if cond else expr`). IfElse, /// Precedence of boolean `or` expressions. Or, /// Precedence of boolean `and` expressions. And, /// Precedence of boolean `not` expressions. Not, /// Precedence of comparisons (`<`, `<=`, `>`, `>=`, `!=`, `==`), /// memberships (`in`, `not in`) and identity tests (`is`, `is not`). ComparisonsMembershipIdentity, /// Precedence of bitwise `|` operator. BitOr, /// Precedence of bitwise `^` operator. BitXor, /// Precedence of bitwise `&` operator. BitAnd, /// Precedence of left and right shift expressions (`<<`, `>>`). LeftRightShift, /// Precedence of addition and subtraction expressions (`+`, `-`). AddSub, /// Precedence of multiplication (`*`), matrix multiplication (`@`), division (`/`), /// floor division (`//`) and remainder (`%`) expressions. MulDivRemain, /// Precedence of unary positive (`+`), negative (`-`), and bitwise NOT (`~`) expressions. PosNegBitNot, /// Precedence of exponentiation expressions (`**`). Exponent, /// Precedence of `await` expressions. Await, /// Precedence of call expressions (`()`), attribute access (`.`), and subscript (`[]`) expressions. CallAttribute, /// Precedence of atomic expressions (literals, names, containers). Atomic, } impl OperatorPrecedence { pub fn from_expr_ref(expr: ExprRef) -> Self { match expr { // Binding or parenthesized expression, list display, dictionary display, set display ExprRef::Tuple(_) | ExprRef::Dict(_) | ExprRef::Set(_) | ExprRef::ListComp(_) | ExprRef::List(_) | ExprRef::SetComp(_) | ExprRef::DictComp(_) | ExprRef::Generator(_) | ExprRef::Name(_) | ExprRef::StringLiteral(_) | ExprRef::BytesLiteral(_) | ExprRef::NumberLiteral(_) | ExprRef::BooleanLiteral(_) | ExprRef::NoneLiteral(_) | ExprRef::EllipsisLiteral(_) | ExprRef::FString(_) | ExprRef::TString(_) => Self::Atomic, // Subscription, slicing, call, attribute reference ExprRef::Attribute(_) | ExprRef::Subscript(_) | ExprRef::Call(_) | ExprRef::Slice(_) => Self::CallAttribute, // Await expression ExprRef::Await(_) => Self::Await, // Exponentiation ** // Handled below along with other binary operators // Unary operators: +x, -x, ~x (except boolean not) ExprRef::UnaryOp(operator) => match operator.op { UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert => Self::PosNegBitNot, UnaryOp::Not => Self::Not, }, // Math binary ops ExprRef::BinOp(binary_operation) => Self::from(binary_operation.op), // Comparisons: <, <=, >, >=, ==, !=, in, not in, is, is not ExprRef::Compare(_) => Self::ComparisonsMembershipIdentity, // Boolean not // Handled above in unary operators // Boolean operations: and, or ExprRef::BoolOp(bool_op) => Self::from(bool_op.op), // Conditional expressions: x if y else z ExprRef::If(_) => Self::IfElse, // Lambda expressions ExprRef::Lambda(_) => Self::Lambda, // Unpacking also omitted in the docs, but has almost the lowest precedence, // except for assignment & yield expressions. E.g. `[*(v := [1,2])]` is valid // but `[*v := [1,2]] would fail on incorrect syntax because * will associate // `v` before the assignment. ExprRef::Starred(_) => Self::Starred, // Assignment expressions (aka named) ExprRef::Named(_) => Self::Assign, // Although omitted in docs, yield expressions may be used inside an expression // but must be parenthesized. So for our purposes we assume they just have // the lowest "real" precedence. ExprRef::Yield(_) | ExprRef::YieldFrom(_) => Self::Yield, // Not a real python expression, so treat as lowest as well ExprRef::IpyEscapeCommand(_) => Self::None, } } pub fn from_expr(expr: &Expr) -> Self { Self::from(ExprRef::from(expr)) } /// Returns `true` if the precedence is right-associative i.e., the operations are evaluated /// from right to left. pub fn is_right_associative(self) -> bool { matches!(self, OperatorPrecedence::Exponent) } } impl From<&Expr> for OperatorPrecedence { fn from(expr: &Expr) -> Self { Self::from_expr(expr) } } impl<'a> From> for OperatorPrecedence { fn from(expr_ref: ExprRef<'a>) -> Self { Self::from_expr_ref(expr_ref) } } impl From for OperatorPrecedence { fn from(operator: Operator) -> Self { match operator { // Multiplication, matrix multiplication, division, floor division, remainder: // *, @, /, //, % Operator::Mult | Operator::MatMult | Operator::Div | Operator::Mod | Operator::FloorDiv => Self::MulDivRemain, // Addition, subtraction Operator::Add | Operator::Sub => Self::AddSub, // Bitwise shifts: <<, >> Operator::LShift | Operator::RShift => Self::LeftRightShift, // Bitwise operations: &, ^, | Operator::BitAnd => Self::BitAnd, Operator::BitXor => Self::BitXor, Operator::BitOr => Self::BitOr, // Exponentiation ** Operator::Pow => Self::Exponent, } } } impl From for OperatorPrecedence { fn from(operator: BoolOp) -> Self { match operator { BoolOp::And => Self::And, BoolOp::Or => Self::Or, } } } impl From for OperatorPrecedence { fn from(unary_op: UnaryOp) -> Self { match unary_op { UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert => Self::PosNegBitNot, UnaryOp::Not => Self::Not, } } } ast_serialize-0.13.1/crates/ruff_python_ast/src/parenthesize.rs000064400000000000000000000064251046102023000217040ustar00use ruff_python_trivia::{BackwardsTokenizer, CommentRanges, SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextLen, TextRange}; use crate::AnyNodeRef; use crate::ExprRef; /// Returns an iterator over the ranges of the optional parentheses surrounding an expression. /// /// E.g. for `((f()))` with `f()` as expression, the iterator returns the ranges (1, 6) and (0, 7). /// /// Note that without a parent the range can be inaccurate, e.g. `f(a)` we falsely return a set of /// parentheses around `a` even if the parentheses actually belong to `f`. That is why you should /// generally prefer [`parenthesized_range`]. /// /// Prefer [`crate::token::parentheses_iterator`] if you have access to [`crate::token::Tokens`]. fn parentheses_iterator<'a>( expr: ExprRef<'a>, parent: Option, comment_ranges: &'a CommentRanges, source: &'a str, ) -> impl Iterator + 'a { let right_tokenizer = if let Some(parent) = parent { // 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() - ")".text_len() } else { parent.end() }; SimpleTokenizer::new(source, TextRange::new(expr.end(), exclusive_parent_end)) } else { SimpleTokenizer::starts_at(expr.end(), source) }; let right_tokenizer = right_tokenizer .skip_trivia() .take_while(|token| token.kind == SimpleTokenKind::RParen); let left_tokenizer = BackwardsTokenizer::up_to(expr.start(), source, comment_ranges) .skip_trivia() .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) .map(|(right, left)| TextRange::new(left.start(), right.end())) } /// Returns the [`TextRange`] of a given expression including parentheses, if the expression is /// parenthesized; or `None`, if the expression is not parenthesized. /// /// Prefer [`crate::token::parenthesized_range`] if you have access to [`crate::token::Tokens`]. pub fn parenthesized_range( expr: ExprRef, parent: AnyNodeRef, comment_ranges: &CommentRanges, source: &str, ) -> Option { parentheses_iterator(expr, Some(parent), comment_ranges, source).last() } ast_serialize-0.13.1/crates/ruff_python_ast/src/python_version.rs000064400000000000000000000157171046102023000222750ustar00use std::{fmt, str::FromStr}; /// Representation of a Python version. /// /// N.B. This does not necessarily represent a Python version that we actually support. #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[cfg_attr(feature = "cache", derive(ruff_macros::CacheKey))] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct PythonVersion { pub major: u8, pub minor: u8, } impl PythonVersion { pub const PY37: PythonVersion = PythonVersion { major: 3, minor: 7 }; pub const PY38: PythonVersion = PythonVersion { major: 3, minor: 8 }; pub const PY39: PythonVersion = PythonVersion { major: 3, minor: 9 }; pub const PY310: PythonVersion = PythonVersion { major: 3, minor: 10, }; pub const PY311: PythonVersion = PythonVersion { major: 3, minor: 11, }; pub const PY312: PythonVersion = PythonVersion { major: 3, minor: 12, }; pub const PY313: PythonVersion = PythonVersion { major: 3, minor: 13, }; pub const PY314: PythonVersion = PythonVersion { major: 3, minor: 14, }; pub const PY315: PythonVersion = PythonVersion { major: 3, minor: 15, }; pub fn iter() -> impl Iterator { [ PythonVersion::PY37, PythonVersion::PY38, PythonVersion::PY39, PythonVersion::PY310, PythonVersion::PY311, PythonVersion::PY312, PythonVersion::PY313, PythonVersion::PY314, PythonVersion::PY315, ] .into_iter() } /// The minimum supported Python version. pub const fn lowest() -> Self { Self::PY37 } pub const fn latest() -> Self { Self::PY314 } /// The latest Python version supported in preview pub fn latest_preview() -> Self { let latest_preview = Self::PY315; debug_assert!(latest_preview >= Self::latest()); latest_preview } pub const fn latest_ty() -> Self { // Make sure to update the default value for `EnvironmentOptions::python_version` when bumping this version. Self::PY314 } pub const fn as_tuple(self) -> (u8, u8) { (self.major, self.minor) } pub fn free_threaded_build_available(self) -> bool { self >= PythonVersion::PY313 } /// Return `true` if the current version supports [PEP 701]. /// /// [PEP 701]: https://peps.python.org/pep-0701/ pub fn supports_pep_701(self) -> bool { self >= Self::PY312 } pub fn defers_annotations(self) -> bool { self >= Self::PY314 } } impl Default for PythonVersion { fn default() -> Self { Self::PY310 } } impl From<(u8, u8)> for PythonVersion { fn from(value: (u8, u8)) -> Self { let (major, minor) = value; Self { major, minor } } } impl TryFrom<(i64, i64)> for PythonVersion { type Error = std::num::TryFromIntError; fn try_from(value: (i64, i64)) -> Result { let (major, minor) = value; Ok(Self { major: u8::try_from(major)?, minor: u8::try_from(minor)?, }) } } impl fmt::Display for PythonVersion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let PythonVersion { major, minor } = self; write!(f, "{major}.{minor}") } } #[derive(thiserror::Error, Debug, PartialEq, Eq, Clone)] pub enum PythonVersionDeserializationError { #[error("Invalid python version `{0}`: expected `major.minor`")] WrongPeriodNumber(Box), #[error("Invalid major version `{0}`: {1}")] InvalidMajorVersion(Box, #[source] std::num::ParseIntError), #[error("Invalid minor version `{0}`: {1}")] InvalidMinorVersion(Box, #[source] std::num::ParseIntError), } impl TryFrom<(&str, &str)> for PythonVersion { type Error = PythonVersionDeserializationError; fn try_from(value: (&str, &str)) -> Result { let (major, minor) = value; Ok(Self { major: major.parse().map_err(|err| { PythonVersionDeserializationError::InvalidMajorVersion(Box::from(major), err) })?, minor: minor.parse().map_err(|err| { PythonVersionDeserializationError::InvalidMinorVersion(Box::from(minor), err) })?, }) } } impl FromStr for PythonVersion { type Err = PythonVersionDeserializationError; fn from_str(s: &str) -> Result { let (major, minor) = s .split_once('.') .ok_or_else(|| PythonVersionDeserializationError::WrongPeriodNumber(Box::from(s)))?; Self::try_from((major, minor)).map_err(|err| { // Give a better error message for something like `3.8.5` or `3..8` if matches!( err, PythonVersionDeserializationError::InvalidMinorVersion(_, _) ) && minor.contains('.') { PythonVersionDeserializationError::WrongPeriodNumber(Box::from(s)) } else { err } }) } } #[cfg(feature = "serde")] mod serde { use super::PythonVersion; impl<'de> serde::Deserialize<'de> for PythonVersion { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { String::deserialize(deserializer)? .parse() .map_err(serde::de::Error::custom) } } impl serde::Serialize for PythonVersion { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(&self.to_string()) } } } #[cfg(feature = "schemars")] mod schemars { use super::PythonVersion; use schemars::{JsonSchema, Schema, SchemaGenerator}; use serde_json::Value; impl JsonSchema for PythonVersion { fn schema_name() -> std::borrow::Cow<'static, str> { std::borrow::Cow::Borrowed("PythonVersion") } fn json_schema(_gen: &mut SchemaGenerator) -> Schema { let mut any_of: Vec = vec![ schemars::json_schema!({ "type": "string", "pattern": r"^\d+\.\d+$", }) .into(), ]; for version in Self::iter() { let mut schema = schemars::json_schema!({ "const": version.to_string(), }); schema.ensure_object().insert( "description".to_string(), Value::String(format!("Python {version}")), ); any_of.push(schema.into()); } let mut schema = Schema::default(); schema .ensure_object() .insert("anyOf".to_string(), Value::Array(any_of)); schema } } } ast_serialize-0.13.1/crates/ruff_python_ast/src/relocate.rs000064400000000000000000000110261046102023000207720ustar00use ruff_text_size::TextRange; use crate::visitor::transformer::{Transformer, walk_expr, walk_keyword}; use crate::{self as ast}; use crate::{Expr, Keyword}; /// Change an expression's location (recursively) to match a desired, fixed /// range. pub fn relocate_expr(expr: &mut Expr, range: TextRange) { Relocator { range }.visit_expr(expr); } #[derive(Debug)] struct Relocator { range: TextRange, } impl Transformer for Relocator { fn visit_expr(&self, expr: &mut Expr) { match expr { Expr::BoolOp(ast::ExprBoolOp { range, .. }) => { *range = self.range; } Expr::Named(ast::ExprNamed { range, .. }) => { *range = self.range; } Expr::BinOp(ast::ExprBinOp { range, .. }) => { *range = self.range; } Expr::UnaryOp(ast::ExprUnaryOp { range, .. }) => { *range = self.range; } Expr::Lambda(ast::ExprLambda { range, .. }) => { *range = self.range; } Expr::If(ast::ExprIf { range, .. }) => { *range = self.range; } Expr::Dict(ast::ExprDict { range, .. }) => { *range = self.range; } Expr::Set(ast::ExprSet { range, .. }) => { *range = self.range; } Expr::ListComp(ast::ExprListComp { range, .. }) => { *range = self.range; } Expr::SetComp(ast::ExprSetComp { range, .. }) => { *range = self.range; } Expr::DictComp(ast::ExprDictComp { range, .. }) => { *range = self.range; } Expr::Generator(ast::ExprGenerator { range, .. }) => { *range = self.range; } Expr::Await(ast::ExprAwait { range, .. }) => { *range = self.range; } Expr::Yield(ast::ExprYield { range, .. }) => { *range = self.range; } Expr::YieldFrom(ast::ExprYieldFrom { range, .. }) => { *range = self.range; } Expr::Compare(ast::ExprCompare { range, .. }) => { *range = self.range; } Expr::Call(ast::ExprCall { range_start, arguments, .. }) => { *range_start = self.range.start(); arguments.range = self.range; } Expr::FString(ast::ExprFString { range, .. }) => { *range = self.range; } Expr::TString(ast::ExprTString { range, .. }) => { *range = self.range; } Expr::StringLiteral(ast::ExprStringLiteral { range, .. }) => { *range = self.range; } Expr::BytesLiteral(ast::ExprBytesLiteral { range, .. }) => { *range = self.range; } Expr::NumberLiteral(ast::ExprNumberLiteral { range, .. }) => { *range = self.range; } Expr::BooleanLiteral(ast::ExprBooleanLiteral { range, .. }) => { *range = self.range; } Expr::NoneLiteral(ast::ExprNoneLiteral { range, .. }) => { *range = self.range; } Expr::EllipsisLiteral(ast::ExprEllipsisLiteral { range, .. }) => { *range = self.range; } Expr::Attribute(ast::ExprAttribute { range, .. }) => { *range = self.range; } Expr::Subscript(ast::ExprSubscript { range, .. }) => { *range = self.range; } Expr::Starred(ast::ExprStarred { range, .. }) => { *range = self.range; } Expr::Name(ast::ExprName { range, .. }) => { *range = self.range; } Expr::List(ast::ExprList { range, .. }) => { *range = self.range; } Expr::Tuple(ast::ExprTuple { range, .. }) => { *range = self.range; } Expr::Slice(ast::ExprSlice { range, .. }) => { *range = self.range; } Expr::IpyEscapeCommand(ast::ExprIpyEscapeCommand { range, .. }) => { *range = self.range; } } walk_expr(self, expr); } fn visit_keyword(&self, keyword: &mut Keyword) { keyword.range = self.range; walk_keyword(self, keyword); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/script.rs000064400000000000000000000115531046102023000205050ustar00use std::sync::LazyLock; use memchr::memmem::Finder; static FINDER: LazyLock = LazyLock::new(|| Finder::new(b"# /// script")); /// PEP 723 metadata as parsed from a `script` comment block. /// /// See: /// /// Vendored from: #[derive(Debug, Clone, Eq, PartialEq)] pub struct ScriptTag { /// The content of the script before the metadata block. prelude: String, /// The metadata block. metadata: String, /// The content of the script after the metadata block. postlude: String, } impl ScriptTag { /// Returns the TOML contents of the metadata block. pub fn metadata(&self) -> &str { &self.metadata } /// Given the contents of a Python file, extract the `script` metadata block with leading /// comment hashes removed, any preceding shebang or content (prelude), and the remaining Python /// script. /// /// Given the following input string representing the contents of a Python script: /// /// ```python /// #!/usr/bin/env python3 /// # /// script /// # requires-python = '>=3.11' /// # dependencies = [ /// # 'requests<3', /// # 'rich', /// # ] /// # /// /// /// import requests /// /// print("Hello, World!") /// ``` /// /// This function would return: /// /// - Preamble: `#!/usr/bin/env python3\n` /// - Metadata: `requires-python = '>=3.11'\ndependencies = [\n 'requests<3',\n 'rich',\n]` /// - Postlude: `import requests\n\nprint("Hello, World!")\n` /// /// See: pub fn parse(contents: &[u8]) -> Option { FINDER .find_iter(contents) .find_map(|index| Self::parse_at(contents, index)) } fn parse_at(contents: &[u8], index: usize) -> Option { // The opening pragma must be the first line, or immediately preceded by a newline. if !(index == 0 || matches!(contents[index - 1], b'\r' | b'\n')) { return None; } // Extract the preceding content. let prelude = std::str::from_utf8(&contents[..index]).ok()?; // Decode as UTF-8. let contents = &contents[index..]; let contents = std::str::from_utf8(contents).ok()?; let mut lines = contents.lines(); // Ensure that the first line is exactly `# /// script`. if lines.next().is_none_or(|line| line != "# /// script") { return None; } // > Every line between these two lines (# /// TYPE and # ///) MUST be a comment starting // > with #. If there are characters after the # then the first character MUST be a space. The // > embedded content is formed by taking away the first two characters of each line if the // > second character is a space, otherwise just the first character (which means the line // > consists of only a single #). let mut toml = vec![]; // Extract the content that follows the metadata block. let mut python_script = vec![]; while let Some(line) = lines.next() { // Remove the leading `#`. let Some(line) = line.strip_prefix('#') else { python_script.push(line); python_script.extend(lines); break; }; // If the line is empty, continue. if line.is_empty() { toml.push(""); continue; } // Otherwise, the line _must_ start with ` `. let Some(line) = line.strip_prefix(' ') else { python_script.push(line); python_script.extend(lines); break; }; toml.push(line); } // Find the closing `# ///`. The precedence is such that we need to identify the _last_ such // line. // // For example, given: // ```python // # /// script // # // # /// // # // # /// // ``` // // The latter `///` is the closing pragma let index = toml.iter().rev().position(|line| *line == "///")?; let index = toml.len() - index; // Discard any lines after the closing `# ///`. // // For example, given: // ```python // # /// script // # // # /// // # // # // ``` // // We need to discard the last two lines. toml.truncate(index - 1); // Join the lines into a single string. let prelude = prelude.to_string(); let metadata = toml.join("\n") + "\n"; let postlude = python_script.join("\n") + "\n"; Some(Self { prelude, metadata, postlude, }) } } ast_serialize-0.13.1/crates/ruff_python_ast/src/statement_visitor.rs000064400000000000000000000062231046102023000227620ustar00//! Specialized AST visitor trait and walk functions that only visit statements. use crate::{self as ast, ElifElseClause, ExceptHandler, MatchCase, Stmt}; /// A trait for AST visitors that only need to visit statements. pub trait StatementVisitor<'a> { fn visit_body(&mut self, body: &'a [Stmt]) { walk_body(self, body); } fn visit_stmt(&mut self, stmt: &'a Stmt) { walk_stmt(self, stmt); } fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) { walk_except_handler(self, except_handler); } fn visit_elif_else_clause(&mut self, elif_else_clause: &'a ElifElseClause) { walk_elif_else_clause(self, elif_else_clause); } fn visit_match_case(&mut self, match_case: &'a MatchCase) { walk_match_case(self, match_case); } } pub fn walk_body<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, body: &'a [Stmt]) { for stmt in body { visitor.visit_stmt(stmt); } } pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => { visitor.visit_body(body); } Stmt::For(ast::StmtFor { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { visitor.visit_body(body); } Stmt::While(ast::StmtWhile { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } Stmt::If(ast::StmtIf { body, elif_else_clauses, .. }) => { visitor.visit_body(body); for clause in elif_else_clauses { visitor.visit_elif_else_clause(clause); } } Stmt::With(ast::StmtWith { body, .. }) => { visitor.visit_body(body); } Stmt::Match(ast::StmtMatch { cases, .. }) => { for match_case in cases { visitor.visit_match_case(match_case); } } Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, .. }) => { visitor.visit_body(body); for except_handler in handlers { visitor.visit_except_handler(except_handler); } visitor.visit_body(orelse); visitor.visit_body(finalbody); } _ => {} } } pub fn walk_except_handler<'a, V: StatementVisitor<'a> + ?Sized>( visitor: &mut V, except_handler: &'a ExceptHandler, ) { match except_handler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) => { visitor.visit_body(body); } } } pub fn walk_elif_else_clause<'a, V: StatementVisitor<'a> + ?Sized>( visitor: &mut V, elif_else_clause: &'a ElifElseClause, ) { visitor.visit_body(&elif_else_clause.body); } pub fn walk_match_case<'a, V: StatementVisitor<'a> + ?Sized>( visitor: &mut V, match_case: &'a MatchCase, ) { visitor.visit_body(&match_case.body); } ast_serialize-0.13.1/crates/ruff_python_ast/src/stmt_if.rs000064400000000000000000000026541046102023000206500ustar00use std::iter; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; use crate::{ElifElseClause, Expr, Stmt, StmtIf}; /// Return the `Range` of the first `Elif` or `Else` token in an `If` statement. pub fn elif_else_range(clause: &ElifElseClause, contents: &str) -> Option { let token = SimpleTokenizer::new(contents, clause.range) .skip_trivia() .next()?; matches!(token.kind, SimpleTokenKind::Elif | SimpleTokenKind::Else).then_some(token.range()) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum BranchKind { If, Elif, } #[derive(Debug)] pub struct IfElifBranch<'a> { pub kind: BranchKind, pub test: &'a Expr, pub body: &'a [Stmt], 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, test: stmt_if.test.as_ref(), body: stmt_if.body.as_slice(), range: TextRange::new(stmt_if.start(), stmt_if.body.last().unwrap().end()), }) .chain(stmt_if.elif_else_clauses.iter().filter_map(|clause| { Some(IfElifBranch { kind: BranchKind::Elif, test: clause.test.as_ref()?, body: clause.body.as_slice(), range: clause.range, }) })) } ast_serialize-0.13.1/crates/ruff_python_ast/src/str.rs000064400000000000000000000200321046102023000200010ustar00use aho_corasick::{AhoCorasick, AhoCorasickKind, Anchored, Input, MatchKind, StartKind}; use std::fmt; use std::sync::LazyLock; use ruff_text_size::{TextLen, TextRange}; /// Enumeration of the two kinds of quotes that can be used /// for Python string/f/t-string/bytestring literals #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq, is_macro::Is)] pub enum Quote { /// E.g. `'` Single, /// E.g. `"` #[default] Double, } impl Quote { #[inline] pub const fn as_char(self) -> char { match self { Self::Single => '\'', Self::Double => '"', } } #[inline] pub const fn as_str(self) -> &'static str { match self { Self::Single => "'", Self::Double => "\"", } } #[must_use] #[inline] pub const fn opposite(self) -> Self { match self { Self::Single => Self::Double, Self::Double => Self::Single, } } #[inline] pub const fn as_byte(self) -> u8 { match self { Self::Single => b'\'', Self::Double => b'"', } } } impl fmt::Display for Quote { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.as_char()) } } impl TryFrom for Quote { type Error = (); fn try_from(value: char) -> Result { match value { '\'' => Ok(Quote::Single), '"' => Ok(Quote::Double), _ => Err(()), } } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum TripleQuotes { Yes, No, } impl TripleQuotes { #[must_use] pub const fn is_yes(self) -> bool { matches!(self, Self::Yes) } #[must_use] pub const fn is_no(self) -> bool { matches!(self, Self::No) } } /// Includes all permutations of `r`, `u`, `f`, and `fr` (`ur` is invalid, as is `uf`). This /// includes all possible orders, and all possible casings, for both single and triple quotes. /// /// See: #[rustfmt::skip] const TRIPLE_QUOTE_STR_PREFIXES: &[&str] = &[ "FR\"\"\"", "Fr\"\"\"", "fR\"\"\"", "fr\"\"\"", "RF\"\"\"", "Rf\"\"\"", "rF\"\"\"", "rf\"\"\"", "FR'''", "Fr'''", "fR'''", "fr'''", "RF'''", "Rf'''", "rF'''", "rf'''", "R\"\"\"", "r\"\"\"", "R'''", "r'''", "F\"\"\"", "f\"\"\"", "F'''", "f'''", "U\"\"\"", "u\"\"\"", "U'''", "u'''", "\"\"\"", "'''", ]; #[rustfmt::skip] const SINGLE_QUOTE_STR_PREFIXES: &[&str] = &[ "FR\"", "Fr\"", "fR\"", "fr\"", "RF\"", "Rf\"", "rF\"", "rf\"", "FR'", "Fr'", "fR'", "fr'", "RF'", "Rf'", "rF'", "rf'", "R\"", "r\"", "R'", "r'", "F\"", "f\"", "F'", "f'", "U\"", "u\"", "U'", "u'", "\"", "'", ]; /// Includes all permutations of `b` and `rb`. This includes all possible orders, and all possible /// casings, for both single and triple quotes. /// /// See: #[rustfmt::skip] pub(crate) const TRIPLE_QUOTE_BYTE_PREFIXES: &[&str] = &[ "BR\"\"\"", "Br\"\"\"", "bR\"\"\"", "br\"\"\"", "RB\"\"\"", "Rb\"\"\"", "rB\"\"\"", "rb\"\"\"", "BR'''", "Br'''", "bR'''", "br'''", "RB'''", "Rb'''", "rB'''", "rb'''", "B\"\"\"", "b\"\"\"", "B'''", "b'''", ]; #[rustfmt::skip] pub(crate) const SINGLE_QUOTE_BYTE_PREFIXES: &[&str] = &[ "BR\"", "Br\"", "bR\"", "br\"", "RB\"", "Rb\"", "rB\"", "rb\"", "BR'", "Br'", "bR'", "br'", "RB'", "Rb'", "rB'", "rb'", "B\"", "b\"", "B'", "b'", ]; /// Includes all permutations of `t` and `rt`. This includes all possible orders, and all possible /// casings, for both single and triple quotes. /// /// See: #[rustfmt::skip] pub(crate) const TRIPLE_QUOTE_TEMPLATE_PREFIXES: &[&str] = &[ "TR\"\"\"", "Tr\"\"\"", "tR\"\"\"", "tr\"\"\"", "RT\"\"\"", "Rt\"\"\"", "rT\"\"\"", "rt\"\"\"", "TR'''", "Tr'''", "tR'''", "tr'''", "RT'''", "Rt'''", "rT'''", "rt'''", "T\"\"\"", "t\"\"\"", "T'''", "t'''", ]; #[rustfmt::skip] pub(crate) const SINGLE_QUOTE_TEMPLATE_PREFIXES: &[&str] = &[ "TR\"", "Tr\"", "tR\"", "tr\"", "RT\"", "Rt\"", "rT\"", "rt\"", "TR'", "Tr'", "tR'", "tr'", "RT'", "Rt'", "rT'", "rt'", "T\"", "t\"", "T'", "t'", ]; /// Strip the leading and trailing quotes from a string. /// Assumes that the string is a valid string literal, but does not verify that the string /// is a "simple" string literal (i.e., that it does not contain any implicit concatenations). pub fn raw_contents(contents: &str) -> Option<&str> { let range = raw_contents_range(contents)?; Some(&contents[range]) } fn raw_contents_range(contents: &str) -> Option { let leading_quote_str = leading_quote(contents)?; let trailing_quote_str = trailing_quote(contents)?; Some(TextRange::new( leading_quote_str.text_len(), contents.text_len() - trailing_quote_str.text_len(), )) } /// An [`AhoCorasick`] matcher for string, template, and bytes literal prefixes. static PREFIX_MATCHER: LazyLock = LazyLock::new(|| { AhoCorasick::builder() .start_kind(StartKind::Anchored) .match_kind(MatchKind::LeftmostLongest) .kind(Some(AhoCorasickKind::DFA)) .build( TRIPLE_QUOTE_STR_PREFIXES .iter() .chain(TRIPLE_QUOTE_BYTE_PREFIXES) .chain(TRIPLE_QUOTE_TEMPLATE_PREFIXES) .chain(SINGLE_QUOTE_STR_PREFIXES) .chain(SINGLE_QUOTE_BYTE_PREFIXES) .chain(SINGLE_QUOTE_TEMPLATE_PREFIXES), ) .unwrap() }); /// Return the leading quote for a string, template, or bytes literal (e.g., `"""`). pub fn leading_quote(content: &str) -> Option<&str> { let mat = PREFIX_MATCHER.find(Input::new(content).anchored(Anchored::Yes))?; Some(&content[mat.start()..mat.end()]) } /// Return the trailing quote string for a string, template, or bytes literal (e.g., `"""`). pub fn trailing_quote(content: &str) -> Option<&str> { if content.ends_with("'''") { Some("'''") } else if content.ends_with("\"\"\"") { Some("\"\"\"") } else if content.ends_with('\'') { Some("'") } else if content.ends_with('\"') { Some("\"") } else { None } } /// Return `true` if the string is a triple-quote string or byte prefix. pub fn is_triple_quote(content: &str) -> bool { TRIPLE_QUOTE_STR_PREFIXES.contains(&content) || TRIPLE_QUOTE_BYTE_PREFIXES.contains(&content) || TRIPLE_QUOTE_TEMPLATE_PREFIXES.contains(&content) } #[cfg(test)] mod tests { use super::{ SINGLE_QUOTE_BYTE_PREFIXES, SINGLE_QUOTE_STR_PREFIXES, SINGLE_QUOTE_TEMPLATE_PREFIXES, TRIPLE_QUOTE_BYTE_PREFIXES, TRIPLE_QUOTE_STR_PREFIXES, TRIPLE_QUOTE_TEMPLATE_PREFIXES, }; #[test] fn prefix_uniqueness() { let prefixes = TRIPLE_QUOTE_STR_PREFIXES .iter() .chain(TRIPLE_QUOTE_BYTE_PREFIXES) .chain(TRIPLE_QUOTE_TEMPLATE_PREFIXES) .chain(SINGLE_QUOTE_STR_PREFIXES) .chain(SINGLE_QUOTE_BYTE_PREFIXES) .chain(SINGLE_QUOTE_TEMPLATE_PREFIXES) .collect::>(); for (i, prefix_i) in prefixes.iter().enumerate() { for (j, prefix_j) in prefixes.iter().enumerate() { if i > j { assert!( !prefix_i.starts_with(*prefix_j), "Prefixes are not unique: {prefix_i} starts with {prefix_j}", ); } } } } } ast_serialize-0.13.1/crates/ruff_python_ast/src/str_prefix.rs000064400000000000000000000166031046102023000213670ustar00use ruff_text_size::TextSize; use std::fmt; /// Enumerations of the valid prefixes a string literal can have. /// /// Bytestrings and f-strings are excluded from this enumeration, /// as they are represented by different AST nodes. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, is_macro::Is)] pub enum StringLiteralPrefix { /// Just a regular string with no prefixes Empty, /// A string with a `u` or `U` prefix, e.g. `u"foo"`. /// Note that, despite this variant's name, /// it is in fact a no-op at runtime to use the `u` or `U` prefix /// in Python. All Python-3 strings are unicode strings; /// this prefix is only allowed in Python 3 for backwards compatibility /// with Python 2. However, using this prefix in a Python string /// is mutually exclusive with an `r` or `R` prefix. Unicode, /// A "raw" string, that has an `r` or `R` prefix, /// e.g. `r"foo\."` or `R'bar\d'`. Raw { uppercase: bool }, } impl StringLiteralPrefix { /// Return a `str` representation of the prefix pub const fn as_str(self) -> &'static str { match self { Self::Empty => "", Self::Unicode => "u", Self::Raw { uppercase: true } => "R", Self::Raw { uppercase: false } => "r", } } pub const fn text_len(self) -> TextSize { match self { Self::Empty => TextSize::new(0), Self::Unicode | Self::Raw { .. } => TextSize::new(1), } } } impl fmt::Display for StringLiteralPrefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// Enumeration of the valid prefixes an f-string literal can have. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum FStringPrefix { /// Just a regular f-string with no other prefixes, e.g. f"{bar}" Regular, /// A "raw" format-string, that has an `r` or `R` prefix, /// e.g. `rf"{bar}"` or `Rf"{bar}"` Raw { uppercase_r: bool }, } impl FStringPrefix { /// Return a `str` representation of the prefix pub const fn as_str(self) -> &'static str { match self { Self::Regular => "f", Self::Raw { uppercase_r: true } => "Rf", Self::Raw { uppercase_r: false } => "rf", } } pub const fn text_len(self) -> TextSize { match self { Self::Regular => TextSize::new(1), Self::Raw { .. } => TextSize::new(2), } } /// Return true if this prefix indicates a "raw f-string", /// e.g. `rf"{bar}"` or `Rf"{bar}"` pub const fn is_raw(self) -> bool { matches!(self, Self::Raw { .. }) } } impl fmt::Display for FStringPrefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// Enumeration of the valid prefixes a t-string literal can have. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TStringPrefix { /// Just a regular t-string with no other prefixes, e.g. t"{bar}" Regular, /// A "raw" template string, that has an `r` or `R` prefix, /// e.g. `rt"{bar}"` or `Rt"{bar}"` Raw { uppercase_r: bool }, } impl TStringPrefix { /// Return a `str` representation of the prefix pub const fn as_str(self) -> &'static str { match self { Self::Regular => "t", Self::Raw { uppercase_r: true } => "Rt", Self::Raw { uppercase_r: false } => "rt", } } pub const fn text_len(self) -> TextSize { match self { Self::Regular => TextSize::new(1), Self::Raw { .. } => TextSize::new(2), } } /// Return true if this prefix indicates a "raw t-string", /// e.g. `rt"{bar}"` or `Rt"{bar}"` pub const fn is_raw(self) -> bool { matches!(self, Self::Raw { .. }) } } impl fmt::Display for TStringPrefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// Enumeration of the valid prefixes a bytestring literal can have. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum ByteStringPrefix { /// Just a regular bytestring with no other prefixes, e.g. `b"foo"` Regular, /// A "raw" bytestring, that has an `r` or `R` prefix, /// e.g. `Rb"foo"` or `rb"foo"` Raw { uppercase_r: bool }, } impl ByteStringPrefix { /// Return a `str` representation of the prefix pub const fn as_str(self) -> &'static str { match self { Self::Regular => "b", Self::Raw { uppercase_r: true } => "Rb", Self::Raw { uppercase_r: false } => "rb", } } pub const fn text_len(self) -> TextSize { match self { Self::Regular => TextSize::new(1), Self::Raw { .. } => TextSize::new(2), } } /// Return true if this prefix indicates a "raw bytestring", /// e.g. `rb"foo"` or `Rb"foo"` pub const fn is_raw(self) -> bool { matches!(self, Self::Raw { .. }) } } impl fmt::Display for ByteStringPrefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } /// Enumeration of all the possible valid prefixes /// prior to a Python string literal. /// /// Using the `as_flags()` method on variants of this enum /// is the recommended way to set `*_PREFIX` flags from the /// `StringFlags` bitflag, as it means that you cannot accidentally /// set a combination of `*_PREFIX` flags that would be invalid /// at runtime in Python. /// /// [String and Bytes literals]: https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals /// [PEP 701]: https://peps.python.org/pep-0701/ #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, is_macro::Is)] pub enum AnyStringPrefix { /// Prefixes that indicate the string is a bytestring Bytes(ByteStringPrefix), /// Prefixes that indicate the string is an f-string Format(FStringPrefix), /// Prefixes that indicate the string is a t-string Template(TStringPrefix), /// All other prefixes Regular(StringLiteralPrefix), } impl AnyStringPrefix { pub const fn as_str(self) -> &'static str { match self { Self::Regular(regular_prefix) => regular_prefix.as_str(), Self::Bytes(bytestring_prefix) => bytestring_prefix.as_str(), Self::Format(fstring_prefix) => fstring_prefix.as_str(), Self::Template(tstring_prefix) => tstring_prefix.as_str(), } } pub const fn text_len(self) -> TextSize { match self { Self::Regular(regular_prefix) => regular_prefix.text_len(), Self::Bytes(bytestring_prefix) => bytestring_prefix.text_len(), Self::Format(fstring_prefix) => fstring_prefix.text_len(), Self::Template(tstring_prefix) => tstring_prefix.text_len(), } } pub const fn is_raw(self) -> bool { match self { Self::Regular(regular_prefix) => regular_prefix.is_raw(), Self::Bytes(bytestring_prefix) => bytestring_prefix.is_raw(), Self::Format(fstring_prefix) => fstring_prefix.is_raw(), Self::Template(tstring_prefix) => tstring_prefix.is_raw(), } } } impl fmt::Display for AnyStringPrefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } impl Default for AnyStringPrefix { fn default() -> Self { Self::Regular(StringLiteralPrefix::Empty) } } ast_serialize-0.13.1/crates/ruff_python_ast/src/token/parentheses.rs000064400000000000000000000041741046102023000226430ustar00use ruff_text_size::{Ranged, TextLen, TextRange}; use super::{TokenKind, Tokens}; use crate::{AnyNodeRef, ExprRef}; /// Returns an iterator over the ranges of the optional parentheses surrounding an expression. /// /// E.g. for `((f()))` with `f()` as expression, the iterator returns the ranges (1, 6) and (0, 7). /// /// Note that without a parent the range can be inaccurate, e.g. `f(a)` we falsely return a set of /// parentheses around `a` even if the parentheses actually belong to `f`. That is why you should /// generally prefer [`parenthesized_range`]. pub fn parentheses_iterator<'a>( expr: ExprRef<'a>, parent: Option, tokens: &'a Tokens, ) -> impl Iterator + 'a { let after_tokens = if let Some(parent) = parent { // 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. let exclusive_parent_end = if parent.is_arguments() { parent.end() - ")".text_len() } else { parent.end() }; tokens.in_range(TextRange::new(expr.end(), exclusive_parent_end)) } else { tokens.after(expr.end()) }; let right_parens = after_tokens .iter() .filter(|token| !token.kind().is_trivia()) .take_while(move |token| token.kind() == TokenKind::Rpar); let left_parens = tokens .before(expr.start()) .iter() .rev() .filter(|token| !token.kind().is_trivia()) .take_while(|token| token.kind() == TokenKind::Lpar); right_parens .zip(left_parens) .map(|(right, left)| TextRange::new(left.start(), right.end())) } /// 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: ExprRef, parent: AnyNodeRef, tokens: &Tokens, ) -> Option { parentheses_iterator(expr, Some(parent), tokens).last() } ast_serialize-0.13.1/crates/ruff_python_ast/src/token/tokens.rs000064400000000000000000000570541046102023000216320ustar00use std::{iter::FusedIterator, ops::Deref}; use super::{Token, TokenKind}; use ruff_python_trivia::{CommentRanges, ParenthesizedExpressions, TriviaRanges}; use ruff_text_size::{Ranged as _, TextRange, TextSize}; use rustc_hash::FxHashSet; /// Tokens represents a vector of lexed [`Token`]. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Tokens { raw: Vec, } impl Tokens { pub fn new(tokens: Vec) -> Tokens { Tokens { raw: tokens } } /// Returns an iterator over all the tokens that provides context. pub fn iter_with_context(&self) -> TokenIterWithContext<'_> { TokenIterWithContext::new(&self.raw) } /// Performs a binary search to find the index of the **first** token that starts at the given `offset`. /// /// Unlike `binary_search_by_key`, this method ensures that if multiple tokens start at the same offset, /// it returns the index of the first one. Multiple tokens can start at the same offset in cases where /// zero-length tokens are involved (like `Dedent` or `Newline` at the end of the file). fn binary_search_by_start(&self, offset: TextSize) -> Result { let partition_point = self.partition_point(|token| token.start() < offset); let after = &self[partition_point..]; if after.first().is_some_and(|first| first.start() == offset) { Ok(partition_point) } else { Err(partition_point) } } /// Returns a slice of [`Token`] that are within the given `range`. /// /// The start and end offset of the given range should be either: /// 1. Token boundary /// 2. Gap between the tokens /// /// For example, considering the following tokens and their corresponding range: /// /// | Token | Range | /// |---------------------|-----------| /// | `Def` | `0..3` | /// | `Name` | `4..7` | /// | `Lpar` | `7..8` | /// | `Rpar` | `8..9` | /// | `Colon` | `9..10` | /// | `Newline` | `10..11` | /// | `Comment` | `15..24` | /// | `NonLogicalNewline` | `24..25` | /// | `Indent` | `25..29` | /// | `Pass` | `29..33` | /// /// Here, for (1) a token boundary is considered either the start or end offset of any of the /// above tokens. For (2), the gap would be any offset between the `Newline` and `Comment` /// token which are 12, 13, and 14. /// /// Examples: /// 1) `4..10` would give `Name`, `Lpar`, `Rpar`, `Colon` /// 2) `11..25` would give `Comment`, `NonLogicalNewline` /// 3) `12..25` would give same as (2) and offset 12 is in the "gap" /// 4) `9..12` would give `Colon`, `Newline` and offset 12 is in the "gap" /// 5) `18..27` would panic because both the start and end offset is within a token /// /// ## Note /// /// The returned slice can contain the [`TokenKind::Unknown`] token if there was a lexical /// error encountered within the given range. /// /// # Panics /// /// If either the start or end offset of the given range is within a token range. pub fn in_range(&self, range: TextRange) -> &[Token] { let tokens_after_start = self.after(range.start()); Self::before_impl(tokens_after_start, range.end()) } /// Searches the token(s) at `offset`. /// /// Returns [`TokenAt::Between`] if `offset` points directly inbetween two tokens /// (the left token ends at `offset` and the right token starts at `offset`). pub fn at_offset(&self, offset: TextSize) -> TokenAt { match self.binary_search_by_start(offset) { // The token at `index` starts exactly at `offset. // ```python // object.attribute // ^ OFFSET // ``` Ok(index) => { let token = self[index]; // `token` starts exactly at `offset`. Test if the offset is right between // `token` and the previous token (if there's any) if let Some(previous) = index.checked_sub(1).map(|idx| self[idx]) { if previous.end() == offset { return TokenAt::Between(previous, token); } } TokenAt::Single(token) } // No token found that starts exactly at the given offset. But it's possible that // the token starting before `offset` fully encloses `offset` (it's end range ends after `offset`). // ```python // object.attribute // ^ OFFSET // # or // if True: // print("test") // ^ OFFSET // ``` Err(index) => { if let Some(previous) = index.checked_sub(1).map(|idx| self[idx]) { if previous.range().contains_inclusive(offset) { return TokenAt::Single(previous); } } TokenAt::None } } } /// Returns a slice of tokens before the given [`TextSize`] offset. /// /// If the given offset is between two tokens, the returned slice will end just before the /// following token. In other words, if the offset is between the end of previous token and /// start of next token, the returned slice will end just before the next token. /// /// # Panics /// /// If the given offset is inside a token range at any point /// other than the start of the range. pub fn before(&self, offset: TextSize) -> &[Token] { Self::before_impl(&self.raw, offset) } fn before_impl(tokens: &[Token], offset: TextSize) -> &[Token] { let partition_point = tokens.partition_point(|token| token.start() < offset); let before = &tokens[..partition_point]; if let Some(last) = before.last() { // If it's equal to the end offset, then it's at a token boundary which is // valid. If it's greater than the end offset, then it's in the gap between // the tokens which is valid as well. assert!( offset >= last.end(), "Offset {offset:?} is inside token `{last:?}`", ); } before } /// Returns a slice of tokens after the given [`TextSize`] offset. /// /// If the given offset is between two tokens, the returned slice will start from the following /// token. In other words, if the offset is between the end of previous token and start of next /// token, the returned slice will start from the next token. /// /// # Panics /// /// If the given offset is inside a token range at any point /// other than the start of the range. pub fn after(&self, offset: TextSize) -> &[Token] { let partition_point = self.partition_point(|token| token.end() <= offset); let after = &self[partition_point..]; if let Some(first) = after.first() { // valid. If it's greater than the end offset, then it's in the gap between // the tokens which is valid as well. assert!( offset <= first.start(), "Offset {offset:?} is inside token `{first:?}`", ); } after } /// Returns a pair of token slices from both before and after the given [`TextSize`] offset. /// /// If the given offset is between two tokens, the "before" slice will end just before the /// following token. In other words, if the offset is between the end of previous token and /// start of next token, the "before" slice will end just before the next token. The "after" /// slice will contain the rest of the tokens. /// /// Note that the contents of the "after" slice may differ from the results of calling `after()` /// directly, particularly when the given offset occurs on zero-width tokens like `Dedent`. /// /// # Panics /// /// If the given offset is inside a token range at any point /// other than the start of the range. pub fn split_at(&self, offset: TextSize) -> (&[Token], &[Token]) { let partition_point = self.partition_point(|token| token.start() < offset); let (before, after) = &self.raw.split_at(partition_point); if let Some(last) = before.last() { assert!( offset >= last.end(), "Offset {offset:?} is inside token `{last:?}`" ); } (before, after) } /// Return the range of the token at the given offset. /// /// Returns an empty range at the given offset if there's no token at the offset, /// or if the offset is between two tokens. pub fn token_range(&self, offset: TextSize) -> TextRange { match self.at_offset(offset) { TokenAt::Single(token) => token.range(), TokenAt::None | TokenAt::Between(..) => TextRange::empty(offset), } } } impl IntoIterator for Tokens { type Item = Token; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.raw.into_iter() } } impl<'a> IntoIterator for &'a Tokens { type Item = &'a Token; type IntoIter = std::slice::Iter<'a, Token>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl Deref for Tokens { type Target = [Token]; fn deref(&self) -> &Self::Target { &self.raw } } /// A token that encloses a given offset or ends exactly at it. #[derive(Debug, Clone)] pub enum TokenAt { /// There's no token at the given offset None, /// There's a single token at the given offset. Single(Token), /// The offset falls exactly between two tokens. E.g. `CURSOR` in `call(arguments)` is /// positioned exactly between the `call` and `(` tokens. Between(Token, Token), } impl Iterator for TokenAt { type Item = Token; fn next(&mut self) -> Option { match *self { TokenAt::None => None, TokenAt::Single(token) => { *self = TokenAt::None; Some(token) } TokenAt::Between(first, second) => { *self = TokenAt::Single(second); Some(first) } } } } impl FusedIterator for TokenAt {} impl From<&Tokens> for CommentRanges { fn from(tokens: &Tokens) -> Self { let mut ranges = vec![]; for token in tokens { if token.kind() == TokenKind::Comment { ranges.push(token.range()); } } CommentRanges::new(ranges) } } impl From<&Tokens> for TriviaRanges { fn from(tokens: &Tokens) -> Self { let mut comments = vec![]; let mut parenthesized = FxHashSet::default(); let mut stack = Vec::>::new(); let mut previous_end = None; for token in tokens { if token.kind() == TokenKind::Comment { comments.push(token.range()); } if token.kind().is_trivia() { continue; } match token.kind() { TokenKind::Lpar => { if let Some(start) = stack.last_mut() { start.get_or_insert(token.start()); } stack.push(None); } TokenKind::Rpar => { if let (Some(Some(start)), Some(end)) = (stack.pop(), previous_end) { parenthesized.insert(TextRange::new(start, end)); } } _ => { if let Some(start) = stack.last_mut() { start.get_or_insert(token.start()); } } } previous_end = Some(token.end()); } TriviaRanges::new( CommentRanges::new(comments), ParenthesizedExpressions::new(parenthesized), ) } } /// An iterator over the [`Token`]s with context. /// /// This struct is created by the [`iter_with_context`] method on [`Tokens`]. Refer to its /// documentation for more details. /// /// [`iter_with_context`]: Tokens::iter_with_context #[derive(Debug, Clone)] pub struct TokenIterWithContext<'a> { inner: std::slice::Iter<'a, Token>, nesting: u32, } impl<'a> TokenIterWithContext<'a> { fn new(tokens: &'a [Token]) -> TokenIterWithContext<'a> { TokenIterWithContext { inner: tokens.iter(), nesting: 0, } } /// Return the nesting level the iterator is currently in. pub const fn nesting(&self) -> u32 { self.nesting } /// Returns `true` if the iterator is within a parenthesized context. pub const fn in_parenthesized_context(&self) -> bool { self.nesting > 0 } /// Returns the next [`Token`] in the iterator without consuming it. pub fn peek(&self) -> Option<&'a Token> { self.clone().next() } } impl<'a> Iterator for TokenIterWithContext<'a> { type Item = &'a Token; fn next(&mut self) -> Option { let token = self.inner.next()?; match token.kind() { TokenKind::Lpar | TokenKind::Lbrace | TokenKind::Lsqb => self.nesting += 1, TokenKind::Rpar | TokenKind::Rbrace | TokenKind::Rsqb => { self.nesting = self.nesting.saturating_sub(1); } // This mimics the behavior of re-lexing which reduces the nesting level on the lexer. // We don't need to reduce it by 1 because unlike the lexer we see the final token // after recovering from every unclosed parenthesis. TokenKind::Newline if self.nesting > 0 => { self.nesting = 0; } _ => {} } Some(token) } } impl FusedIterator for TokenIterWithContext<'_> {} #[cfg(test)] mod tests { use std::ops::Range; use ruff_text_size::TextSize; use crate::token::{Token, TokenFlags, TokenKind}; use super::*; /// Test case containing a "gap" between two tokens. /// /// Code: const TEST_CASE_WITH_GAP: [(TokenKind, Range); 10] = [ (TokenKind::Def, 0..3), (TokenKind::Name, 4..7), (TokenKind::Lpar, 7..8), (TokenKind::Rpar, 8..9), (TokenKind::Colon, 9..10), (TokenKind::Newline, 10..11), // Gap ||..|| (TokenKind::Comment, 15..24), (TokenKind::NonLogicalNewline, 24..25), (TokenKind::Indent, 25..29), (TokenKind::Pass, 29..33), // No newline at the end to keep the token set full of unique tokens ]; /// Helper function to create [`Tokens`] from an iterator of (kind, range). fn new_tokens(tokens: impl Iterator)>) -> Tokens { Tokens::new( tokens .map(|(kind, range)| { Token::new( kind, TextRange::new(TextSize::new(range.start), TextSize::new(range.end)), TokenFlags::empty(), ) }) .collect(), ) } #[test] fn tokens_after_offset_at_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let after = tokens.after(TextSize::new(8)); assert_eq!(after.len(), 7); assert_eq!(after.first().unwrap().kind(), TokenKind::Rpar); } #[test] fn tokens_after_offset_at_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let after = tokens.after(TextSize::new(11)); assert_eq!(after.len(), 4); assert_eq!(after.first().unwrap().kind(), TokenKind::Comment); } #[test] fn tokens_after_offset_between_tokens() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let after = tokens.after(TextSize::new(13)); assert_eq!(after.len(), 4); assert_eq!(after.first().unwrap().kind(), TokenKind::Comment); } #[test] fn tokens_after_offset_at_last_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let after = tokens.after(TextSize::new(33)); assert_eq!(after.len(), 0); } #[test] #[should_panic(expected = "Offset 5 is inside token `Name 4..7`")] fn tokens_after_offset_inside_token() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); tokens.after(TextSize::new(5)); } #[test] fn tokens_before_offset_at_first_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(0)); assert_eq!(before.len(), 0); } #[test] fn tokens_before_offset_after_first_token_gap() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(3)); assert_eq!(before.len(), 1); assert_eq!(before.last().unwrap().kind(), TokenKind::Def); } #[test] fn tokens_before_offset_at_second_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(4)); assert_eq!(before.len(), 1); assert_eq!(before.last().unwrap().kind(), TokenKind::Def); } #[test] fn tokens_before_offset_at_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(8)); assert_eq!(before.len(), 3); assert_eq!(before.last().unwrap().kind(), TokenKind::Lpar); } #[test] fn tokens_before_offset_at_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(11)); assert_eq!(before.len(), 6); assert_eq!(before.last().unwrap().kind(), TokenKind::Newline); } #[test] fn tokens_before_offset_between_tokens() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(13)); assert_eq!(before.len(), 6); assert_eq!(before.last().unwrap().kind(), TokenKind::Newline); } #[test] fn tokens_before_offset_at_last_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let before = tokens.before(TextSize::new(33)); assert_eq!(before.len(), 10); assert_eq!(before.last().unwrap().kind(), TokenKind::Pass); } #[test] #[should_panic(expected = "Offset 5 is inside token `Name 4..7`")] fn tokens_before_offset_inside_token() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); tokens.before(TextSize::new(5)); } #[test] fn tokens_in_range_at_token_offset() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let in_range = tokens.in_range(TextRange::new(4.into(), 10.into())); assert_eq!(in_range.len(), 4); assert_eq!(in_range.first().unwrap().kind(), TokenKind::Name); assert_eq!(in_range.last().unwrap().kind(), TokenKind::Colon); } #[test] fn tokens_in_range_start_offset_at_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let in_range = tokens.in_range(TextRange::new(11.into(), 29.into())); assert_eq!(in_range.len(), 3); assert_eq!(in_range.first().unwrap().kind(), TokenKind::Comment); assert_eq!(in_range.last().unwrap().kind(), TokenKind::Indent); } #[test] fn tokens_in_range_end_offset_at_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let in_range = tokens.in_range(TextRange::new(8.into(), 15.into())); assert_eq!(in_range.len(), 3); assert_eq!(in_range.first().unwrap().kind(), TokenKind::Rpar); assert_eq!(in_range.last().unwrap().kind(), TokenKind::Newline); } #[test] fn tokens_in_range_start_offset_between_tokens() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let in_range = tokens.in_range(TextRange::new(13.into(), 29.into())); assert_eq!(in_range.len(), 3); assert_eq!(in_range.first().unwrap().kind(), TokenKind::Comment); assert_eq!(in_range.last().unwrap().kind(), TokenKind::Indent); } #[test] fn tokens_in_range_end_offset_between_tokens() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let in_range = tokens.in_range(TextRange::new(9.into(), 13.into())); assert_eq!(in_range.len(), 2); assert_eq!(in_range.first().unwrap().kind(), TokenKind::Colon); assert_eq!(in_range.last().unwrap().kind(), TokenKind::Newline); } #[test] #[should_panic(expected = "Offset 5 is inside token `Name 4..7`")] fn tokens_in_range_start_offset_inside_token() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); tokens.in_range(TextRange::new(5.into(), 10.into())); } #[test] #[should_panic(expected = "Offset 6 is inside token `Name 4..7`")] fn tokens_in_range_end_offset_inside_token() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); tokens.in_range(TextRange::new(0.into(), 6.into())); } #[test] fn tokens_split_at_first_token_start() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let (before, after) = tokens.split_at(TextSize::new(0)); assert_eq!(before.len(), 0); assert_eq!(after.len(), 10); } #[test] fn tokens_split_at_last_token_end() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let (before, after) = tokens.split_at(TextSize::new(33)); assert_eq!(before.len(), 10); assert_eq!(after.len(), 0); } #[test] fn tokens_split_at_inside_gap() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let (before, after) = tokens.split_at(TextSize::new(13)); assert_eq!(before.len(), 6); assert_eq!(after.len(), 4); } #[test] #[should_panic(expected = "Offset 18 is inside token `Comment 15..24`")] fn tokens_split_at_inside_token() { let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); tokens.split_at(TextSize::new(18)); } #[test] fn tokens_split_at_matches_before_and_after() { let offset = TextSize::new(15); let tokens = new_tokens(TEST_CASE_WITH_GAP.into_iter()); let (before, after) = tokens.split_at(offset); assert_eq!(before, tokens.before(offset)); assert_eq!(after, tokens.after(offset)); } #[test] #[should_panic(expected = "Contents of after slice different when offset at dedent")] fn tokens_split_at_matches_before_and_after_zero_length() { let offset = TextSize::new(13); let tokens = new_tokens( [ (TokenKind::If, 0..2), (TokenKind::Name, 3..4), (TokenKind::Colon, 4..5), (TokenKind::Newline, 5..6), (TokenKind::Indent, 6..7), (TokenKind::Pass, 7..11), (TokenKind::Newline, 11..12), (TokenKind::NonLogicalNewline, 12..13), (TokenKind::Dedent, 13..13), (TokenKind::Name, 13..14), (TokenKind::Newline, 14..14), ] .into_iter(), ); let (before, after) = tokens.split_at(offset); assert_eq!(before, tokens.before(offset)); assert!( after == tokens.after(offset), "Contents of after slice different when offset at dedent" ); } } ast_serialize-0.13.1/crates/ruff_python_ast/src/token.rs000064400000000000000000000712771046102023000203320ustar00//! Token kinds for Python source code created by the lexer and consumed by the `ruff_python_parser`. //! //! This module defines the tokens that the lexer recognizes. The tokens are //! loosely based on the token definitions found in the [CPython source]. //! //! [CPython source]: https://github.com/python/cpython/blob/dfc2e065a2e71011017077e549cd2f9bf4944c54/Grammar/Tokens use std::fmt; use bitflags::bitflags; use crate::str::{Quote, TripleQuotes}; use crate::str_prefix::{ AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix, TStringPrefix, }; use crate::{AnyStringFlags, BoolOp, Operator, StringFlags, UnaryOp}; use ruff_text_size::{Ranged, TextRange}; mod parentheses; mod tokens; pub use parentheses::{parentheses_iterator, parenthesized_range}; pub use tokens::{TokenAt, TokenIterWithContext, Tokens}; #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct Token { /// The kind of the token. kind: TokenKind, /// The range of the token. range: TextRange, /// The set of flags describing this token. flags: TokenFlags, } impl Token { pub fn new(kind: TokenKind, range: TextRange, flags: TokenFlags) -> Token { Self { kind, range, flags } } /// Returns the token kind. #[inline] pub const fn kind(&self) -> TokenKind { self.kind } /// Returns the token as a tuple of (kind, range). #[inline] pub const fn as_tuple(&self) -> (TokenKind, TextRange) { (self.kind, self.range) } /// Returns `true` if the current token is a triple-quoted string of any kind. /// /// # Panics /// /// If it isn't a string or any f/t-string tokens. pub fn is_triple_quoted_string(self) -> bool { self.unwrap_string_flags().is_triple_quoted() } /// Returns the [`Quote`] style for the current string token of any kind. /// /// # Panics /// /// If it isn't a string or any f/t-string tokens. pub fn string_quote_style(self) -> Quote { self.unwrap_string_flags().quote_style() } /// Returns the [`AnyStringFlags`] style for the current string token of any kind. /// /// # Panics /// /// If it isn't a string or any f/t-string tokens. pub fn unwrap_string_flags(self) -> AnyStringFlags { self.string_flags() .unwrap_or_else(|| panic!("token to be a string")) } /// Returns true if the current token is a string and it is raw. pub fn string_flags(self) -> Option { if self.is_any_string() { Some(self.flags.as_any_string_flags()) } else { None } } /// Returns `true` if this is any kind of string token - including /// tokens in t-strings (which do not have type `str`). const fn is_any_string(self) -> bool { matches!( self.kind, TokenKind::String | TokenKind::FStringStart | TokenKind::FStringMiddle | TokenKind::FStringEnd | TokenKind::TStringStart | TokenKind::TStringMiddle | TokenKind::TStringEnd ) } } impl Ranged for Token { fn range(&self) -> TextRange { self.range } } impl fmt::Debug for Token { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?} {:?}", self.kind, self.range)?; if !self.flags.is_empty() { f.write_str(" (flags = ")?; let mut first = true; for (name, _) in self.flags.iter_names() { if first { first = false; } else { f.write_str(" | ")?; } f.write_str(name)?; } f.write_str(")")?; } Ok(()) } } /// A kind of a token. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub enum TokenKind { /// Token kind for a name, commonly known as an identifier. Name, /// Token kind for an integer. Int, /// Token kind for a floating point number. Float, /// Token kind for a complex number. Complex, /// Token kind for a string. String, /// Token kind for the start of an f-string. This includes the `f`/`F`/`fr` prefix /// and the opening quote(s). FStringStart, /// Token kind that includes the portion of text inside the f-string that's not /// part of the expression part and isn't an opening or closing brace. FStringMiddle, /// Token kind for the end of an f-string. This includes the closing quote. FStringEnd, /// Token kind for the start of a t-string. This includes the `t`/`T`/`tr` prefix /// and the opening quote(s). TStringStart, /// Token kind that includes the portion of text inside the t-string that's not /// part of the interpolation part and isn't an opening or closing brace. TStringMiddle, /// Token kind for the end of a t-string. This includes the closing quote. TStringEnd, /// Token kind for a IPython escape command. IpyEscapeCommand, /// Token kind for a comment. These are filtered out of the token stream prior to parsing. Comment, /// Token kind for a newline. Newline, /// Token kind for a newline that is not a logical line break. These are filtered out of /// the token stream prior to parsing. NonLogicalNewline, /// Token kind for an indent. Indent, /// Token kind for a dedent. Dedent, EndOfFile, /// Token kind for a question mark `?`. Question, /// Token kind for an exclamation mark `!`. Exclamation, /// Token kind for a left parenthesis `(`. Lpar, /// Token kind for a right parenthesis `)`. Rpar, /// Token kind for a left square bracket `[`. Lsqb, /// Token kind for a right square bracket `]`. Rsqb, /// Token kind for a colon `:`. Colon, /// Token kind for a comma `,`. Comma, /// Token kind for a semicolon `;`. Semi, /// Token kind for plus `+`. Plus, /// Token kind for minus `-`. Minus, /// Token kind for star `*`. Star, /// Token kind for slash `/`. Slash, /// Token kind for vertical bar `|`. Vbar, /// Token kind for ampersand `&`. Amper, /// Token kind for less than `<`. Less, /// Token kind for greater than `>`. Greater, /// Token kind for equal `=`. Equal, /// Token kind for dot `.`. Dot, /// Token kind for percent `%`. Percent, /// Token kind for left bracket `{`. Lbrace, /// Token kind for right bracket `}`. Rbrace, /// Token kind for double equal `==`. EqEqual, /// Token kind for not equal `!=`. NotEqual, /// Token kind for less than or equal `<=`. LessEqual, /// Token kind for greater than or equal `>=`. GreaterEqual, /// Token kind for tilde `~`. Tilde, /// Token kind for caret `^`. CircumFlex, /// Token kind for left shift `<<`. LeftShift, /// Token kind for right shift `>>`. RightShift, /// Token kind for double star `**`. DoubleStar, /// Token kind for double star equal `**=`. DoubleStarEqual, /// Token kind for plus equal `+=`. PlusEqual, /// Token kind for minus equal `-=`. MinusEqual, /// Token kind for star equal `*=`. StarEqual, /// Token kind for slash equal `/=`. SlashEqual, /// Token kind for percent equal `%=`. PercentEqual, /// Token kind for ampersand equal `&=`. AmperEqual, /// Token kind for vertical bar equal `|=`. VbarEqual, /// Token kind for caret equal `^=`. CircumflexEqual, /// Token kind for left shift equal `<<=`. LeftShiftEqual, /// Token kind for right shift equal `>>=`. RightShiftEqual, /// Token kind for double slash `//`. DoubleSlash, /// Token kind for double slash equal `//=`. DoubleSlashEqual, /// Token kind for colon equal `:=`. ColonEqual, /// Token kind for at `@`. At, /// Token kind for at equal `@=`. AtEqual, /// Token kind for arrow `->`. Rarrow, /// Token kind for ellipsis `...`. Ellipsis, // The keywords should be sorted in alphabetical order. If the boundary tokens for the // "Keywords" and "Soft keywords" group change, update the related methods on `TokenKind`. // Keywords And, As, Assert, Async, Await, Break, Class, Continue, Def, Del, Elif, Else, Except, False, Finally, For, From, Global, If, Import, In, Is, Lambda, None, Nonlocal, Not, Or, Pass, Raise, Return, True, Try, While, With, Yield, // Soft keywords Case, Lazy, Match, Type, Unknown, } impl TokenKind { /// Returns `true` if this is an end of file token. #[inline] pub const fn is_eof(self) -> bool { matches!(self, TokenKind::EndOfFile) } /// Returns `true` if this is either a newline or non-logical newline token. #[inline] pub const fn is_any_newline(self) -> bool { matches!(self, TokenKind::Newline | TokenKind::NonLogicalNewline) } /// Returns `true` if the token is a keyword (including soft keywords). /// /// See also [`is_soft_keyword`], [`is_non_soft_keyword`]. /// /// [`is_soft_keyword`]: TokenKind::is_soft_keyword /// [`is_non_soft_keyword`]: TokenKind::is_non_soft_keyword #[inline] pub fn is_keyword(self) -> bool { TokenKind::And <= self && self <= TokenKind::Type } /// Returns `true` if the token is strictly a soft keyword. /// /// See also [`is_keyword`], [`is_non_soft_keyword`]. /// /// [`is_keyword`]: TokenKind::is_keyword /// [`is_non_soft_keyword`]: TokenKind::is_non_soft_keyword #[inline] pub fn is_soft_keyword(self) -> bool { TokenKind::Case <= self && self <= TokenKind::Type } /// Returns `true` if the token is strictly a non-soft keyword. /// /// See also [`is_keyword`], [`is_soft_keyword`]. /// /// [`is_keyword`]: TokenKind::is_keyword /// [`is_soft_keyword`]: TokenKind::is_soft_keyword #[inline] pub fn is_non_soft_keyword(self) -> bool { TokenKind::And <= self && self <= TokenKind::Yield } #[inline] pub const fn is_operator(self) -> bool { matches!( self, TokenKind::Lpar | TokenKind::Rpar | TokenKind::Lsqb | TokenKind::Rsqb | TokenKind::Comma | TokenKind::Semi | TokenKind::Plus | TokenKind::Minus | TokenKind::Star | TokenKind::Slash | TokenKind::Vbar | TokenKind::Amper | TokenKind::Less | TokenKind::Greater | TokenKind::Equal | TokenKind::Dot | TokenKind::Percent | TokenKind::Lbrace | TokenKind::Rbrace | TokenKind::EqEqual | TokenKind::NotEqual | TokenKind::LessEqual | TokenKind::GreaterEqual | TokenKind::Tilde | TokenKind::CircumFlex | TokenKind::LeftShift | TokenKind::RightShift | TokenKind::DoubleStar | TokenKind::PlusEqual | TokenKind::MinusEqual | TokenKind::StarEqual | TokenKind::SlashEqual | TokenKind::PercentEqual | TokenKind::AmperEqual | TokenKind::VbarEqual | TokenKind::CircumflexEqual | TokenKind::LeftShiftEqual | TokenKind::RightShiftEqual | TokenKind::DoubleStarEqual | TokenKind::DoubleSlash | TokenKind::DoubleSlashEqual | TokenKind::At | TokenKind::AtEqual | TokenKind::Rarrow | TokenKind::Ellipsis | TokenKind::ColonEqual | TokenKind::Colon | TokenKind::And | TokenKind::Or | TokenKind::Not | TokenKind::In | TokenKind::Is ) } /// Returns `true` if this is a singleton token i.e., `True`, `False`, or `None`. #[inline] pub const fn is_singleton(self) -> bool { matches!(self, TokenKind::False | TokenKind::True | TokenKind::None) } /// Returns `true` if this is a trivia token i.e., a comment or a non-logical newline. #[inline] pub const fn is_trivia(&self) -> bool { matches!(self, TokenKind::Comment | TokenKind::NonLogicalNewline) } /// Returns `true` if this is a comment token. #[inline] pub const fn is_comment(&self) -> bool { matches!(self, TokenKind::Comment) } #[inline] pub const fn is_arithmetic(self) -> bool { matches!( self, TokenKind::DoubleStar | TokenKind::Star | TokenKind::Plus | TokenKind::Minus | TokenKind::Slash | TokenKind::DoubleSlash | TokenKind::At ) } #[inline] pub const fn is_bitwise_or_shift(self) -> bool { matches!( self, TokenKind::LeftShift | TokenKind::LeftShiftEqual | TokenKind::RightShift | TokenKind::RightShiftEqual | TokenKind::Amper | TokenKind::AmperEqual | TokenKind::Vbar | TokenKind::VbarEqual | TokenKind::CircumFlex | TokenKind::CircumflexEqual | TokenKind::Tilde ) } /// Returns `true` if the current token is a unary arithmetic operator. #[inline] pub const fn is_unary_arithmetic_operator(self) -> bool { matches!(self, TokenKind::Plus | TokenKind::Minus) } #[inline] pub const fn is_interpolated_string_end(self) -> bool { matches!(self, TokenKind::FStringEnd | TokenKind::TStringEnd) } /// Returns the [`UnaryOp`] that corresponds to this token kind, if it is a unary arithmetic /// operator, otherwise return [None]. /// /// Use [`as_unary_operator`] to match against any unary operator. /// /// [`as_unary_operator`]: TokenKind::as_unary_operator #[inline] pub const fn as_unary_arithmetic_operator(self) -> Option { Some(match self { TokenKind::Plus => UnaryOp::UAdd, TokenKind::Minus => UnaryOp::USub, _ => return None, }) } /// Returns the [`UnaryOp`] that corresponds to this token kind, if it is a unary operator, /// otherwise return [None]. /// /// Use [`as_unary_arithmetic_operator`] to match against only an arithmetic unary operator. /// /// [`as_unary_arithmetic_operator`]: TokenKind::as_unary_arithmetic_operator #[inline] pub const fn as_unary_operator(self) -> Option { Some(match self { TokenKind::Plus => UnaryOp::UAdd, TokenKind::Minus => UnaryOp::USub, TokenKind::Tilde => UnaryOp::Invert, TokenKind::Not => UnaryOp::Not, _ => return None, }) } /// Returns the [`BoolOp`] that corresponds to this token kind, if it is a boolean operator, /// otherwise return [None]. #[inline] pub const fn as_bool_operator(self) -> Option { Some(match self { TokenKind::And => BoolOp::And, TokenKind::Or => BoolOp::Or, _ => return None, }) } /// Returns the binary [`Operator`] that corresponds to the current token, if it's a binary /// operator, otherwise return [None]. /// /// Use [`as_augmented_assign_operator`] to match against an augmented assignment token. /// /// [`as_augmented_assign_operator`]: TokenKind::as_augmented_assign_operator pub const fn as_binary_operator(self) -> Option { Some(match self { TokenKind::Plus => Operator::Add, TokenKind::Minus => Operator::Sub, TokenKind::Star => Operator::Mult, TokenKind::At => Operator::MatMult, TokenKind::DoubleStar => Operator::Pow, TokenKind::Slash => Operator::Div, TokenKind::DoubleSlash => Operator::FloorDiv, TokenKind::Percent => Operator::Mod, TokenKind::Amper => Operator::BitAnd, TokenKind::Vbar => Operator::BitOr, TokenKind::CircumFlex => Operator::BitXor, TokenKind::LeftShift => Operator::LShift, TokenKind::RightShift => Operator::RShift, _ => return None, }) } /// Returns the [`Operator`] that corresponds to this token kind, if it is /// an augmented assignment operator, or [`None`] otherwise. #[inline] pub const fn as_augmented_assign_operator(self) -> Option { Some(match self { TokenKind::PlusEqual => Operator::Add, TokenKind::MinusEqual => Operator::Sub, TokenKind::StarEqual => Operator::Mult, TokenKind::AtEqual => Operator::MatMult, TokenKind::DoubleStarEqual => Operator::Pow, TokenKind::SlashEqual => Operator::Div, TokenKind::DoubleSlashEqual => Operator::FloorDiv, TokenKind::PercentEqual => Operator::Mod, TokenKind::AmperEqual => Operator::BitAnd, TokenKind::VbarEqual => Operator::BitOr, TokenKind::CircumflexEqual => Operator::BitXor, TokenKind::LeftShiftEqual => Operator::LShift, TokenKind::RightShiftEqual => Operator::RShift, _ => return None, }) } } impl From for TokenKind { #[inline] fn from(op: BoolOp) -> Self { match op { BoolOp::And => TokenKind::And, BoolOp::Or => TokenKind::Or, } } } impl From for TokenKind { #[inline] fn from(op: UnaryOp) -> Self { match op { UnaryOp::Invert => TokenKind::Tilde, UnaryOp::Not => TokenKind::Not, UnaryOp::UAdd => TokenKind::Plus, UnaryOp::USub => TokenKind::Minus, } } } impl From for TokenKind { #[inline] fn from(op: Operator) -> Self { match op { Operator::Add => TokenKind::Plus, Operator::Sub => TokenKind::Minus, Operator::Mult => TokenKind::Star, Operator::MatMult => TokenKind::At, Operator::Div => TokenKind::Slash, Operator::Mod => TokenKind::Percent, Operator::Pow => TokenKind::DoubleStar, Operator::LShift => TokenKind::LeftShift, Operator::RShift => TokenKind::RightShift, Operator::BitOr => TokenKind::Vbar, Operator::BitXor => TokenKind::CircumFlex, Operator::BitAnd => TokenKind::Amper, Operator::FloorDiv => TokenKind::DoubleSlash, } } } impl fmt::Display for TokenKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let value = match self { TokenKind::Unknown => "Unknown", TokenKind::Newline => "newline", TokenKind::NonLogicalNewline => "NonLogicalNewline", TokenKind::Indent => "indent", TokenKind::Dedent => "dedent", TokenKind::EndOfFile => "end of file", TokenKind::Name => "name", TokenKind::Int => "int", TokenKind::Float => "float", TokenKind::Complex => "complex", TokenKind::String => "string", TokenKind::FStringStart => "FStringStart", TokenKind::FStringMiddle => "FStringMiddle", TokenKind::FStringEnd => "FStringEnd", TokenKind::TStringStart => "TStringStart", TokenKind::TStringMiddle => "TStringMiddle", TokenKind::TStringEnd => "TStringEnd", TokenKind::IpyEscapeCommand => "IPython escape command", TokenKind::Comment => "comment", TokenKind::Question => "`?`", TokenKind::Exclamation => "`!`", TokenKind::Lpar => "`(`", TokenKind::Rpar => "`)`", TokenKind::Lsqb => "`[`", TokenKind::Rsqb => "`]`", TokenKind::Lbrace => "`{`", TokenKind::Rbrace => "`}`", TokenKind::Equal => "`=`", TokenKind::ColonEqual => "`:=`", TokenKind::Dot => "`.`", TokenKind::Colon => "`:`", TokenKind::Semi => "`;`", TokenKind::Comma => "`,`", TokenKind::Rarrow => "`->`", TokenKind::Plus => "`+`", TokenKind::Minus => "`-`", TokenKind::Star => "`*`", TokenKind::DoubleStar => "`**`", TokenKind::Slash => "`/`", TokenKind::DoubleSlash => "`//`", TokenKind::Percent => "`%`", TokenKind::Vbar => "`|`", TokenKind::Amper => "`&`", TokenKind::CircumFlex => "`^`", TokenKind::LeftShift => "`<<`", TokenKind::RightShift => "`>>`", TokenKind::Tilde => "`~`", TokenKind::At => "`@`", TokenKind::Less => "`<`", TokenKind::Greater => "`>`", TokenKind::EqEqual => "`==`", TokenKind::NotEqual => "`!=`", TokenKind::LessEqual => "`<=`", TokenKind::GreaterEqual => "`>=`", TokenKind::PlusEqual => "`+=`", TokenKind::MinusEqual => "`-=`", TokenKind::StarEqual => "`*=`", TokenKind::DoubleStarEqual => "`**=`", TokenKind::SlashEqual => "`/=`", TokenKind::DoubleSlashEqual => "`//=`", TokenKind::PercentEqual => "`%=`", TokenKind::VbarEqual => "`|=`", TokenKind::AmperEqual => "`&=`", TokenKind::CircumflexEqual => "`^=`", TokenKind::LeftShiftEqual => "`<<=`", TokenKind::RightShiftEqual => "`>>=`", TokenKind::AtEqual => "`@=`", TokenKind::Ellipsis => "`...`", TokenKind::False => "`False`", TokenKind::None => "`None`", TokenKind::True => "`True`", TokenKind::And => "`and`", TokenKind::As => "`as`", TokenKind::Assert => "`assert`", TokenKind::Async => "`async`", TokenKind::Await => "`await`", TokenKind::Break => "`break`", TokenKind::Class => "`class`", TokenKind::Continue => "`continue`", TokenKind::Def => "`def`", TokenKind::Del => "`del`", TokenKind::Elif => "`elif`", TokenKind::Else => "`else`", TokenKind::Except => "`except`", TokenKind::Finally => "`finally`", TokenKind::For => "`for`", TokenKind::From => "`from`", TokenKind::Global => "`global`", TokenKind::If => "`if`", TokenKind::Import => "`import`", TokenKind::In => "`in`", TokenKind::Is => "`is`", TokenKind::Lambda => "`lambda`", TokenKind::Nonlocal => "`nonlocal`", TokenKind::Not => "`not`", TokenKind::Or => "`or`", TokenKind::Pass => "`pass`", TokenKind::Raise => "`raise`", TokenKind::Return => "`return`", TokenKind::Try => "`try`", TokenKind::While => "`while`", TokenKind::Lazy => "`lazy`", TokenKind::Match => "`match`", TokenKind::Type => "`type`", TokenKind::Case => "`case`", TokenKind::With => "`with`", TokenKind::Yield => "`yield`", }; f.write_str(value) } } bitflags! { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct TokenFlags: u16 { /// The token is a string with double quotes (`"`). const DOUBLE_QUOTES = 1 << 0; /// The token is a triple-quoted string i.e., it starts and ends with three consecutive /// quote characters (`"""` or `'''`). const TRIPLE_QUOTED_STRING = 1 << 1; /// The token is a unicode string i.e., prefixed with `u` or `U` const UNICODE_STRING = 1 << 2; /// The token is a byte string i.e., prefixed with `b` or `B` const BYTE_STRING = 1 << 3; /// The token is an f-string i.e., prefixed with `f` or `F` const F_STRING = 1 << 4; /// The token is a t-string i.e., prefixed with `t` or `T` const T_STRING = 1 << 5; /// The token is a raw string and the prefix character is in lowercase. const RAW_STRING_LOWERCASE = 1 << 6; /// The token is a raw string and the prefix character is in uppercase. const RAW_STRING_UPPERCASE = 1 << 7; /// String without matching closing quote(s) const UNCLOSED_STRING = 1 << 8; /// The token is a name containing at least one non-ASCII codepoint. const NON_ASCII_NAME = 1 << 9; /// The token is a raw string i.e., prefixed with `r` or `R` const RAW_STRING = Self::RAW_STRING_LOWERCASE.bits() | Self::RAW_STRING_UPPERCASE.bits(); } } #[cfg(feature = "get-size")] impl get_size2::GetSize for TokenFlags {} impl StringFlags for TokenFlags { fn quote_style(self) -> Quote { if self.intersects(TokenFlags::DOUBLE_QUOTES) { Quote::Double } else { Quote::Single } } fn triple_quotes(self) -> TripleQuotes { if self.intersects(TokenFlags::TRIPLE_QUOTED_STRING) { TripleQuotes::Yes } else { TripleQuotes::No } } fn prefix(self) -> AnyStringPrefix { if self.intersects(TokenFlags::F_STRING) { if self.intersects(TokenFlags::RAW_STRING_LOWERCASE) { AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: false }) } else if self.intersects(TokenFlags::RAW_STRING_UPPERCASE) { AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: true }) } else { AnyStringPrefix::Format(FStringPrefix::Regular) } } else if self.intersects(TokenFlags::T_STRING) { if self.intersects(TokenFlags::RAW_STRING_LOWERCASE) { AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: false }) } else if self.intersects(TokenFlags::RAW_STRING_UPPERCASE) { AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: true }) } else { AnyStringPrefix::Template(TStringPrefix::Regular) } } else if self.intersects(TokenFlags::BYTE_STRING) { if self.intersects(TokenFlags::RAW_STRING_LOWERCASE) { AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: false }) } else if self.intersects(TokenFlags::RAW_STRING_UPPERCASE) { AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: true }) } else { AnyStringPrefix::Bytes(ByteStringPrefix::Regular) } } else if self.intersects(TokenFlags::RAW_STRING_LOWERCASE) { AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }) } else if self.intersects(TokenFlags::RAW_STRING_UPPERCASE) { AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: true }) } else if self.intersects(TokenFlags::UNICODE_STRING) { AnyStringPrefix::Regular(StringLiteralPrefix::Unicode) } else { AnyStringPrefix::Regular(StringLiteralPrefix::Empty) } } fn is_unclosed(self) -> bool { self.intersects(TokenFlags::UNCLOSED_STRING) } } impl TokenFlags { /// Returns `true` if the token is an f-string. pub const fn is_f_string(self) -> bool { self.intersects(TokenFlags::F_STRING) } /// Returns `true` if the token is a t-string. pub const fn is_t_string(self) -> bool { self.intersects(TokenFlags::T_STRING) } /// Returns `true` if the token is a t-string. pub const fn is_interpolated_string(self) -> bool { self.intersects(TokenFlags::T_STRING.union(TokenFlags::F_STRING)) } /// Returns `true` if the token is a triple-quoted t-string. pub fn is_triple_quoted_interpolated_string(self) -> bool { self.intersects(TokenFlags::TRIPLE_QUOTED_STRING) && self.is_interpolated_string() } /// Returns `true` if the token is a raw string. pub const fn is_raw_string(self) -> bool { self.intersects(TokenFlags::RAW_STRING) } /// Returns `true` if the token is a name containing at least one non-ASCII codepoint. #[inline] pub const fn is_non_ascii_name(self) -> bool { self.intersects(TokenFlags::NON_ASCII_NAME) } } ast_serialize-0.13.1/crates/ruff_python_ast/src/traversal.rs000064400000000000000000000057541046102023000212120ustar00//! Utilities for manually traversing a Python AST. use crate::{self as ast, AnyNodeRef, ExceptHandler, Stmt}; /// Given a [`Stmt`] and its parent, return the [`ast::Suite`] that contains the [`Stmt`]. pub fn suite<'a>( stmt: impl Into>, parent: impl Into>, ) -> Option> { // TODO: refactor this to work without a parent, ie when `stmt` is at the top level let stmt = stmt.into(); match parent.into() { AnyNodeRef::ModModule(ast::ModModule { body, .. }) => EnclosingSuite::new(body, stmt), AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) => { EnclosingSuite::new(body, stmt) } AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) => EnclosingSuite::new(body, stmt), AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) => [body, orelse] .iter() .find_map(|suite| EnclosingSuite::new(suite, stmt)), AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => [body, orelse] .iter() .find_map(|suite| EnclosingSuite::new(suite, stmt)), AnyNodeRef::StmtIf(ast::StmtIf { body, elif_else_clauses, .. }) => [body] .into_iter() .chain(elif_else_clauses.iter().map(|clause| &clause.body)) .find_map(|suite| EnclosingSuite::new(suite, stmt)), AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) => EnclosingSuite::new(body, stmt), AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => cases .iter() .map(|case| &case.body) .find_map(|body| EnclosingSuite::new(body, stmt)), AnyNodeRef::StmtTry(ast::StmtTry { body, handlers, orelse, finalbody, .. }) => [body, orelse, finalbody] .into_iter() .chain( handlers .iter() .filter_map(ExceptHandler::as_except_handler) .map(|handler| &handler.body), ) .find_map(|suite| EnclosingSuite::new(suite, stmt)), _ => None, } } pub struct EnclosingSuite<'a> { suite: &'a [Stmt], position: usize, } impl<'a> EnclosingSuite<'a> { pub fn new(suite: &'a [Stmt], stmt: AnyNodeRef<'a>) -> Option { let position = suite .iter() .position(|sibling| AnyNodeRef::ptr_eq(sibling.into(), stmt))?; Some(EnclosingSuite { suite, position }) } pub fn next_sibling(&self) -> Option<&'a Stmt> { self.suite.get(self.position + 1) } pub fn next_siblings(&self) -> &'a [Stmt] { self.suite.get(self.position + 1..).unwrap_or_default() } pub fn previous_sibling(&self) -> Option<&'a Stmt> { self.suite.get(self.position.checked_sub(1)?) } } impl std::ops::Deref for EnclosingSuite<'_> { type Target = [Stmt]; fn deref(&self) -> &Self::Target { self.suite } } ast_serialize-0.13.1/crates/ruff_python_ast/src/types.rs000064400000000000000000000001511046102023000203350ustar00use crate::{Expr, Stmt}; #[derive(Clone)] pub enum Node<'a> { Stmt(&'a Stmt), Expr(&'a Expr), } ast_serialize-0.13.1/crates/ruff_python_ast/src/visitor/source_order.rs000064400000000000000000000433171046102023000233760ustar00use crate::{ Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator, ElifElseClause, ExceptHandler, Expr, FString, InterpolatedStringElement, Keyword, MatchCase, Mod, Operator, Parameter, ParameterWithDefault, Parameters, Pattern, PatternArguments, PatternKeyword, Singleton, Stmt, StringLiteral, TString, TypeParam, TypeParams, UnaryOp, WithItem, }; use crate::{AnyNodeRef, Identifier}; /// Visitor that traverses all nodes recursively in the order they appear in the source. /// /// If you need a visitor that visits the nodes in the order they're evaluated at runtime, /// use [`Visitor`](super::Visitor) instead. pub trait SourceOrderVisitor<'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_singleton(&mut self, _singleton: &'a Singleton) {} #[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_arguments(&mut self, arguments: &'a Arguments) { walk_arguments(self, arguments); } #[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_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_pattern_arguments(&mut self, pattern_arguments: &'a PatternArguments) { walk_pattern_arguments(self, pattern_arguments); } #[inline] fn visit_pattern_keyword(&mut self, pattern_keyword: &'a PatternKeyword) { walk_pattern_keyword(self, pattern_keyword); } #[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); } #[inline] fn visit_f_string(&mut self, f_string: &'a FString) { walk_f_string(self, f_string); } #[inline] fn visit_interpolated_string_element( &mut self, interpolated_string_element: &'a InterpolatedStringElement, ) { walk_interpolated_string_element(self, interpolated_string_element); } #[inline] fn visit_t_string(&mut self, t_string: &'a TString) { walk_t_string(self, t_string); } #[inline] fn visit_string_literal(&mut self, string_literal: &'a StringLiteral) { walk_string_literal(self, string_literal); } #[inline] fn visit_bytes_literal(&mut self, bytes_literal: &'a BytesLiteral) { walk_bytes_literal(self, bytes_literal); } #[inline] fn visit_identifier(&mut self, identifier: &'a Identifier) { walk_identifier(self, identifier); } } pub fn walk_module<'a, V>(visitor: &mut V, module: &'a Mod) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(module); if visitor.enter_node(node).is_traverse() { match module { Mod::Module(module) => module.visit_source_order(visitor), Mod::Expression(module) => module.visit_source_order(visitor), } } visitor.leave_node(node); } pub fn walk_body<'a, V>(visitor: &mut V, body: &'a [Stmt]) where V: SourceOrderVisitor<'a> + ?Sized, { for stmt in body { visitor.visit_stmt(stmt); } } pub fn walk_stmt<'a, V>(visitor: &mut V, stmt: &'a Stmt) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(stmt); if visitor.enter_node(node).is_traverse() { stmt.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_node<'a, V>(visitor: &mut V, node: AnyNodeRef<'a>) where V: SourceOrderVisitor<'a> + ?Sized, { if visitor.enter_node(node).is_traverse() { node.visit_source_order(visitor); } visitor.leave_node(node); } #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum TraversalSignal { Traverse, Skip, } impl TraversalSignal { pub const fn is_traverse(self) -> bool { matches!(self, TraversalSignal::Traverse) } } pub fn walk_annotation<'a, V: SourceOrderVisitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } pub fn walk_decorator<'a, V>(visitor: &mut V, decorator: &'a Decorator) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(decorator); if visitor.enter_node(node).is_traverse() { decorator.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_expr<'a, V>(visitor: &mut V, expr: &'a Expr) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(expr); if visitor.enter_node(node).is_traverse() { match expr { Expr::BoolOp(expr) => expr.visit_source_order(visitor), Expr::Named(expr) => expr.visit_source_order(visitor), Expr::BinOp(expr) => expr.visit_source_order(visitor), Expr::UnaryOp(expr) => expr.visit_source_order(visitor), Expr::Lambda(expr) => expr.visit_source_order(visitor), Expr::If(expr) => expr.visit_source_order(visitor), Expr::Dict(expr) => expr.visit_source_order(visitor), Expr::Set(expr) => expr.visit_source_order(visitor), Expr::ListComp(expr) => expr.visit_source_order(visitor), Expr::SetComp(expr) => expr.visit_source_order(visitor), Expr::DictComp(expr) => expr.visit_source_order(visitor), Expr::Generator(expr) => expr.visit_source_order(visitor), Expr::Await(expr) => expr.visit_source_order(visitor), Expr::Yield(expr) => expr.visit_source_order(visitor), Expr::YieldFrom(expr) => expr.visit_source_order(visitor), Expr::Compare(expr) => expr.visit_source_order(visitor), Expr::Call(expr) => expr.visit_source_order(visitor), Expr::FString(expr) => expr.visit_source_order(visitor), Expr::TString(expr) => expr.visit_source_order(visitor), Expr::StringLiteral(expr) => expr.visit_source_order(visitor), Expr::BytesLiteral(expr) => expr.visit_source_order(visitor), Expr::NumberLiteral(expr) => expr.visit_source_order(visitor), Expr::BooleanLiteral(expr) => expr.visit_source_order(visitor), Expr::NoneLiteral(expr) => expr.visit_source_order(visitor), Expr::EllipsisLiteral(expr) => expr.visit_source_order(visitor), Expr::Attribute(expr) => expr.visit_source_order(visitor), Expr::Subscript(expr) => expr.visit_source_order(visitor), Expr::Starred(expr) => expr.visit_source_order(visitor), Expr::Name(expr) => expr.visit_source_order(visitor), Expr::List(expr) => expr.visit_source_order(visitor), Expr::Tuple(expr) => expr.visit_source_order(visitor), Expr::Slice(expr) => expr.visit_source_order(visitor), Expr::IpyEscapeCommand(expr) => expr.visit_source_order(visitor), } } visitor.leave_node(node); } pub fn walk_comprehension<'a, V>(visitor: &mut V, comprehension: &'a Comprehension) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(comprehension); if visitor.enter_node(node).is_traverse() { comprehension.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_elif_else_clause<'a, V>(visitor: &mut V, elif_else_clause: &'a ElifElseClause) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(elif_else_clause); if visitor.enter_node(node).is_traverse() { elif_else_clause.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_except_handler<'a, V>(visitor: &mut V, except_handler: &'a ExceptHandler) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(except_handler); if visitor.enter_node(node).is_traverse() { match except_handler { ExceptHandler::ExceptHandler(except_handler) => { except_handler.visit_source_order(visitor); } } } visitor.leave_node(node); } pub fn walk_format_spec<'a, V: SourceOrderVisitor<'a> + ?Sized>( visitor: &mut V, format_spec: &'a Expr, ) { 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: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(arguments); if visitor.enter_node(node).is_traverse() { arguments.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_parameters<'a, V>(visitor: &mut V, parameters: &'a Parameters) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(parameters); if visitor.enter_node(node).is_traverse() { parameters.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_parameter<'a, V>(visitor: &mut V, parameter: &'a Parameter) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(parameter); if visitor.enter_node(node).is_traverse() { parameter.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_parameter_with_default<'a, V>( visitor: &mut V, parameter_with_default: &'a ParameterWithDefault, ) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(parameter_with_default); if visitor.enter_node(node).is_traverse() { parameter_with_default.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(keyword); if visitor.enter_node(node).is_traverse() { keyword.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_with_item<'a, V>(visitor: &mut V, with_item: &'a WithItem) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(with_item); if visitor.enter_node(node).is_traverse() { with_item.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_type_params<'a, V>(visitor: &mut V, type_params: &'a TypeParams) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(type_params); if visitor.enter_node(node).is_traverse() { type_params.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_type_param<'a, V>(visitor: &mut V, type_param: &'a TypeParam) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(type_param); if visitor.enter_node(node).is_traverse() { type_param.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_match_case<'a, V>(visitor: &mut V, match_case: &'a MatchCase) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(match_case); if visitor.enter_node(node).is_traverse() { match_case.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_pattern<'a, V>(visitor: &mut V, pattern: &'a Pattern) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(pattern); if visitor.enter_node(node).is_traverse() { match pattern { Pattern::MatchValue(pattern) => pattern.visit_source_order(visitor), Pattern::MatchSingleton(pattern) => pattern.visit_source_order(visitor), Pattern::MatchSequence(pattern) => pattern.visit_source_order(visitor), Pattern::MatchMapping(pattern) => pattern.visit_source_order(visitor), Pattern::MatchClass(pattern) => pattern.visit_source_order(visitor), Pattern::MatchStar(pattern) => pattern.visit_source_order(visitor), Pattern::MatchAs(pattern) => pattern.visit_source_order(visitor), Pattern::MatchOr(pattern) => pattern.visit_source_order(visitor), } } visitor.leave_node(node); } pub fn walk_pattern_arguments<'a, V>(visitor: &mut V, pattern_arguments: &'a PatternArguments) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(pattern_arguments); if visitor.enter_node(node).is_traverse() { pattern_arguments.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_pattern_keyword<'a, V>(visitor: &mut V, pattern_keyword: &'a PatternKeyword) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(pattern_keyword); if visitor.enter_node(node).is_traverse() { pattern_keyword.visit_source_order(visitor); } visitor.leave_node(node); } pub fn walk_interpolated_string_element<'a, V: SourceOrderVisitor<'a> + ?Sized>( visitor: &mut V, f_string_element: &'a InterpolatedStringElement, ) { let node = AnyNodeRef::from(f_string_element); if visitor.enter_node(node).is_traverse() { match f_string_element { InterpolatedStringElement::Interpolation(element) => { element.visit_source_order(visitor); } InterpolatedStringElement::Literal(element) => element.visit_source_order(visitor), } } visitor.leave_node(node); } pub fn walk_bool_op<'a, V>(_visitor: &mut V, _bool_op: &'a BoolOp) where V: SourceOrderVisitor<'a> + ?Sized, { } #[inline] pub fn walk_operator<'a, V>(_visitor: &mut V, _operator: &'a Operator) where V: SourceOrderVisitor<'a> + ?Sized, { } #[inline] pub fn walk_unary_op<'a, V>(_visitor: &mut V, _unary_op: &'a UnaryOp) where V: SourceOrderVisitor<'a> + ?Sized, { } #[inline] pub fn walk_cmp_op<'a, V>(_visitor: &mut V, _cmp_op: &'a CmpOp) where V: SourceOrderVisitor<'a> + ?Sized, { } #[inline] pub fn walk_f_string<'a, V>(visitor: &mut V, f_string: &'a FString) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(f_string); if visitor.enter_node(node).is_traverse() { f_string.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_t_string<'a, V>(visitor: &mut V, t_string: &'a TString) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(t_string); if visitor.enter_node(node).is_traverse() { t_string.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_string_literal<'a, V>(visitor: &mut V, string_literal: &'a StringLiteral) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(string_literal); if visitor.enter_node(node).is_traverse() { string_literal.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_bytes_literal<'a, V>(visitor: &mut V, bytes_literal: &'a BytesLiteral) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(bytes_literal); if visitor.enter_node(node).is_traverse() { bytes_literal.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_alias<'a, V>(visitor: &mut V, alias: &'a Alias) where V: SourceOrderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(alias); if visitor.enter_node(node).is_traverse() { alias.visit_source_order(visitor); } visitor.leave_node(node); } #[inline] pub fn walk_identifier<'a, V: SourceOrderVisitor<'a> + ?Sized>( visitor: &mut V, identifier: &'a Identifier, ) { let node = AnyNodeRef::from(identifier); if visitor.enter_node(node).is_traverse() { identifier.visit_source_order(visitor); } visitor.leave_node(node); } ast_serialize-0.13.1/crates/ruff_python_ast/src/visitor/transformer.rs000064400000000000000000000640471046102023000232500ustar00use crate::{ self as ast, Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator, ElifElseClause, ExceptHandler, Expr, ExprContext, FString, InterpolatedStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword, Stmt, StringLiteral, TString, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem, }; /// A trait for transforming ASTs. Visits all nodes in the AST recursively in evaluation-order. pub trait Transformer { fn visit_stmt(&self, stmt: &mut Stmt) { walk_stmt(self, stmt); } fn visit_annotation(&self, expr: &mut Expr) { walk_annotation(self, expr); } fn visit_decorator(&self, decorator: &mut Decorator) { walk_decorator(self, decorator); } fn visit_expr(&self, expr: &mut Expr) { walk_expr(self, expr); } fn visit_expr_context(&self, expr_context: &mut ExprContext) { walk_expr_context(self, expr_context); } fn visit_bool_op(&self, bool_op: &mut BoolOp) { walk_bool_op(self, bool_op); } fn visit_operator(&self, operator: &mut Operator) { walk_operator(self, operator); } fn visit_unary_op(&self, unary_op: &mut UnaryOp) { walk_unary_op(self, unary_op); } fn visit_cmp_op(&self, cmp_op: &mut CmpOp) { walk_cmp_op(self, cmp_op); } fn visit_comprehension(&self, comprehension: &mut Comprehension) { walk_comprehension(self, comprehension); } fn visit_except_handler(&self, except_handler: &mut ExceptHandler) { walk_except_handler(self, except_handler); } fn visit_arguments(&self, arguments: &mut Arguments) { walk_arguments(self, arguments); } fn visit_parameters(&self, parameters: &mut Parameters) { walk_parameters(self, parameters); } fn visit_parameter(&self, parameter: &mut Parameter) { walk_parameter(self, parameter); } fn visit_keyword(&self, keyword: &mut Keyword) { walk_keyword(self, keyword); } fn visit_alias(&self, alias: &mut Alias) { walk_alias(self, alias); } fn visit_with_item(&self, with_item: &mut WithItem) { walk_with_item(self, with_item); } fn visit_type_params(&self, type_params: &mut TypeParams) { walk_type_params(self, type_params); } fn visit_type_param(&self, type_param: &mut TypeParam) { walk_type_param(self, type_param); } fn visit_match_case(&self, match_case: &mut MatchCase) { walk_match_case(self, match_case); } fn visit_pattern(&self, pattern: &mut Pattern) { walk_pattern(self, pattern); } fn visit_pattern_arguments(&self, pattern_arguments: &mut PatternArguments) { walk_pattern_arguments(self, pattern_arguments); } fn visit_pattern_keyword(&self, pattern_keyword: &mut PatternKeyword) { walk_pattern_keyword(self, pattern_keyword); } fn visit_body(&self, body: &mut [Stmt]) { walk_body(self, body); } fn visit_elif_else_clause(&self, elif_else_clause: &mut ElifElseClause) { walk_elif_else_clause(self, elif_else_clause); } fn visit_f_string(&self, f_string: &mut FString) { walk_f_string(self, f_string); } fn visit_interpolated_string_element( &self, interpolated_string_element: &mut InterpolatedStringElement, ) { walk_interpolated_string_element(self, interpolated_string_element); } fn visit_t_string(&self, t_string: &mut TString) { walk_t_string(self, t_string); } fn visit_string_literal(&self, string_literal: &mut StringLiteral) { walk_string_literal(self, string_literal); } fn visit_bytes_literal(&self, bytes_literal: &mut BytesLiteral) { walk_bytes_literal(self, bytes_literal); } } pub fn walk_body(visitor: &V, body: &mut [Stmt]) { for stmt in body { visitor.visit_stmt(stmt); } } pub fn walk_elif_else_clause( visitor: &V, elif_else_clause: &mut ElifElseClause, ) { if let Some(test) = &mut elif_else_clause.test { visitor.visit_expr(test); } visitor.visit_body(&mut elif_else_clause.body); } pub fn walk_stmt(visitor: &V, stmt: &mut Stmt) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { parameters, body, decorator_list, returns, type_params, .. }) => { for decorator in decorator_list { visitor.visit_decorator(decorator); } if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_parameters(parameters); if let Some(expr) = returns { visitor.visit_annotation(expr); } visitor.visit_body(body); } Stmt::ClassDef(ast::StmtClassDef { arguments, body, decorator_list, type_params, .. }) => { 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); } Stmt::Return(ast::StmtReturn { value, range: _, node_index: _, }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } Stmt::Delete(ast::StmtDelete { targets, range: _, node_index: _, }) => { for expr in targets { visitor.visit_expr(expr); } } Stmt::TypeAlias(ast::StmtTypeAlias { range: _, node_index: _, name, type_params, value, }) => { visitor.visit_expr(value); if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_expr(name); } Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { visitor.visit_expr(value); for expr in targets { visitor.visit_expr(expr); } } Stmt::AugAssign(ast::StmtAugAssign { target, op, value, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_operator(op); visitor.visit_expr(target); } Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, .. }) => { if let Some(expr) = value { visitor.visit_expr(expr); } visitor.visit_annotation(annotation); visitor.visit_expr(target); } Stmt::For(ast::StmtFor { 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: _, node_index: _, }) => { visitor.visit_expr(test); visitor.visit_body(body); visitor.visit_body(orelse); } Stmt::If(ast::StmtIf { test, body, elif_else_clauses, range: _, node_index: _, }) => { 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, .. }) => { for with_item in items { visitor.visit_with_item(with_item); } visitor.visit_body(body); } Stmt::Match(ast::StmtMatch { subject, cases, range: _, node_index: _, }) => { visitor.visit_expr(subject); for match_case in cases { visitor.visit_match_case(match_case); } } Stmt::Raise(ast::StmtRaise { exc, cause, range: _, node_index: _, }) => { 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, is_star: _, range: _, node_index: _, }) => { 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: _, node_index: _, }) => { visitor.visit_expr(test); if let Some(expr) = msg { visitor.visit_expr(expr); } } Stmt::Import(ast::StmtImport { names, is_lazy: _, range: _, node_index: _, }) => { for alias in names { visitor.visit_alias(alias); } } Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => { for alias in names { visitor.visit_alias(alias); } } Stmt::Global(_) => {} Stmt::Nonlocal(_) => {} Stmt::Expr(ast::StmtExpr { value, range: _, node_index: _, }) => visitor.visit_expr(value), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {} } } pub fn walk_annotation(visitor: &V, expr: &mut Expr) { visitor.visit_expr(expr); } pub fn walk_decorator(visitor: &V, decorator: &mut Decorator) { visitor.visit_expr(&mut decorator.expression); } pub fn walk_expr(visitor: &V, expr: &mut Expr) { match expr { Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, node_index: _, }) => { visitor.visit_bool_op(op); for expr in values { visitor.visit_expr(expr); } } Expr::Named(ast::ExprNamed { target, value, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr(target); } Expr::BinOp(ast::ExprBinOp { left, op, right, range: _, node_index: _, }) => { visitor.visit_expr(left); visitor.visit_operator(op); visitor.visit_expr(right); } Expr::UnaryOp(ast::ExprUnaryOp { op, operand, range: _, node_index: _, }) => { visitor.visit_unary_op(op); visitor.visit_expr(operand); } Expr::Lambda(ast::ExprLambda { parameters, body, range: _, node_index: _, }) => { if let Some(parameters) = parameters { visitor.visit_parameters(parameters); } visitor.visit_expr(body); } Expr::If(ast::ExprIf { test, body, orelse, range: _, node_index: _, }) => { visitor.visit_expr(test); visitor.visit_expr(body); visitor.visit_expr(orelse); } Expr::Dict(ast::ExprDict { items, range: _, node_index: _, }) => { for ast::DictItem { key, value } in items { if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); } } Expr::Set(ast::ExprSet { elts, range: _, node_index: _, }) => { for expr in elts { visitor.visit_expr(expr); } } Expr::ListComp(ast::ExprListComp { elt, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::SetComp(ast::ExprSetComp { elt, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::DictComp(ast::ExprDictComp { key, value, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); } Expr::Generator(ast::ExprGenerator { elt, generators, range: _, node_index: _, parenthesized: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::Await(ast::ExprAwait { value, range: _, node_index: _, }) => visitor.visit_expr(value), Expr::Yield(ast::ExprYield { value, range: _, node_index: _, }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } Expr::YieldFrom(ast::ExprYieldFrom { value, range: _, node_index: _, }) => visitor.visit_expr(value), Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _, node_index: _, }) => { visitor.visit_expr(left); for cmp_op in &mut **ops { visitor.visit_cmp_op(cmp_op); } for expr in &mut **comparators { visitor.visit_expr(expr); } } Expr::Call(ast::ExprCall { func, arguments, range_start: _, node_index: _, }) => { visitor.visit_expr(func); visitor.visit_arguments(arguments); } Expr::FString(ast::ExprFString { value, .. }) => { for f_string_part in value.iter_mut() { match f_string_part { ast::FStringPart::Literal(string_literal) => { visitor.visit_string_literal(string_literal); } ast::FStringPart::FString(f_string) => { visitor.visit_f_string(f_string); } } } } Expr::TString(ast::ExprTString { value, .. }) => { for t_string in value.iter_mut() { visitor.visit_t_string(t_string); } } Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => { for string_literal in value.iter_mut() { visitor.visit_string_literal(string_literal); } } Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => { for bytes_literal in value.iter_mut() { visitor.visit_bytes_literal(bytes_literal); } } Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) => {} Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } Expr::Subscript(ast::ExprSubscript { value, slice, ctx, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr(slice); visitor.visit_expr_context(ctx); } Expr::Starred(ast::ExprStarred { value, ctx, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } Expr::Name(ast::ExprName { ctx, .. }) => { visitor.visit_expr_context(ctx); } Expr::List(ast::ExprList { elts, ctx, range: _, node_index: _, }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } Expr::Tuple(ast::ExprTuple { elts, ctx, range: _, node_index: _, parenthesized: _, }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } Expr::Slice(ast::ExprSlice { lower, upper, step, range: _, node_index: _, }) => { 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::IpyEscapeCommand(_) => {} } } pub fn walk_comprehension(visitor: &V, comprehension: &mut Comprehension) { visitor.visit_expr(&mut comprehension.iter); visitor.visit_expr(&mut comprehension.target); for expr in &mut comprehension.ifs { visitor.visit_expr(expr); } } pub fn walk_except_handler( visitor: &V, except_handler: &mut ExceptHandler, ) { match except_handler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => { if let Some(expr) = type_ { visitor.visit_expr(expr); } visitor.visit_body(body); } } } pub fn walk_arguments(visitor: &V, arguments: &mut Arguments) { // Note that there might be keywords before the last arg, e.g. in // f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then // `keywords`. See also [Arguments::arguments_source_order`]. for arg in &mut *arguments.args { visitor.visit_expr(arg); } for keyword in &mut *arguments.keywords { visitor.visit_keyword(keyword); } } pub fn walk_parameters(visitor: &V, parameters: &mut Parameters) { // Defaults are evaluated before annotations. for arg in &mut parameters.posonlyargs { if let Some(default) = &mut arg.default { visitor.visit_expr(default); } } for arg in &mut parameters.args { if let Some(default) = &mut arg.default { visitor.visit_expr(default); } } for arg in &mut parameters.kwonlyargs { if let Some(default) = &mut arg.default { visitor.visit_expr(default); } } for arg in &mut parameters.posonlyargs { visitor.visit_parameter(&mut arg.parameter); } for arg in &mut parameters.args { visitor.visit_parameter(&mut arg.parameter); } if let Some(arg) = &mut parameters.vararg { visitor.visit_parameter(arg); } for arg in &mut parameters.kwonlyargs { visitor.visit_parameter(&mut arg.parameter); } if let Some(arg) = &mut parameters.kwarg { visitor.visit_parameter(arg); } } pub fn walk_parameter(visitor: &V, parameter: &mut Parameter) { if let Some(expr) = &mut parameter.annotation { visitor.visit_annotation(expr); } } pub fn walk_keyword(visitor: &V, keyword: &mut Keyword) { visitor.visit_expr(&mut keyword.value); } pub fn walk_with_item(visitor: &V, with_item: &mut WithItem) { visitor.visit_expr(&mut with_item.context_expr); if let Some(expr) = &mut with_item.optional_vars { visitor.visit_expr(expr); } } pub fn walk_type_params(visitor: &V, type_params: &mut TypeParams) { for type_param in &mut type_params.type_params { visitor.visit_type_param(type_param); } } pub fn walk_type_param(visitor: &V, type_param: &mut TypeParam) { match type_param { TypeParam::TypeVar(TypeParamTypeVar { bound, default, name: _, range: _, node_index: _, }) => { if let Some(expr) = bound { visitor.visit_expr(expr); } if let Some(expr) = default { visitor.visit_expr(expr); } } TypeParam::TypeVarTuple(TypeParamTypeVarTuple { default, name: _, range: _, node_index: _, }) => { if let Some(expr) = default { visitor.visit_expr(expr); } } TypeParam::ParamSpec(TypeParamParamSpec { default, name: _, range: _, node_index: _, }) => { if let Some(expr) = default { visitor.visit_expr(expr); } } } } pub fn walk_match_case(visitor: &V, match_case: &mut MatchCase) { visitor.visit_pattern(&mut match_case.pattern); if let Some(expr) = &mut match_case.guard { visitor.visit_expr(expr); } visitor.visit_body(&mut match_case.body); } pub fn walk_pattern(visitor: &V, pattern: &mut Pattern) { match pattern { Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => { visitor.visit_expr(value); } Pattern::MatchSingleton(_) => {} Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } } Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { for expr in keys { visitor.visit_expr(expr); } for pattern in patterns { visitor.visit_pattern(pattern); } } Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => { visitor.visit_expr(cls); visitor.visit_pattern_arguments(arguments); } Pattern::MatchStar(_) => {} Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => { if let Some(pattern) = pattern { visitor.visit_pattern(pattern); } } Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } } } } pub fn walk_pattern_arguments( visitor: &V, pattern_arguments: &mut PatternArguments, ) { for pattern in &mut pattern_arguments.patterns { visitor.visit_pattern(pattern); } for keyword in &mut pattern_arguments.keywords { visitor.visit_pattern_keyword(keyword); } } pub fn walk_pattern_keyword( visitor: &V, pattern_keyword: &mut PatternKeyword, ) { visitor.visit_pattern(&mut pattern_keyword.pattern); } pub fn walk_f_string(visitor: &V, f_string: &mut FString) { for element in &mut f_string.elements { visitor.visit_interpolated_string_element(element); } } pub fn walk_interpolated_string_element( visitor: &V, interpolated_string_element: &mut InterpolatedStringElement, ) { if let ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement { expression, format_spec, .. }) = interpolated_string_element { visitor.visit_expr(expression); if let Some(format_spec) = format_spec { for spec_element in &mut format_spec.elements { visitor.visit_interpolated_string_element(spec_element); } } } } pub fn walk_t_string(visitor: &V, t_string: &mut TString) { for element in &mut t_string.elements { visitor.visit_interpolated_string_element(element); } } pub fn walk_expr_context(_visitor: &V, _expr_context: &mut ExprContext) {} pub fn walk_bool_op(_visitor: &V, _bool_op: &mut BoolOp) {} pub fn walk_operator(_visitor: &V, _operator: &mut Operator) {} pub fn walk_unary_op(_visitor: &V, _unary_op: &mut UnaryOp) {} pub fn walk_cmp_op(_visitor: &V, _cmp_op: &mut CmpOp) {} pub fn walk_alias(_visitor: &V, _alias: &mut Alias) {} pub fn walk_string_literal( _visitor: &V, _string_literal: &mut StringLiteral, ) { } pub fn walk_bytes_literal( _visitor: &V, _bytes_literal: &mut BytesLiteral, ) { } ast_serialize-0.13.1/crates/ruff_python_ast/src/visitor.rs000064400000000000000000000637731046102023000207130ustar00//! AST visitor trait and walk functions. pub mod source_order; pub mod transformer; use crate::{ self as ast, Alias, AnyParameterRef, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator, ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringPart, InterpolatedStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword, Stmt, StringLiteral, TString, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem, }; /// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order. /// /// Prefer [`crate::statement_visitor::StatementVisitor`] for visitors that only need to visit /// statements. /// /// Use the [`PreorderVisitor`](source_order::SourceOrderVisitor) if you want to visit the nodes /// in source-order rather than evaluation order. /// /// Use the [`Transformer`](transformer::Transformer) if you want to modify the nodes. pub trait Visitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { walk_stmt(self, stmt); } fn visit_annotation(&mut self, expr: &'a Expr) { walk_annotation(self, expr); } fn visit_decorator(&mut self, decorator: &'a Decorator) { walk_decorator(self, decorator); } fn visit_expr(&mut self, expr: &'a Expr) { walk_expr(self, expr); } fn visit_expr_context(&mut self, expr_context: &'a ExprContext) { walk_expr_context(self, expr_context); } fn visit_bool_op(&mut self, bool_op: &'a BoolOp) { walk_bool_op(self, bool_op); } fn visit_operator(&mut self, operator: &'a Operator) { walk_operator(self, operator); } fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) { walk_unary_op(self, unary_op); } fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) { walk_cmp_op(self, cmp_op); } fn visit_comprehension(&mut self, comprehension: &'a Comprehension) { walk_comprehension(self, comprehension); } fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) { walk_except_handler(self, except_handler); } fn visit_arguments(&mut self, arguments: &'a Arguments) { walk_arguments(self, arguments); } 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); } fn visit_alias(&mut self, alias: &'a Alias) { walk_alias(self, alias); } 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); } fn visit_match_case(&mut self, match_case: &'a MatchCase) { walk_match_case(self, match_case); } fn visit_pattern(&mut self, pattern: &'a Pattern) { walk_pattern(self, pattern); } fn visit_pattern_arguments(&mut self, pattern_arguments: &'a PatternArguments) { walk_pattern_arguments(self, pattern_arguments); } fn visit_pattern_keyword(&mut self, pattern_keyword: &'a PatternKeyword) { walk_pattern_keyword(self, pattern_keyword); } fn visit_body(&mut self, body: &'a [Stmt]) { walk_body(self, body); } fn visit_elif_else_clause(&mut self, elif_else_clause: &'a ElifElseClause) { walk_elif_else_clause(self, elif_else_clause); } fn visit_f_string(&mut self, f_string: &'a FString) { walk_f_string(self, f_string); } fn visit_interpolated_string_element( &mut self, interpolated_string_element: &'a InterpolatedStringElement, ) { walk_interpolated_string_element(self, interpolated_string_element); } fn visit_t_string(&mut self, t_string: &'a TString) { walk_t_string(self, t_string); } fn visit_string_literal(&mut self, string_literal: &'a StringLiteral) { walk_string_literal(self, string_literal); } fn visit_bytes_literal(&mut self, bytes_literal: &'a BytesLiteral) { walk_bytes_literal(self, bytes_literal); } } pub fn walk_body<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, body: &'a [Stmt]) { for stmt in body { visitor.visit_stmt(stmt); } } pub fn walk_elif_else_clause<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, elif_else_clause: &'a ElifElseClause, ) { if let Some(test) = &elif_else_clause.test { visitor.visit_expr(test); } visitor.visit_body(&elif_else_clause.body); } pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { parameters, body, decorator_list, returns, type_params, .. }) => { for decorator in decorator_list { visitor.visit_decorator(decorator); } if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_parameters(parameters); if let Some(expr) = returns { visitor.visit_annotation(expr); } visitor.visit_body(body); } Stmt::ClassDef(ast::StmtClassDef { arguments, body, decorator_list, type_params, .. }) => { 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); } Stmt::Return(ast::StmtReturn { value, range: _, node_index: _, }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } Stmt::Delete(ast::StmtDelete { targets, range: _, node_index: _, }) => { for expr in targets { visitor.visit_expr(expr); } } Stmt::TypeAlias(ast::StmtTypeAlias { range: _, node_index: _, name, type_params, value, }) => { visitor.visit_expr(value); if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } visitor.visit_expr(name); } Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { visitor.visit_expr(value); for expr in targets { visitor.visit_expr(expr); } } Stmt::AugAssign(ast::StmtAugAssign { target, op, value, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_operator(op); visitor.visit_expr(target); } Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, .. }) => { if let Some(expr) = value { visitor.visit_expr(expr); } visitor.visit_annotation(annotation); visitor.visit_expr(target); } Stmt::For(ast::StmtFor { 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: _, node_index: _, }) => { visitor.visit_expr(test); visitor.visit_body(body); visitor.visit_body(orelse); } Stmt::If(ast::StmtIf { test, body, elif_else_clauses, range: _, node_index: _, }) => { 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, .. }) => { for with_item in items { visitor.visit_with_item(with_item); } visitor.visit_body(body); } Stmt::Match(ast::StmtMatch { subject, cases, range: _, node_index: _, }) => { visitor.visit_expr(subject); for match_case in cases { visitor.visit_match_case(match_case); } } Stmt::Raise(ast::StmtRaise { exc, cause, range: _, node_index: _, }) => { 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, is_star: _, range: _, node_index: _, }) => { 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: _, node_index: _, }) => { visitor.visit_expr(test); if let Some(expr) = msg { visitor.visit_expr(expr); } } Stmt::Import(ast::StmtImport { names, is_lazy: _, range: _, node_index: _, }) => { for alias in names { visitor.visit_alias(alias); } } Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => { for alias in names { visitor.visit_alias(alias); } } Stmt::Global(_) => {} Stmt::Nonlocal(_) => {} Stmt::Expr(ast::StmtExpr { value, range: _, node_index: _, }) => visitor.visit_expr(value), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {} } } pub fn walk_annotation<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } pub fn walk_decorator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, decorator: &'a Decorator) { visitor.visit_expr(&decorator.expression); } pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { match expr { Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, node_index: _, }) => { visitor.visit_bool_op(op); for expr in values { visitor.visit_expr(expr); } } Expr::Named(ast::ExprNamed { target, value, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr(target); } Expr::BinOp(ast::ExprBinOp { left, op, right, range: _, node_index: _, }) => { visitor.visit_expr(left); visitor.visit_operator(op); visitor.visit_expr(right); } Expr::UnaryOp(ast::ExprUnaryOp { op, operand, range: _, node_index: _, }) => { visitor.visit_unary_op(op); visitor.visit_expr(operand); } Expr::Lambda(ast::ExprLambda { parameters, body, range: _, node_index: _, }) => { if let Some(parameters) = parameters { visitor.visit_parameters(parameters); } visitor.visit_expr(body); } Expr::If(ast::ExprIf { test, body, orelse, range: _, node_index: _, }) => { visitor.visit_expr(test); visitor.visit_expr(body); visitor.visit_expr(orelse); } Expr::Dict(ast::ExprDict { items, range: _, node_index: _, }) => { for ast::DictItem { key, value } in items { if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); } } Expr::Set(ast::ExprSet { elts, range: _, node_index: _, }) => { for expr in elts { visitor.visit_expr(expr); } } Expr::ListComp(ast::ExprListComp { elt, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::SetComp(ast::ExprSetComp { elt, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::DictComp(ast::ExprDictComp { key, value, generators, range: _, node_index: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } if let Some(key) = key { visitor.visit_expr(key); } visitor.visit_expr(value); } Expr::Generator(ast::ExprGenerator { elt, generators, range: _, node_index: _, parenthesized: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } Expr::Await(ast::ExprAwait { value, range: _, node_index: _, }) => visitor.visit_expr(value), Expr::Yield(ast::ExprYield { value, range: _, node_index: _, }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } Expr::YieldFrom(ast::ExprYieldFrom { value, range: _, node_index: _, }) => visitor.visit_expr(value), Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _, node_index: _, }) => { visitor.visit_expr(left); for cmp_op in ops { visitor.visit_cmp_op(cmp_op); } for expr in comparators { visitor.visit_expr(expr); } } Expr::Call(ast::ExprCall { func, arguments, range_start: _, node_index: _, }) => { visitor.visit_expr(func); visitor.visit_arguments(arguments); } Expr::FString(ast::ExprFString { value, .. }) => { for part in value { match part { FStringPart::Literal(string_literal) => { visitor.visit_string_literal(string_literal); } FStringPart::FString(f_string) => visitor.visit_f_string(f_string), } } } Expr::TString(ast::ExprTString { value, .. }) => { for t_string in value { visitor.visit_t_string(t_string); } } Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => { for string_literal in value { visitor.visit_string_literal(string_literal); } } Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => { for bytes_literal in value { visitor.visit_bytes_literal(bytes_literal); } } Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::NoneLiteral(_) | Expr::EllipsisLiteral(_) => {} Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } Expr::Subscript(ast::ExprSubscript { value, slice, ctx, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr(slice); visitor.visit_expr_context(ctx); } Expr::Starred(ast::ExprStarred { value, ctx, range: _, node_index: _, }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } Expr::Name(ast::ExprName { ctx, .. }) => { visitor.visit_expr_context(ctx); } Expr::List(ast::ExprList { elts, ctx, range: _, node_index: _, }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } Expr::Tuple(ast::ExprTuple { elts, ctx, range: _, node_index: _, parenthesized: _, }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } Expr::Slice(ast::ExprSlice { lower, upper, step, range: _, node_index: _, }) => { 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::IpyEscapeCommand(_) => {} } } pub fn walk_comprehension<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, comprehension: &'a Comprehension, ) { visitor.visit_expr(&comprehension.iter); visitor.visit_expr(&comprehension.target); for expr in &comprehension.ifs { visitor.visit_expr(expr); } } pub fn walk_except_handler<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, except_handler: &'a ExceptHandler, ) { match except_handler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => { if let Some(expr) = type_ { visitor.visit_expr(expr); } visitor.visit_body(body); } } } pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) { // Note that there might be keywords before the last arg, e.g. in // f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then // `keywords`. See also [Arguments::arguments_source_order`]. 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 default in parameters .iter_non_variadic_params() .filter_map(|param| param.default.as_deref()) { visitor.visit_expr(default); } for parameter in parameters.iter().map(AnyParameterRef::as_parameter) { visitor.visit_parameter(parameter); } } 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); } } pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) { visitor.visit_expr(&keyword.value); } pub fn walk_with_item<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, with_item: &'a WithItem) { visitor.visit_expr(&with_item.context_expr); if let Some(expr) = &with_item.optional_vars { visitor.visit_expr(expr); } } 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 { bound, default, name: _, range: _, node_index: _, }) => { if let Some(expr) = bound { visitor.visit_expr(expr); } if let Some(expr) = default { visitor.visit_expr(expr); } } TypeParam::TypeVarTuple(TypeParamTypeVarTuple { default, name: _, range: _, node_index: _, }) => { if let Some(expr) = default { visitor.visit_expr(expr); } } TypeParam::ParamSpec(TypeParamParamSpec { default, name: _, range: _, node_index: _, }) => { if let Some(expr) = default { visitor.visit_expr(expr); } } } } pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: &'a MatchCase) { visitor.visit_pattern(&match_case.pattern); if let Some(expr) = &match_case.guard { visitor.visit_expr(expr); } visitor.visit_body(&match_case.body); } pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) { match pattern { Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => { visitor.visit_expr(value); } Pattern::MatchSingleton(_) => {} Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } } Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { for expr in keys { visitor.visit_expr(expr); } for pattern in patterns { visitor.visit_pattern(pattern); } } Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => { visitor.visit_expr(cls); visitor.visit_pattern_arguments(arguments); } Pattern::MatchStar(_) => {} Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => { if let Some(pattern) = pattern { visitor.visit_pattern(pattern); } } Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } } } } pub fn walk_pattern_arguments<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, pattern_arguments: &'a PatternArguments, ) { for pattern in &pattern_arguments.patterns { visitor.visit_pattern(pattern); } for keyword in &pattern_arguments.keywords { visitor.visit_pattern_keyword(keyword); } } pub fn walk_pattern_keyword<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, pattern_keyword: &'a PatternKeyword, ) { visitor.visit_pattern(&pattern_keyword.pattern); } pub fn walk_f_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, f_string: &'a FString) { for interpolated_string_element in &f_string.elements { visitor.visit_interpolated_string_element(interpolated_string_element); } } pub fn walk_interpolated_string_element<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, interpolated_string_element: &'a InterpolatedStringElement, ) { if let ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement { expression, format_spec, .. }) = interpolated_string_element { visitor.visit_expr(expression); if let Some(format_spec) = format_spec { for spec_element in &format_spec.elements { visitor.visit_interpolated_string_element(spec_element); } } } } pub fn walk_t_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, t_string: &'a TString) { for t_string_element in &t_string.elements { visitor.visit_interpolated_string_element(t_string_element); } } pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>( _visitor: &V, _expr_context: &'a ExprContext, ) { } pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _bool_op: &'a BoolOp) {} pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _operator: &'a Operator) {} pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _unary_op: &'a UnaryOp) {} pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _cmp_op: &'a CmpOp) {} pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _alias: &'a Alias) {} pub fn walk_string_literal<'a, V: Visitor<'a> + ?Sized>( _visitor: &V, _string_literal: &'a StringLiteral, ) { } pub fn walk_bytes_literal<'a, V: Visitor<'a> + ?Sized>( _visitor: &V, _bytes_literal: &'a BytesLiteral, ) { } ast_serialize-0.13.1/crates/ruff_python_ast/src/whitespace.rs000064400000000000000000000025421046102023000213330ustar00use ruff_python_trivia::{PythonWhitespace, indentation_at_offset, is_python_whitespace}; use ruff_source_file::{LineRanges, UniversalNewlineIterator}; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::Stmt; /// Extract the leading indentation from a line. #[inline] pub fn indentation<'a, T>(source: &'a str, located: &T) -> Option<&'a str> where T: Ranged, { indentation_at_offset(located.start(), source) } /// Return the end offset at which the empty lines following a statement. pub fn trailing_lines_end(stmt: &Stmt, source: &str) -> TextSize { let line_end = source.full_line_end(stmt.end()); UniversalNewlineIterator::with_offset(&source[line_end.to_usize()..], line_end) .take_while(|line| line.trim_whitespace().is_empty()) .last() .map_or(line_end, |line| line.full_end()) } /// If a [`Ranged`] has a trailing comment, return the index of the hash. pub fn trailing_comment_start_offset(located: &T, source: &str) -> Option where T: Ranged, { let line_end = source.line_end(located.end()); let trailing = &source[TextRange::new(located.end(), line_end)]; for (index, char) in trailing.char_indices() { if char == '#' { return TextSize::try_from(index).ok(); } if !is_python_whitespace(char) { return None; } } None } ast_serialize-0.13.1/crates/ruff_python_parser/CONTRIBUTING.md000064400000000000000000000051121046102023000207740ustar00# Contributing to the Python Parser ## Development ### Inline tests The parser crate supports writing inline tests. These are tests that are written in the source code itself, and are extracted to a separate file and run with the test suite. They are written in the form of comments with a specific format. There are two forms of inline tests: Test that the parser successfully parses the input with no syntax errors. They're written in the following format: ```rs // test_ok this_is_the_test_name // def foo(): // pass println!("some rust code"); ``` Test that the parser fails to parse the input with a syntax error. They're written in the following format: ```rs // test_err this_is_the_test_name // [1, 2 println!("some rust code"); ``` Note that the difference between the two is the `test_ok` and `test_err` keywords. The comment block must be independent of any other comment blocks. For example, the following is not extracted: ```rs // Some random comment // // test_ok this_is_the_test_name // def foo(): // pass println!("some rust code"); ``` To generate the corresponding Python files for the inline tests, run the following command: ```sh cargo test --package ruff_python_parser --test generate_inline_tests ``` Then, run the Parser test suite with the following command: ```sh cargo test --package ruff_python_parser ``` ### Python-based fuzzer The Ruff project includes a Python-based fuzzer that can be used to run the parser on randomly generated (but syntactically valid) Python source code files. To run the fuzzer, execute the following command (requires [`uv`](https://github.com/astral-sh/uv) to be installed): ```sh uv run --project=./python/py-fuzzer fuzz ``` Refer to the [py-fuzzer](https://github.com/astral-sh/ruff/blob/main/python/py-fuzzer/fuzz.py) script for more information or use the `--help` flag to see the available options. #### CI The fuzzer is run as part of the CI pipeline. The purpose of running the fuzzer in the CI is to catch any regressions introduced by any new changes to the parser. This is why the fuzzer is run on the same set of seeds on every run. ## Benchmarks The `ruff_benchmark` crate can benchmark both the lexer and the parser. To run the lexer benchmarks, use the following command: ```sh cargo bench --package ruff_benchmark --bench lexer ``` And to run the parser benchmarks, use the following command: ```sh cargo bench --package ruff_benchmark --bench parser ``` Refer to the [Benchmarking and Profiling](https://docs.astral.sh/ruff/contributing/#benchmark-driven-development) section in the contributing guide for more information. ast_serialize-0.13.1/crates/ruff_python_parser/Cargo.toml000064400000000000000000000027011046102023000204740ustar00[package] name = "ruff_python_parser" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = ["Charlie Marsh ", "RustPython Team"] edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [lib] [dependencies] ruff_python_ast = { workspace = true, features = ["get-size"] } ruff_python_trivia = { workspace = true } ruff_text_size = { workspace = true, features = ["get-size"] } bitflags = { workspace = true } bstr = { workspace = true } drop_bomb = { workspace = true } get-size2 = { workspace = true } memchr = { workspace = true } rustc-hash = { workspace = true } static_assertions = { workspace = true } thin-vec = { workspace = true } unicode-ident = { workspace = true } unicode-normalization = { workspace = true } unicode_names2 = { workspace = true } [dev-dependencies] ruff_annotate_snippets = { workspace = true } ruff_python_ast = { workspace = true, features = ["serde"] } ruff_source_file = { workspace = true } anyhow = { workspace = true } datatest-stable = { workspace = true } insta = { workspace = true } itertools = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } walkdir = { workspace = true } [[test]] name = "fixtures" harness = false [lints] workspace = true ast_serialize-0.13.1/crates/ruff_python_parser/README.md000064400000000000000000000026211046102023000200240ustar00# Ruff Python Parser Ruff's Python parser is a hand-written [recursive descent parser] which can parse Python source code into an [Abstract Syntax Tree (AST)](https://crates.io/crates/ruff_python_ast). It also utilizes the [Pratt parsing](https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html) technique to parse expressions with different [precedence](https://docs.python.org/3/reference/expressions.html#operator-precedence). Try out the parser in the [playground](https://play.ruff.rs/?secondary=AST). ## Contributing Refer to the [contributing guidelines](./CONTRIBUTING.md) to get started and GitHub issues with the [parser label](https://github.com/astral-sh/ruff/issues?q=is:open+is:issue+label:parser) for issues that need help. ## Versioning This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_python_parser). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. [recursive descent parser]: https://en.wikipedia.org/wiki/Recursive_descent_parser ast_serialize-0.13.1/crates/ruff_python_parser/resources/.editorconfig000064400000000000000000000002271046102023000232340ustar00# Check http://editorconfig.org for more information # This is the main config file for this project: root = true [*.py] insert_final_newline = false ann_assign_stmt_invalid_annotation.py000064400000000000000000000000771046102023000322520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errx: *int = 1 x: yield a = 1 x: yield from b = 1 x: y := int = 1 ann_assign_stmt_invalid_target.py000064400000000000000000000002521046102023000313610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err"abc": str = "def" call(): str = "no" *x: int = 1, 2 # Tuple assignment x,: int = 1 x, y: int = 1, 2 (x, y): int = 1, 2 # List assignment [x]: int = 1 [x, y]: int = 1, 2 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_invalid_value.py000064400000000000000000000001011046102023000312570ustar00x: Any = *a and b x: Any = x := 1 x: list = [x, *a | b, *a or b] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_missing_rhs.py000064400000000000000000000000111046102023000307620ustar00x: int = ann_assign_stmt_type_alias_annotation.py000064400000000000000000000000451046102023000327510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/erra: type X = int lambda: type X = int args_unparenthesized_generator.py000064400000000000000000000001341046102023000314070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errsum(x for x in range(10), 5) total(1, 2, x for x in range(5), 6) sum(x for x in range(10),) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assert_empty_msg.py000064400000000000000000000000121046102023000265540ustar00assert x, ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assert_empty_test.py000064400000000000000000000000071046102023000267510ustar00assert ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assert_invalid_msg_expr.py000064400000000000000000000001231046102023000301050ustar00assert False, *x assert False, assert x assert False, yield x assert False, x := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assert_invalid_test_expr.py000064400000000000000000000000671046102023000303050ustar00assert *x assert assert x assert yield x assert x := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_target.py000064400000000000000000000000721046102023000306040ustar001 = 1 x = 1 = 2 x = 1 = y = 2 = z ["a", "b"] = ["a", "b"] assign_stmt_invalid_value_expr.py000064400000000000000000000001321046102023000314060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errx = (*a and b,) x = (42, *yield x) x = (42, *yield from x) x = (*lambda x: x,) x = x := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assign_stmt_keyword_target.py000064400000000000000000000000521046102023000306400ustar00a = pass = c a + b a = b = pass = c a + b ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/assign_stmt_missing_rhs.py000064400000000000000000000000461046102023000301360ustar00x = 1 + 1 x = y = 2 + 2 x = = y 3 + 3 assign_stmt_starred_expr_value.py000064400000000000000000000000551046102023000314300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err_ = *[42] _ = *{42} _ = *list() _ = *(p + q) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/async_unexpected_token.py000064400000000000000000000001641046102023000277400ustar00async class Foo: ... async while test: ... async x = 1 async async def foo(): ... async match test: case _: ... aug_assign_stmt_invalid_target.py000064400000000000000000000000731046102023000313620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err1 += 1 "a" += "b" *x += 1 pass += 1 x += pass (x + y) += 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/aug_assign_stmt_invalid_value.py000064400000000000000000000001151046102023000312640ustar00x += *a and b x += *yield x x += *yield from x x += *lambda x: x x += y := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/aug_assign_stmt_missing_rhs.py000064400000000000000000000000331046102023000307660ustar00x += 1 + 1 x += y += 2 + 2 backslash_continuation_indentation_error.py000064400000000000000000000000351046102023000334470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errif True: 1 \ 2 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/case_expect_indented_block.py000064400000000000000000000000531046102023000305030ustar00match subject: case 1: case 2: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/class_def_empty_body.py000064400000000000000000000000371046102023000273540ustar00class Foo: class Foo(): x = 42 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/class_def_missing_name.py000064400000000000000000000000651046102023000276530ustar00class : ... class (): ... class (metaclass=ABC): ... class_def_unclosed_type_param_list.py000064400000000000000000000000511046102023000322060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errclass Foo[T1, *T2(a, b): pass x = 10 class_def_unparenthesized_generator_argument.py000064400000000000000000000000471046102023000343030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errclass Foo(base for base in bases): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/class_type_params_py311.py000064400000000000000000000001611046102023000276420ustar00# parse_options: {"target-version": "3.11"} class Foo[S: (str, bytes), T: float, *Ts, **P]: ... class Foo[]: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/clause_expect_indented_block.py000064400000000000000000000002531046102023000310460ustar00# Here, the error is highlighted at the `pass` token if True: pass # The parser is at the end of the program, so let's highlight # at the newline token after `:` if True: clause_expect_single_statement.py000064400000000000000000000000271046102023000313670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errif True: if True: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/comma_separated_missing_comma.py000064400000000000000000000000171046102023000312250ustar00call(**x := 1) comma_separated_missing_comma_between_elements.py000064400000000000000000000001341046102023000345530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# The comma between the first two elements is expected in `parse_list_expression`. [0, 1 2] comma_separated_missing_element_between_commas.py000064400000000000000000000000141046102023000345500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err[0, 1, , 2] comma_separated_missing_first_element.py000064400000000000000000000000121046102023000327050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errcall(= 1) comprehension_missing_for_after_async.py000064400000000000000000000000341046102023000327420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err(async) (x async x in iter) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_class.py000064400000000000000000000001221046102023000270110ustar00class __debug__: ... # class name class C[__debug__]: ... # type parameter name ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_function.py000064400000000000000000000002521046102023000275350ustar00def __debug__(): ... # function name def f[__debug__](): ... # type parameter name def f(__debug__): ... # parameter name lambda __debug__: 0 # lambda parameter name ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_import.py000064400000000000000000000001441046102023000272220ustar00import __debug__ import debug as __debug__ from x import __debug__ from x import debug as __debug__ ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_match.py000064400000000000000000000000411046102023000270000ustar00match x: case __debug__: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_try.py000064400000000000000000000000541046102023000265260ustar00try: ... except Exception as __debug__: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_type_alias.py000064400000000000000000000001371046102023000300440ustar00type __debug__ = list[int] # visited as an Expr but still flagged type Debug[__debug__] = str ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/debug_shadow_with.py000064400000000000000000000000471046102023000266650ustar00with open("foo.txt") as __debug__: ... decorator_await_expression_py38.py000064400000000000000000000001401046102023000314230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: { "target-version": "3.8" } async def foo(): @await bar def baz(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_dict_literal_py38.py000064400000000000000000000001041046102023000305550ustar00# parse_options: { "target-version": "3.8" } @{3: 3} def bar(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_expression_py38.py000064400000000000000000000001311046102023000303150ustar00# parse_options: { "target-version": "3.8" } @buttons[0].clicked.connect def spam(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_float_literal_py38.py000064400000000000000000000001021046102023000307350ustar00# parse_options: { "target-version": "3.8" } @3.14 def bar(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_invalid_expression.py000064400000000000000000000000701046102023000311420ustar00@*x @(*x) @((*x)) @yield x @yield from x def foo(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_missing_expression.py000064400000000000000000000001061046102023000311650ustar00@def foo(): ... @ def foo(): ... @@ def foo(): ... @test @ class Test ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_missing_newline.py000064400000000000000000000000741046102023000304330ustar00@x def foo(): ... @x async def foo(): ... @x class Foo: ... decorator_named_expression_py37.py000064400000000000000000000001251046102023000314040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: { "target-version": "3.7" } @(x := lambda x: x)(foo) def bar(): ... decorator_non_toplevel_call_expression_py38.py000064400000000000000000000001111046102023000340130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: { "target-version": "3.8" } @foo().bar() def baz(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/decorator_unexpected_token.py000064400000000000000000000000421046102023000306000ustar00@foo async with x: ... @foo x = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/del_debug_py39.py000064400000000000000000000000711046102023000257720ustar00# parse_options: {"target-version": "3.9"} del __debug__ ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/del_incomplete_target.py000064400000000000000000000000301046102023000275200ustar00del x, y. z del x, y[ z ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/del_stmt_empty.py000064400000000000000000000000041046102023000262210ustar00del different_match_pattern_bindings.py000064400000000000000000000005331046102023000316540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch x: case [a] | [b]: ... case [a] | []: ... case (x, y) | (x,): ... case [a, _] | [a, b]: ... case (x, (y | z)): ... case [a] | [b] | [c]: ... case [] | [a]: ... case [a] | [C(x)]: ... case [[a] | [b]]: ... case [C(a)] | [C(b)]: ... case [C(D(a))] | [C(D(b))]: ... case [(a, b)] | [(c, d)]: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/dotted_name_multiple_dots.py000064400000000000000000000000311046102023000304170ustar00import a..b import a...b ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/duplicate_match_class_attr.py000064400000000000000000000003471046102023000305470ustar00match x: case Class(x=1, x=2): ... case [Class(x=1, x=2)]: ... case {"x": x, "y": Foo(x=1, x=2)}: ... case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/duplicate_match_key.py000064400000000000000000000013621046102023000271760ustar00match x: case {"x": 1, "x": 2}: ... case {b"x": 1, b"x": 2}: ... case {0: 1, 0: 2}: ... case {1.0: 1, 1.0: 2}: ... case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... case {True: 1, True: 2}: ... case {None: 1, None: 2}: ... case {0: 1, False: 2}: ... case {1.0: 1, True: 2}: ... case {-0: 1, False: 2}: ... case {1 + 0j: 1, True: 2}: ... case { """x y z """: 1, """x y z """: 2}: ... case {"x": 1, "x": 2, "x": 3}: ... case {0: 1, "x": 1, 0: 2, "x": 2}: ... case [{"x": 1, "x": 2}]: ... case Foo(x=1, y={"x": 1, "x": 2}): ... case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... case {2: 1, 2.0: 2}: ... case {9007199254740993: 1, 9007199254740993 + 0j: 2}: ... duplicate_type_parameter_names.py000064400000000000000000000004051046102023000313540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype Alias[T, T] = ... def f[T, T](t: T): ... class C[T, T]: ... type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... def f[T, T, T](): ... # two errors def f[T, *T](): ... # star is still duplicate def f[T, **T](): ... # as is double star ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/except_star_py310.py000064400000000000000000000001761046102023000264570ustar00# parse_options: {"target-version": "3.10"} try: ... except* ValueError: ... except* KeyError: ... except * Error: ... except_stmt_invalid_expression.py000064400000000000000000000001121046102023000314350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtry: pass except yield x: pass try: pass except* *x: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/except_stmt_missing_as_name.py000064400000000000000000000001111046102023000307420ustar00try: pass except Exception as: pass except Exception as pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/except_stmt_missing_exception.py000064400000000000000000000002461046102023000313460ustar00try: pass except as exc: pass # If a '*' is present then exception type is required try: pass except*: pass except* pass except* as exc: pass except_stmt_missing_exception_and_as_name.py000064400000000000000000000000421046102023000335660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtry: pass except as: pass except_stmt_unparenthesized_tuple_as.py000064400000000000000000000001261046102023000326410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtry: pass except x, y as exc: pass try: pass except* x, y as eg: pass except_stmt_unparenthesized_tuple_no_as_py313.py000064400000000000000000000001651046102023000342770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.13"} try: pass except x, y: pass try: pass except* x, y: pass f_string_conversion_follows_exclamation.py000064400000000000000000000000361046102023000333270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"{x! s}" t"{x! s}" f"{x! z}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/f_string_empty_expression.py000064400000000000000000000000161046102023000305030ustar00f"{}" f"{ }" f_string_invalid_conversion_flag_name_tok.py000064400000000000000000000000111046102023000335430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"{x!z}" f_string_invalid_conversion_flag_other_tok.py000064400000000000000000000000261046102023000337520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"{x!123}" f"{x!'a'}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/f_string_invalid_starred_expr.py000064400000000000000000000001601046102023000312760ustar00# Starred expression inside f-string has a minimum precedence of bitwise or. f"{*}" f"{*x and y}" f"{*yield x}" f_string_lambda_without_parentheses.py000064400000000000000000000000211046102023000324070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"{lambda x: x}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/f_string_unclosed_lbrace.py000064400000000000000000000000461046102023000302150ustar00f"{" f"{foo!r" f"{foo=" f"{" f"""{""" f_string_unclosed_lbrace_in_format_spec.py000064400000000000000000000000351046102023000332040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"hello {x:" f"hello {x:.3f" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_iter_unpack_py38.py000064400000000000000000000001521046102023000272310ustar00# parse_options: {"target-version": "3.8"} for x in *a, b: ... for x in a, *b: ... for x in *a, *b: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_iter_expr.py000064400000000000000000000001071046102023000306200ustar00for x in *a and b: ... for x in yield a: ... for target in x := 1: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_target.py000064400000000000000000000002321046102023000301040ustar00for 1 in x: ... for "a" in x: ... for *x and y in z: ... for *x | y in z: ... for await x in z: ... for yield x in y: ... for [x, 1, y, *["a"]] in z: ... for_stmt_invalid_target_binary_expr.py000064400000000000000000000001741046102023000324340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errfor x not in y in z: ... for x == y in z: ... for x or y in z: ... for -x in y: ... for not x in y: ... for x | y in z: ... for_stmt_invalid_target_in_keyword.py000064400000000000000000000002521046102023000322610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errfor d(x in y) in target: ... for (x in y)() in iter: ... for (x in y) in iter: ... for (x in y, z) in iter: ... for [x in y, z] in iter: ... for {x in y, z} in iter: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_stmt_missing_in_keyword.py000064400000000000000000000000301046102023000310070ustar00for a b: ... for a: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_stmt_missing_iter.py000064400000000000000000000000241046102023000276030ustar00for x in: a = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/for_stmt_missing_target.py000064400000000000000000000000161046102023000301270ustar00for in x: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/from_import_dotted_names.py000064400000000000000000000001031046102023000302530ustar00from x import a. from x import a.b from x import a, b.c, d, e.f, g ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/from_import_empty_names.py000064400000000000000000000000601046102023000301300ustar00from x import from x import () from x import ,, ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/from_import_missing_module.py000064400000000000000000000000231046102023000306240ustar00from from import x ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/from_import_missing_rpar.py000064400000000000000000000000651046102023000303110ustar00from x import (a, b 1 + 1 from x import (a, b, 2 + 2 from_import_parenthesized_star.py000064400000000000000000000000221046102023000314240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errfrom x import (*) from_import_star_with_other_names.py000064400000000000000000000001271046102023000321240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errfrom x import *, a from x import a, *, b from x import *, a as b from x import *, *, a from_import_unparenthesized_trailing_comma.py000064400000000000000000000000731046102023000340110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errfrom a import b, from a import b as c, from a import b, c, ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/function_def_empty_body.py000064400000000000000000000000441046102023000300720ustar00def foo(): def foo() -> int: x = 42 function_def_invalid_return_expr.py000064400000000000000000000001121046102023000317170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo() -> *int: ... def foo() -> (*int): ... def foo() -> yield x: ... function_def_missing_identifier.py000064400000000000000000000000371046102023000315150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef (): ... def () -> int: ... function_def_missing_return_type.py000064400000000000000000000000231046102023000317460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo() -> : ... function_def_unclosed_parameter_list.py000064400000000000000000000001121046102023000325430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a: int, b: def foo(): return 42 def foo(a: int, b: str x = 10 function_def_unclosed_type_param_list.py000064400000000000000000000000571046102023000327340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo[T1, *T2(a, b): return a + b x = 10 function_def_unparenthesized_return_types.py000064400000000000000000000000621046102023000336730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo() -> int,: ... def foo() -> int, str: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/function_type_params_py311.py000064400000000000000000000001171046102023000303630ustar00# parse_options: {"target-version": "3.11"} def foo[T](): ... def foo[](): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/global_stmt_empty.py000064400000000000000000000000071046102023000267200ustar00global ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/global_stmt_expression.py000064400000000000000000000000151046102023000277600ustar00global x + 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/global_stmt_trailing_comma.py000064400000000000000000000000401046102023000305440ustar00global , global x, global x, y, ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_elif_missing_colon.py000064400000000000000000000000561046102023000305660ustar00if x: pass elif y pass else: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_empty_body.py000064400000000000000000000000171046102023000270740ustar00if True: 1 + 1 if_stmt_invalid_elif_test_expr.py000064400000000000000000000000701046102023000313630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errif x: pass elif *x: pass elif yield x: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_invalid_test_expr.py000064400000000000000000000000601046102023000304420ustar00if *x: ... if yield x: ... if yield from x: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_missing_colon.py000064400000000000000000000000311046102023000275600ustar00if x if x pass a = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_missing_test.py000064400000000000000000000000111046102023000274230ustar00if : ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/if_stmt_misspelled_elif.py000064400000000000000000000000571046102023000300650ustar00if True: pass elf: pass else: pass implicitly_concatenated_unterminated_string.py000064400000000000000000000000571046102023000341550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err'hello' 'world 1 + 1 'hello' f'world {x} 2 + 2 implicitly_concatenated_unterminated_string_multiline.py000064400000000000000000000001251046102023000362330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err( 'hello' f'world {x} ) 1 + 1 ( 'first' 'second f'third' ) 2 + 2 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/import_alias_missing_asname.py000064400000000000000000000000141046102023000307310ustar00import x as ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/import_from_star.py000064400000000000000000000002201046102023000265560ustar00def f1(): from module import * class C: from module import * def f2(): from ..module import * def f3(): from module import *, * ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/import_stmt_empty.py000064400000000000000000000000071046102023000267720ustar00import import_stmt_parenthesized_names.py000064400000000000000000000000311046102023000316020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errimport (a) import (a, b) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/import_stmt_star_import.py000064400000000000000000000000301046102023000301730ustar00import * import x, *, y ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/import_stmt_trailing_comma.py000064400000000000000000000000261046102023000306220ustar00import , import x, y, incomplete_attribute_before_for_in_delimiter.py000064400000000000000000000002161046102023000342540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err[item. for item in xs] [item. async for item in xs] {item. for item in xs} (item. for item in xs) [item for item. in xs] for item. in xs: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py000064400000000000000000000003671046102023000302510ustar00class F[T](y := list): ... class I[T]((yield 1)): ... class J[T]((yield from 1)): ... class K[T: (yield 1)]: ... # yield in TypeVar class L[T: (x := 1)]: ... # named expr in TypeVar class M[T]((await 1)): ... class N[T: (await 1)]: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py000064400000000000000000000017331046102023000307670ustar00def d[T]() -> (await 1): ... def e[T](arg: (await 1)): ... def f[T]() -> (y := 3): ... def g[T](arg: (x := 1)): ... def h[T](x: (yield 1)): ... def j[T]() -> (yield 1): ... def l[T](x: (yield from 1)): ... def n[T]() -> (yield from 1): ... def p[T: (yield 1)](): ... # yield in TypeVar bound def q[T = (yield 1)](): ... # yield in TypeVar default def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default def s[**Ts = (yield 1)](): ... # yield in ParamSpec default def t[T: (x := 1)](): ... # named expr in TypeVar bound def u[T = (x := 1)](): ... # named expr in TypeVar default def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default def t[T: (await 1)](): ... # await in TypeVar bound def u[T = (await 1)](): ... # await in TypeVar default def v[*Ts = (await 1)](): ... # await in TypeVarTuple default def w[**Ts = (await 1)](): ... # await in ParamSpec default invalid_annotation_function_py314.py000064400000000000000000000004741046102023000316510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} def f() -> (y := 3): ... def g(arg: (x := 1)): ... def outer(): def i(x: (yield 1)): ... def k() -> (yield 1): ... def m(x: (yield from 1)): ... def o() -> (yield from 1): ... async def outer(): def f() -> (await 1): ... def g(arg: (await 1)): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_annotation_py314.py000064400000000000000000000002201046102023000300100ustar00# parse_options: {"target-version": "3.14"} a: (x := 1) def outer(): b: (yield 1) c: (yield from 1) async def outer(): d: (await 1) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_annotation_type_alias.py000064400000000000000000000006261046102023000312740ustar00type X[T: (yield 1)] = int # TypeVar bound type X[T = (yield 1)] = int # TypeVar default type X[*Ts = (yield 1)] = int # TypeVarTuple default type X[**Ts = (yield 1)] = int # ParamSpec default type Y = (yield 1) # yield in value type Y = (x := 1) # named expr in value type Y[T: (await 1)] = int # await in bound type Y = (await 1) # await in value ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_byte_literal.py000064400000000000000000000000541046102023000273620ustar00b'123a𝐁c' rb"a𝐁c123" b"""123a𝐁c""" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_del_target.py000064400000000000000000000001131046102023000270110ustar00del x + 1 del {'x': 1} del {'x', 'y'} del None, True, False, 1, 1.0, "abc" invalid_fstring_literal_element.py000064400000000000000000000000721046102023000315250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf'hello \N{INVALID} world' f"""hello \N{INVALID} world""" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_future_feature.py000064400000000000000000000002271046102023000277320ustar00from __future__ import invalid_feature from __future__ import annotations, invalid_feature from __future__ import invalid_feature_1, invalid_feature_2 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_match_pattern_target.py000064400000000000000000000001001046102023000310720ustar00match value: case 1 as _: ... case {**_}: ... after = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/invalid_string_literal.py000064400000000000000000000000701046102023000277230ustar00'hello \N{INVALID} world' """hello \N{INVALID} world""" ipython_help_escape_command_error_recovery_1.py000064400000000000000000000000641046102023000342060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"mode": "ipython"} with (a, ?b) ? ipython_help_escape_command_error_recovery_2.py000064400000000000000000000000631046102023000342060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"mode": "ipython"} with (a, ?b ? ipython_help_escape_command_error_recovery_3.py000064400000000000000000000000701046102023000342050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"mode": "ipython"} with a, ?b ? x = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/irrefutable_case_pattern.py000064400000000000000000000004751046102023000302400ustar00match x: case var: ... # capture pattern case 2: ... match x: case _: ... case 2: ... # wildcard pattern match x: case var1 as var2: ... # as pattern with irrefutable left-hand side case 2: ... match x: case enum.variant | var: ... # or pattern with irrefutable part case 2: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/iter_unpack_return_py37.py000064400000000000000000000001331046102023000277600ustar00# parse_options: {"target-version": "3.7"} rest = (4, 5, 6) def f(): return 1, 2, 3, *rest ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/iter_unpack_yield_py37.py000064400000000000000000000002001046102023000275420ustar00# parse_options: {"target-version": "3.7"} rest = (4, 5, 6) def g(): yield 1, 2, 3, *rest def h(): yield 1, (yield 2, *rest), 3 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/lambda_body_with_starred_expr.py000064400000000000000000000000761046102023000312530ustar00lambda x: *y lambda x: *y, lambda x: *y, z lambda x: *y and z ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/lambda_body_with_yield_expr.py000064400000000000000000000000511046102023000307060ustar00lambda x: yield y lambda x: yield from y lazy_import_invalid_context_py315.py000064400000000000000000000005021046102023000317000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.15"} try: lazy import os except: pass try: x except* Exception: lazy import sys def func(): lazy import math async def async_func(): lazy from json import loads class MyClass: lazy import typing def outer(): class Inner: lazy import json lazy_import_invalid_from_py315.py000064400000000000000000000002221046102023000311560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.15"} lazy from os import * lazy from __future__ import annotations def func(): lazy from sys import * ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/lazy_import_stmt_py314.py000064400000000000000000000001251046102023000275540ustar00# parse_options: {"target-version": "3.14"} lazy import foo lazy from bar import baz ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_before_py310.py000064400000000000000000000001171046102023000265470ustar00# parse_options: { "target-version": "3.9" } match 2: case 1: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_classify_as_keyword.py000064400000000000000000000000411046102023000304110ustar00match yield foo: case _: ... match_classify_as_keyword_or_identifier.py000064400000000000000000000000471046102023000332420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch *foo: # Keyword case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_expected_colon.py000064400000000000000000000000351046102023000273430ustar00match [1, 2] case _: ... match_stmt_expect_indented_block.py000064400000000000000000000000271046102023000316550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch foo: case _: ... match_stmt_expected_case_block.py000064400000000000000000000000751046102023000313120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch x: x = 1 match x: match y: case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_stmt_invalid_guard_expr.py000064400000000000000000000001441046102023000312660ustar00match x: case y if *a: ... match x: case y if (*a): ... match x: case y if yield x: ... match_stmt_invalid_subject_expr.py000064400000000000000000000002031046102023000315400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch (*x): case _: ... # Starred expression precedence test match *x and y, z: case _: ... match yield x: case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_stmt_missing_guard_expr.py000064400000000000000000000000341046102023000313070ustar00match x: case y if: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/match_stmt_missing_pattern.py000064400000000000000000000000301046102023000306200ustar00match x: case : ... match_stmt_no_newline_before_case.py000064400000000000000000000000271046102023000320130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch foo: case _: ... match_stmt_single_starred_subject.py000064400000000000000000000000341046102023000320630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch *foo: case _: ... mixed_bytes_and_non_bytes_literals.py000064400000000000000000000001001046102023000322230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err'first' b'second' f'first' b'second' 'first' f'second' b'third' multiple_assignment_in_case_pattern.py000064400000000000000000000007101046102023000324160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch 2: case [y, z, y]: ... # MatchSequence case [y, z, *y]: ... # MatchSequence case [y, y, y]: ... # MatchSequence multiple case {1: x, 2: x}: ... # MatchMapping duplicate pattern case {1: x, **x}: ... # MatchMapping duplicate in **rest case Class(x, x): ... # MatchClass positional case Class(y=x, z=x): ... # MatchClass keyword case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr case x as x: ... # MatchAs ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/multiple_clauses_on_same_line.py000064400000000000000000000004021046102023000312540ustar00if True: pass elif False: pass else: pass if True: pass; elif False: pass; else: pass for x in iter: break else: pass for x in iter: break; else: pass try: pass except exc: pass else: pass finally: pass try: pass; except exc: pass; else: pass; finally: pass multiple_starred_assignment_target.py000064400000000000000000000001601046102023000322710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err(*a, *b) = (1, 2) [*a, *b] = (1, 2) (*a, *b, c) = (1, 2, 3) [*a, *b, c] = (1, 2, 3) (*a, *b, (*c, *d)) = (1, 2) multiple_starred_names_in_sequence_pattern.py000064400000000000000000000000651046102023000337750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errmatch subject: case *first, *second, *third: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/named_expr_slice.py000064400000000000000000000001671046102023000265030ustar00# even after 3.9, an unparenthesized named expression is not allowed in a slice lst[x:=1:-1] lst[1:x:=1] lst[1:3:x:=1] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/named_expr_slice_parse_error.py000064400000000000000000000002021046102023000310740ustar00# parse_options: {"target-version": "3.8"} # before 3.9, only emit the parse error, not the unsupported syntax error lst[x:=1:-1] nested_async_comprehension_py310.py000064400000000000000000000007231046102023000314650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.10"} async def f(): return [[x async for x in foo(n)] for n in range(3)] # list async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict async def h(): return [{x async for x in foo(n)} for n in range(3)] # set async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)] nested_quote_in_format_spec_py312.py000064400000000000000000000001361046102023000316240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.12"} f"{1:""}" # this is a ParseError on all versions ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/node_range_with_gaps.py000064400000000000000000000000511046102023000273400ustar00def foo # comment def bar(): ... def baz nonlocal_declaration_at_module_level.py000064400000000000000000000000311046102023000325030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errnonlocal x nonlocal x, y ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_empty.py000064400000000000000000000000261046102023000272660ustar00def _(): nonlocal ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_expression.py000064400000000000000000000000341046102023000303260ustar00def _(): nonlocal x + 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_trailing_comma.py000064400000000000000000000000731046102023000311170ustar00def _(): nonlocal , nonlocal x, nonlocal x, y, ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/param_missing_annotation.py000064400000000000000000000000431046102023000302560ustar00def foo(x:): ... def foo(x:,): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/param_missing_default.py000064400000000000000000000000511046102023000275270ustar00def foo(x=): ... def foo(x: int = ): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/param_with_invalid_annotation.py000064400000000000000000000001211046102023000312630ustar00def foo(arg: *int): ... def foo(arg: yield int): ... def foo(arg: x := int): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/param_with_invalid_default.py000064400000000000000000000001041046102023000305360ustar00def foo(x=*int): ... def foo(x=(*int)): ... def foo(x=yield y): ... param_with_invalid_star_annotation.py000064400000000000000000000002261046102023000322430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(*args: *): ... def foo(*args: (*tuple[int])): ... def foo(*args: *int or str): ... def foo(*args: *yield x): ... # def foo(*args: **int): ... param_with_star_annotation_py310.py000064400000000000000000000001051046102023000314650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.10"} def foo(*args: *Ts): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/params_duplicate_names.py000064400000000000000000000000521046102023000276730ustar00def foo(a, a=10, *a, a, a: str, **a): ... params_expected_after_star_separator.py000064400000000000000000000001421046102023000325520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(*): ... def foo(*,): ... def foo(a, *): ... def foo(a, *,): ... def foo(*, **kwargs): ... params_follows_var_keyword_param.py000064400000000000000000000000551046102023000317430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(**kwargs, a, /, b=10, *, *args): ... params_kwarg_after_star_separator.py000064400000000000000000000000321046102023000320620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(*, **kwargs): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/params_multiple_kwargs.py000064400000000000000000000000461046102023000277520ustar00def foo(a, **kwargs1, **kwargs2): ... params_multiple_slash_separator.py000064400000000000000000000000651046102023000315700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a, /, /, b): ... def foo(a, /, b, c, /): ... params_multiple_star_separator.py000064400000000000000000000000651046102023000314270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a, *, *, b): ... def foo(a, *, b, c, *): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/params_multiple_varargs.py000064400000000000000000000002101046102023000301120ustar00def foo(a, *, *args, b): ... # def foo(a, *, b, c, *args): ... def foo(a, *args1, *args2, b): ... def foo(a, *args1, b, c, *args2): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/params_no_arg_before_slash.py000064400000000000000000000000431046102023000305170ustar00def foo(/): ... def foo(/, a): ... params_non_default_after_default.py000064400000000000000000000000361046102023000316440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a=10, b, c: int): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/params_star_after_slash.py000064400000000000000000000001511046102023000300620ustar00def foo(*a, /): ... def foo(a, *args, b, /): ... def foo(a, *, /, b): ... def foo(a, *, b, c, /, d): ... params_star_separator_after_star_param.py000064400000000000000000000000751046102023000331070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a, *args, *, b): ... def foo(a, *args, b, c, *): ... params_var_keyword_with_default.py000064400000000000000000000000531046102023000315530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a, **kwargs={'b': 1, 'c': 2}): ... params_var_positional_with_default.py000064400000000000000000000000361046102023000322510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errdef foo(a, *args=(1, 2)): ... parenthesized_context_manager_py38.py000064400000000000000000000001761046102023000321110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.8"} with (foo as x, bar as y): ... with (foo, bar as y): ... with (foo as x, bar): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/parenthesized_kwarg_py38.py000064400000000000000000000001151046102023000301160ustar00# parse_options: {"target-version": "3.8"} f((a)=1) f((a) = 1) f( ( a ) = 1) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/pep701_f_string_py311.py000064400000000000000000000010621046102023000270410ustar00# parse_options: {"target-version": "3.11"} f'Magic wand: { bag['wand'] }' # nested quotes f"{'\n'.join(a)}" # escape sequence f'''A complex trick: { bag['bag'] # comment }''' f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes f"{ 1 }" f"test {a \ } more" # line continuation f"""{f"""{x}"""}""" # mark the whole triple quote f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors pep701_nested_interpolation_py311.py000064400000000000000000000002121046102023000313740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.11"} # nested interpolations also need to be checked f'{1: abcd "{'aa'}" }' f'{1: abcd "{"\n"}" }' pep_798_invalid_dict_unpacking_comprehensions_py315.py000064400000000000000000000002261046102023000351370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.15"} {*k: v for k, v in items} {k: *v for k, v in items} {**k: v for k, v in items} {k: **v for k, v in items} pep_798_unpacking_comprehensions_py314.py000064400000000000000000000001761046102023000324310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} [*x for x in y] {*x for x in y} {**x for x in y} (*x for x in y) f(*x for x in y) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/pos_only_py37.py000064400000000000000000000002101046102023000257130ustar00# parse_options: {"target-version": "3.7"} def foo(a, /): ... def foo(a, /, b, /): ... def foo(a, *args, /, b): ... def foo(a, //): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/raise_stmt_from_without_exc.py000064400000000000000000000000371046102023000310150ustar00raise from exc raise from None ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/raise_stmt_invalid_cause.py000064400000000000000000000000711046102023000302340ustar00raise x from *y raise x from yield y raise x from y := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/raise_stmt_invalid_exc.py000064400000000000000000000000441046102023000277130ustar00raise *x raise yield x raise x := 1 raise_stmt_unparenthesized_tuple_cause.py000064400000000000000000000000421046102023000331460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errraise x from y, raise x from y, z raise_stmt_unparenthesized_tuple_exc.py000064400000000000000000000000461046102023000326310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errraise x, raise x, y raise x, y from z rebound_comprehension_variable.py000064400000000000000000000005261046102023000313560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err[(a := 0) for a in range(0)] {(a := 0) for a in range(0)} {(a := 0): val for a in range(0)} {key: (a := 0) for a in range(0)} ((a := 0) for a in range(0)) [[(a := 0)] for a in range(0)] [(a := 0) for b in range (0) for a in range(0)] [(a := 0) for a in range (0) for b in range(0)] [((a := 0), (b := 1)) for a in range (0) for b in range(0)] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/return_stmt_invalid_expr.py000064400000000000000000000001121046102023000303220ustar00return * return yield x return yield from x return x := 1 return *x and y simple_and_compound_stmt_on_same_line.py000064400000000000000000000000211046102023000327060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/erra; if b: pass; b simple_and_compound_stmt_on_same_line_in_block.py000064400000000000000000000000731046102023000345550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errif True: pass if False: pass if True: pass; if False: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/simple_stmts_on_same_line.py000064400000000000000000000000651046102023000304320ustar00a b a + b c + d break; continue pass; continue break simple_stmts_on_same_line_in_block.py000064400000000000000000000000561046102023000322130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errif True: break; continue pass; continue break ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/single_star_for.py000064400000000000000000000000431046102023000263530ustar00for _ in *x: ... for *x in xs: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/single_star_return.py000064400000000000000000000000231046102023000271020ustar00def f(): return *x ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/single_star_yield.py000064400000000000000000000000221046102023000266700ustar00def f(): yield *x single_starred_assignment_target.py000064400000000000000000000000121046102023000317130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err*a = (1,) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/star_index_py310.py000064400000000000000000000004451046102023000262750ustar00# parse_options: {"target-version": "3.10"} lst[*index] # simple index class Array(Generic[DType, *Shape]): ... # motivating example from the PEP lst[a, *b, c] # different positions lst[a, b, *c] # different positions lst[*a, *b] # multiple unpacks array[3:5, *idxs] # mixed with slices ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/star_slices.py000064400000000000000000000000231046102023000255040ustar00array[*start:*end] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/starred_comprehension_target.py000064400000000000000000000000341046102023000311360ustar00[item for *items in source] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/starred_list_comp_py314.py000064400000000000000000000000741046102023000276540ustar00# parse_options: {"target-version": "3.14"} [*x for x in y] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/starred_starred_expression.py000064400000000000000000000000321046102023000306400ustar00print(* *[]) print(* *[]) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/t_string_empty_expression.py000064400000000000000000000000721046102023000305230ustar00# parse_options: {"target-version": "3.14"} t"{}" t"{ }" t_string_invalid_conversion_flag_name_tok.py000064400000000000000000000000651046102023000335720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} t"{x!z}" t_string_invalid_conversion_flag_other_tok.py000064400000000000000000000001021046102023000337630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} t"{x!123}" t"{x!'a'}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/t_string_invalid_starred_expr.py000064400000000000000000000002341046102023000313160ustar00# parse_options: {"target-version": "3.14"} # Starred expression inside t-string has a minimum precedence of bitwise or. t"{*}" t"{*x and y}" t"{*yield x}" t_string_lambda_without_parentheses.py000064400000000000000000000000751046102023000324360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} t"{lambda x: x}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/t_string_unclosed_lbrace.py000064400000000000000000000001221046102023000302260ustar00# parse_options: {"target-version": "3.14"} t"{" t"{foo!r" t"{foo=" t"{" t"""{""" t_string_unclosed_lbrace_in_format_spec.py000064400000000000000000000001111046102023000332150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.14"} t"hello {x:" t"hello {x:.3f" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/template_strings_py313.py000064400000000000000000000001311046102023000275140ustar00# parse_options: {"target-version": "3.13"} t"{hey}" t'{there}' t"""what's happening?""" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/try_stmt_invalid_order.py000064400000000000000000000000571046102023000277660ustar00try: pass finally: pass else: pass try_stmt_missing_except_finally.py000064400000000000000000000000531046102023000316210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtry: pass try: pass else: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/try_stmt_misspelled_except.py000064400000000000000000000002451046102023000306550ustar00try: pass exept: # spellchecker:disable-line pass finally: pass a = 1 try: pass except: pass exept: # spellchecker:disable-line pass b = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/try_stmt_mixed_except_kind.py000064400000000000000000000003621046102023000306270ustar00try: pass except: pass except* ExceptionGroup: pass try: pass except* ExceptionGroup: pass except: pass try: pass except: pass except: pass except* ExceptionGroup: pass except* ExceptionGroup: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/tuple_context_manager_py38.py000064400000000000000000000004411046102023000304470ustar00# parse_options: {"target-version": "3.8"} # these cases are _syntactically_ valid before Python 3.9 because the `with` item # is parsed as a tuple, but this will always cause a runtime error, so we flag it # anyway with (foo, bar): ... with ( foo, bar, baz, ): ... with (foo,): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_alias_incomplete_stmt.py000064400000000000000000000000251046102023000306130ustar00type type x type x = ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_alias_invalid_value_expr.py000064400000000000000000000001031046102023000312620ustar00type x = *y type x = yield y type x = yield from y type x = x := 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_param_default_py312.py000064400000000000000000000002251046102023000300000ustar00# parse_options: {"target-version": "3.12"} type X[T = int] = int def f[T = int](): ... class C[T = int](): ... class D[S, T = int, U = uint](): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_param_invalid_bound_expr.py000064400000000000000000000001471046102023000312740ustar00type X[T: *int] = int type X[T: yield x] = int type X[T: yield from x] = int type X[T: x := int] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_param_missing_bound.py000064400000000000000000000000511046102023000302530ustar00type X[T: ] = int type X[T1: , T2] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_param_param_spec_bound.py000064400000000000000000000000271046102023000307170ustar00type X[**T: int] = int type_param_param_spec_invalid_default_expr.py000064400000000000000000000002141046102023000337170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[**P = *int] = int type X[**P = yield x] = int type X[**P = yield from x] = int type X[**P = x := int] = int type X[**P = *int] = int type_param_param_spec_missing_default.py000064400000000000000000000000541046102023000327060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[**P =] = int type X[**P =, T2] = int type_param_type_var_invalid_default_expr.py000064400000000000000000000002431046102023000334400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[T = *int] = int type X[T = yield x] = int type X[T = (yield x)] = int type X[T = yield from x] = int type X[T = x := int] = int type X[T: int = *int] = int type_param_type_var_missing_default.py000064400000000000000000000001001046102023000324150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[T =] = int type X[T: int =] = int type X[T1 =, T2] = int type_param_type_var_tuple_bound.py000064400000000000000000000000261046102023000315670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[*T: int] = int type_param_type_var_tuple_invalid_default_expr.py000064400000000000000000000002231046102023000346470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[*Ts = *int] = int type X[*Ts = *int or str] = int type X[*Ts = yield x] = int type X[*Ts = yield from x] = int type X[*Ts = x := int] = int type_param_type_var_tuple_missing_default.py000064400000000000000000000000541046102023000336360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errtype X[*Ts =] = int type X[*Ts =, T2] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_parameter_default_order.py000064400000000000000000000001621046102023000311150ustar00class C[T = int, U]: ... class C[T1, T2 = int, T3, T4]: ... def f[T = int, U](): ... type Alias[T = int, U] = ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_params_empty.py000064400000000000000000000000641046102023000267400ustar00def foo[](): pass type ListOrSet[] = list | set ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py000064400000000000000000000000711046102023000261610ustar00# parse_options: {"target-version": "3.11"} type x = int unparenthesized_named_expr_index_py38.py000064400000000000000000000000651046102023000326040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.8"} lst[x:=1] unparenthesized_named_expr_set_comp_py38.py000064400000000000000000000001111046102023000332760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.8"} {last := x for x in range(3)} unparenthesized_named_expr_set_literal_py38.py000064400000000000000000000001301046102023000337750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# parse_options: {"target-version": "3.8"} {x := 1, 2, 3} {1, x := 2, 3} {1, 2, x := 3} unterminated_fstring_newline_recovery.py000064400000000000000000000001031046102023000330030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errf"hello 1 + 1 f"hello {x 2 + 2 f"hello {x: 3 + 3 f"hello {x} 4 + 4 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/walrus_py37.py000064400000000000000000000000661046102023000253770ustar00# parse_options: { "target-version": "3.7" } (x := 1) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/while_stmt_invalid_test_expr.py000064400000000000000000000001061046102023000311550ustar00while *x: ... while yield x: ... while a, b: ... while a := 1, b: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/while_stmt_missing_colon.py000064400000000000000000000000501046102023000302730ustar00while ( a < 30 # comment ) pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/while_stmt_missing_test.py000064400000000000000000000000361046102023000301440ustar00while : ... while : a = 1 with_items_parenthesized_missing_colon.py000064400000000000000000000000711046102023000331410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err# `)` followed by a newline with (item1, item2) pass with_items_parenthesized_missing_comma.py000064400000000000000000000002401046102023000331210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/errwith (item1 item2): ... with (item1 as f1 item2): ... with (item1, item2 item3, item4): ... with (item1, item2 as f1 item3, item4): ... with (item1, item2: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/write_to_debug_expr.py000064400000000000000000000001231046102023000272320ustar00del __debug__ del x, y, __debug__, z __debug__ = 1 x, y, __debug__, z = 1, 2, 3, 4 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/yield_after_comma.py000064400000000000000000000000241046102023000266350ustar00def f(): 1, yield 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/err/yield_from_in_async_function.py000064400000000000000000000000341046102023000311140ustar00async def f(): yield from x ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/all_async_comprehension_py310.py000064400000000000000000000001761046102023000306550ustar00# parse_options: {"target-version": "3.10"} async def test(): return [[x async for x in elements(n)] async for n in range(3)] ambiguous_lpar_with_items_binary_expr.py000064400000000000000000000005211046102023000326050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# It doesn't matter what's inside the parentheses, these tests need to make sure # all binary expressions parses correctly. with (a) and b: ... with (a) is not b: ... # Make sure precedence works with (a) or b and c: ... with (a) and b or c: ... with (a | b) << c | d: ... # Postfix should still be parsed first with (a)[0] + b * c: ... ambiguous_lpar_with_items_if_expr.py000064400000000000000000000002311046102023000317150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okwith (x) if True else y: ... with (x for x in iter) if True else y: ... with (x async for x in iter) if True else y: ... with (x)[0] if True else y: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/ann_assign_stmt_simple_target.py000064400000000000000000000000551046102023000311250ustar00a: int # simple (a): int a.b: int a[0]: int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/args_unparenthesized_generator.py000064400000000000000000000001531046102023000313100ustar00zip((x for x in range(10)), (y for y in range(10))) sum(x for x in range(10)) sum((x for x in range(10)),) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py000064400000000000000000000000441046102023000313260ustar00_ = 4 _ = [4] _ = (*[1],) _ = *[1], ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/assign_targets_terminator.py000064400000000000000000000000471046102023000303010ustar00x = y = z = 1; a, b x = y = z = 1 a, b ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/async_for_statement.py000064400000000000000000000000361046102023000270650ustar00async for target in iter: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/async_function_definition.py000064400000000000000000000000251046102023000302460ustar00async def foo(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/async_with_statement.py000064400000000000000000000000251046102023000272500ustar00async with item: ... backslash_continuation_indentation.py000064400000000000000000000000561046102023000320620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okif True: \ 1 \ 2 else:\ 3 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/class_def_arguments.py000064400000000000000000000001631046102023000270270ustar00class Foo: ... class Foo(): ... class Foo((base for base in bases)): ... class Foo(*(base for base in bases)): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py000064400000000000000000000000421046102023000311020ustar00match 2: case Class(x=x): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/class_type_params_py312.py000064400000000000000000000001401046102023000274610ustar00# parse_options: {"target-version": "3.12"} class Foo[S: (str, bytes), T: float, *Ts, **P]: ... comma_separated_regular_list_terminator.py000064400000000000000000000002651046102023000331070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# The first element is parsed by `parse_list_like_expression` and the comma after # the first element is expected by `parse_list_expression` [0] [0, 1] [0, 1,] [0, 1, 2] [0, 1, 2,] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/debug_rename_import.py000064400000000000000000000001261046102023000270250ustar00import __debug__ as debug from __debug__ import Some from x import __debug__ as debug ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/decorator_async_function.py000064400000000000000000000000401046102023000300750ustar00@decorator async def foo(): ... decorator_await_expression_py39.py000064400000000000000000000001401046102023000312450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: { "target-version": "3.9" } async def foo(): @await bar def baz(): ... decorator_expression_dotted_ident_py38.py000064400000000000000000000001261046102023000326110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: { "target-version": "3.8" } @buttons.clicked.connect def spam(): ... decorator_expression_eval_hack_py38.py000064400000000000000000000001411046102023000320550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: { "target-version": "3.8" } @eval("buttons[0].clicked.connect") def spam(): ... decorator_expression_identity_hack_py38.py000064400000000000000000000001571046102023000327660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: { "target-version": "3.8" } def _(x): return x @_(buttons[0].clicked.connect) def spam(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/decorator_expression_py39.py000064400000000000000000000002011046102023000301350ustar00# parse_options: { "target-version": "3.9" } @buttons[0].clicked.connect def spam(): ... @(x := lambda x: x)(foo) def bar(): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/del_debug_py38.py000064400000000000000000000000711046102023000256120ustar00# parse_options: {"target-version": "3.8"} del __debug__ ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/del_targets_terminator.py000064400000000000000000000000351046102023000275560ustar00del a, b; c, d del a, b c, d different_match_pattern_bindings.py000064400000000000000000000002231046102023000314710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch x: case [a] | [a]: ... case (x, y) | (x, y): ... case (x, (y | y)): ... case [a, _] | [a, _]: ... case [a] | [C(a)]: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/dotted_name_normalized_spaces.py000064400000000000000000000000401046102023000310560ustar00import a.b.c import a . b . c ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/duplicate_match_key_attr.py000064400000000000000000000000501046102023000300420ustar00match x: case {x.a: 1, x.a: 2}: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/except_star_py311.py000064400000000000000000000001151046102023000262720ustar00# parse_options: {"target-version": "3.11"} try: ... except* ValueError: ... except_stmt_as_name_soft_keyword.py000064400000000000000000000001441046102023000315600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/oktry: ... except Exception as match: ... except Exception as case: ... except Exception as type: ... except_stmt_unparenthesized_tuple_no_as_py314.py000064400000000000000000000001651046102023000341210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.14"} try: pass except x, y: pass try: pass except* x, y: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/for_in_target_valid_expr.py000064400000000000000000000001311046102023000300510ustar00for d[x in y] in target: ... for (x in y)[0] in iter: ... for (x in y).attr in iter: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py38.py000064400000000000000000000001601046102023000270510ustar00# parse_options: {"target-version": "3.8"} for x in (*a, b): ... for x in ( a, *b): ... for x in (*a, *b): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py39.py000064400000000000000000000001521046102023000270530ustar00# parse_options: {"target-version": "3.9"} for x in *a, b: ... for x in a, *b: ... for x in *a, *b: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/from_import_no_space.py000064400000000000000000000000361046102023000272220ustar00from.import x from...import x from_import_soft_keyword_module_name.py000064400000000000000000000001751046102023000324440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okfrom match import pattern from type import bar from case import pattern from lazy import qux from match.type.case import foo ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/from_import_stmt_terminator.py000064400000000000000000000001411046102023000306630ustar00from a import (b, c) from a import (b, c); x, y from a import b, c; x, y from a import b, c x, y ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/fstring_format_spec_terminator.py000064400000000000000000000000531046102023000313170ustar00f"hello {x:} world" f"hello {x:.3f} world" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/function_def_parameter_range.py000064400000000000000000000000701046102023000306730ustar00def foo( first: int, second: int, ) -> int: ... function_def_parenthesized_return_types.py000064400000000000000000000000661046102023000331550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okdef foo() -> (int,): ... def foo() -> (int, str): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/function_def_valid_return_expr.py000064400000000000000000000001411046102023000312720ustar00def foo() -> int | str: ... def foo() -> lambda x: x: ... def foo() -> int if True else str: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/function_type_params_py312.py000064400000000000000000000000761046102023000302110ustar00# parse_options: {"target-version": "3.12"} def foo[T](): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/global_stmt.py000064400000000000000000000000301046102023000253170ustar00global x global x, y, z ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/import_as_name_soft_keyword.py000064400000000000000000000001151046102023000306100ustar00import foo as match import bar as case import baz as type import qux as lazy ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/import_from_star.py000064400000000000000000000000251046102023000264020ustar00from module import * ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/import_stmt_terminator.py000064400000000000000000000000521046102023000276410ustar00import a, b; import c, d import a, b c, d irrefutable_case_pattern_at_end.py000064400000000000000000000002601046102023000313040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch x: case 2: ... case var: ... match x: case 2: ... case _: ... match x: case var if True: ... # don't try to refute a guarded pattern case 2: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/iter_unpack_return_py37.py000064400000000000000000000001351046102023000276030ustar00# parse_options: {"target-version": "3.7"} rest = (4, 5, 6) def f(): return (1, 2, 3, *rest) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/iter_unpack_return_py38.py000064400000000000000000000001331046102023000276020ustar00# parse_options: {"target-version": "3.8"} rest = (4, 5, 6) def f(): return 1, 2, 3, *rest ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/iter_unpack_yield_py37.py000064400000000000000000000001341046102023000273710ustar00# parse_options: {"target-version": "3.7"} rest = (4, 5, 6) def g(): yield (1, 2, 3, *rest) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/iter_unpack_yield_py38.py000064400000000000000000000002001046102023000273640ustar00# parse_options: {"target-version": "3.8"} rest = (4, 5, 6) def g(): yield 1, 2, 3, *rest def h(): yield 1, (yield 2, *rest), 3 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/lambda_with_no_parameters.py000064400000000000000000000000121046102023000302020ustar00lambda: 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/lambda_with_valid_body.py000064400000000000000000000002301046102023000274610ustar00lambda x: x lambda x: x if True else y lambda x: await x lambda x: lambda y: x + y lambda x: (yield x) # Parenthesized `yield` is fine lambda x: x, *y ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/lazy_import_relative_py315.py000064400000000000000000000001741046102023000302260ustar00# parse_options: {"target-version": "3.15"} lazy from . import basic2 lazy from .basic2 import x, f lazy from . import b, x ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/lazy_import_semantic_ok_py315.py000064400000000000000000000002551046102023000307070ustar00# parse_options: {"target-version": "3.15"} import contextlib with contextlib.nullcontext(): lazy import os with contextlib.nullcontext(): lazy from sys import path lazy_import_soft_keyword_split_py315.py000064400000000000000000000001411046102023000322600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.15"} lazy import os lazy # comment from sys import path ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/lazy_import_stmt_py315.py000064400000000000000000000002711046102023000274000ustar00# parse_options: {"target-version": "3.15"} lazy import foo lazy import foo as bar lazy from bar import baz lazy from sys import x as y lazy = 1 import foo as lazy from lazy import qux ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_after_py310.py000064400000000000000000000001201046102023000262210ustar00# parse_options: { "target-version": "3.10" } match 2: case 1: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_annotated_assignment.py000064400000000000000000000000441046102023000303760ustar00match[0]: int match [x, y, z]: dict ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_as_pattern.py000064400000000000000000000000741046102023000263340ustar00match foo: case foo_bar: ... match foo: case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_as_pattern_soft_keyword.py000064400000000000000000000001331046102023000311270ustar00match foo: case case: ... match foo: case match: ... match foo: case type: ... match_attr_pattern_soft_keyword.py000064400000000000000000000002031046102023000314150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch foo: case match.bar: ... case case.bar: ... case type.bar: ... case match.case.type.bar.type.case.match: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_classify_as_identifier_1.py000064400000000000000000000000221046102023000311070ustar00match not in case ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_classify_as_identifier_2.py000064400000000000000000000002251046102023000311150ustar00match match != foo (foo, match) [foo, match] {foo, match} match; match: int match, match.foo match / foo match << foo match and foo match is not foo ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_classify_as_keyword_1.py000064400000000000000000000005461046102023000304640ustar00match foo: case _: ... match 1: case _: ... match 1.0: case _: ... match 1j: case _: ... match "foo": case _: ... match f"foo {x}": case _: ... match {1, 2}: case _: ... match ~foo: case _: ... match ...: case _: ... match not foo: case _: ... match await foo(): case _: ... match lambda foo: foo: case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_classify_as_keyword_2.py000064400000000000000000000002521046102023000304570ustar00match match: case _: ... match case: case _: ... match type: case _: ... match None: case _: ... match True: case _: ... match False: case _: ... match_classify_as_keyword_or_identifier.py000064400000000000000000000003411046102023000330600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch (1, 2) # Identifier match (1, 2): # Keyword case _: ... match [1:] # Identifier match [1, 2]: # Keyword case _: ... match * foo # Identifier match - foo # Identifier match -foo: # Keyword case _: ... match_sequence_pattern_parentheses_terminator.py000064400000000000000000000000711046102023000343240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch subject: case [a, b]: ... case (a, b): ... match_sequence_pattern_terminator.py000064400000000000000000000001371046102023000317260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch subject: case a if x: ... case a, b: ... case a, b if x: ... case a: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_stmt_subject_expr.py000064400000000000000000000002711046102023000277370ustar00match x := 1: case _: ... match (x := 1): case _: ... # Starred expressions are only allowed in tuple expression match *x | y, z: case _: ... match await x: case _: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/match_stmt_valid_guard_expr.py000064400000000000000000000002361046102023000305620ustar00match x: case y if a := 1: ... match x: case y if a if True else b: ... match x: case y if lambda a: b: ... match x: case y if (yield x): ... multiple_assignment_in_case_pattern.py000064400000000000000000000000521046102023000322360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okmatch 2: case Class(x) | [x] | x: ... multiple_starred_assignment_target.py000064400000000000000000000000561046102023000321160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok(*a, b) = (1, 2) (*_, normed), *_ = [(1,), 2] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/nested_alternative_patterns.py000064400000000000000000000004171046102023000306210ustar00match ruff: case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}: ... match 42: case [[x] | [x]] | x: ... match 42: case [[x | x] | [x]] | x: ... match 42: case ast.Subscript(n, ast.Constant() | ast.Slice()) | ast.Attribute(n): ... nested_async_comprehension_py310.py000064400000000000000000000002651046102023000313070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.10"} async def f(): [_ for n in range(3)] [_ async for n in range(3)] async def f(): def g(): ... [_ async for n in range(3)] nested_async_comprehension_py311.py000064400000000000000000000004251046102023000313060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.11"} async def f(): return [[x async for x in foo(n)] for n in range(3)] # list async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict async def h(): return [{x async for x in foo(n)} for n in range(3)] # set non_duplicate_type_parameter_names.py000064400000000000000000000002261046102023000320500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/oktype Alias[T] = list[T] def f[T](t: T): ... class C[T]: ... class C[T, U, V]: ... type Alias[T, U: str, V: (str, bytes), *Ts, **P, D = default] = ... non_nested_quote_in_format_spec_py311.py000064400000000000000000000001321046102023000323120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.11"} f"{1:''}" # but this is okay on all versions non_rebound_comprehension_variable.py000064400000000000000000000000331046102023000320420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok[a := 0 for x in range(0)] nonlocal_declaration_at_module_level.py000064400000000000000000000000301046102023000323230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okdef _(): nonlocal x ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/nonlocal_stmt.py000064400000000000000000000000551046102023000256730ustar00def _(): nonlocal x nonlocal x, y, z ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/param_with_annotation.py000064400000000000000000000000661046102023000274060ustar00def foo(arg: int): ... def foo(arg: lambda x: x): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/param_with_default.py000064400000000000000000000001571046102023000266610ustar00def foo(x=lambda y: y): ... def foo(x=1 if True else 2): ... def foo(x=await y): ... def foo(x=(yield y)): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/param_with_star_annotation.py000064400000000000000000000001031046102023000304270ustar00def foo(*args: *int | str): ... def foo(*args: *(int or str)): ... param_with_star_annotation_py310.py000064400000000000000000000006601046102023000313140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.10"} # regression tests for https://github.com/astral-sh/ruff/issues/16874 # starred parameters are fine, just not the annotation from typing import Annotated, Literal def foo(*args: Ts): ... def foo(*x: Literal["this should allow arbitrary strings"]): ... def foo(*x: Annotated[str, "this should allow arbitrary strings"]): ... def foo(*args: str, **kwds: int): ... def union(*x: A | B): ... param_with_star_annotation_py311.py000064400000000000000000000001051046102023000313070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.11"} def foo(*args: *Ts): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/params_non_default_after_star.py000064400000000000000000000001101046102023000310620ustar00def foo(a=10, *, b, c=11, d): ... def foo(a=10, *args, b, c=11, d): ... params_seen_keyword_only_param_after_star.py000064400000000000000000000000751046102023000334360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okdef foo(*, a, **kwargs): ... def foo(*, a=10, **kwargs): ... parenthesized_context_manager_py39.py000064400000000000000000000001761046102023000317330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.9"} with (foo as x, bar as y): ... with (foo, bar as y): ... with (foo as x, bar): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/parenthesized_kwarg_py37.py000064400000000000000000000000641046102023000277410ustar00# parse_options: {"target-version": "3.7"} f((a)=1) parenthesized_named_expr_index_py38.py000064400000000000000000000000671046102023000320640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.8"} lst[(x:=1)] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/parenthesized_named_expr_py38.py000064400000000000000000000001341046102023000307470ustar00# parse_options: {"target-version": "3.8"} {(x := 1), 2, 3} {(last := x) for x in range(3)} ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/parenthesized_star_index_py310.py000064400000000000000000000001361046102023000310400ustar00# parse_options: {"target-version": "3.10"} out[(*(slice(None) for _ in range(2)), *ind)] = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/pep701_f_string_py311.py000064400000000000000000000006371046102023000266710ustar00# parse_options: {"target-version": "3.11"} f"outer {'# not a comment'}" f'outer {x:{"# not a comment"} }' f"""{f'''{f'{"# not a comment"}'}'''}""" f"""{f'''# before expression {f'# aro{f"#{1+1}#"}und #'}'''} # after expression""" f"""{ 1 }""" f"escape outside of \t {expr}\n" f"test\"abcd" f"{1:\x64}" # escapes are valid in the format spec f"{1:\"d\"}" # this also means that escaped outer quotes are valid ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/pep701_f_string_py312.py000064400000000000000000000006401046102023000266640ustar00# parse_options: {"target-version": "3.12"} f'Magic wand: { bag['wand'] }' # nested quotes f"{'\n'.join(a)}" # escape sequence f'''A complex trick: { bag['bag'] # comment }''' f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes f"{ 1 }" f"test {a \ } more" # line continuation ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/pep750_t_string_py314.py000064400000000000000000000006231046102023000267110ustar00# parse_options: {"target-version": "3.14"} t'Magic wand: { bag['wand'] }' # nested quotes t"{'\n'.join(a)}" # escape sequence t'''A complex trick: { bag['bag'] # comment }''' t"{t"{t"{t"{t"{t"{1+1}"}"}"}"}"}" # arbitrary nesting t"{t'''{"nested"} inner'''} outer" # nested (triple) quotes t"test {a \ } more" # line continuation pep_798_unpacking_comprehensions_py315.py000064400000000000000000000003271046102023000322510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.15"} [*x for x in y] {*x for x in y} {**x for x in y} (*x for x in y) f(*x for x in y) [*x async for x in y] {*x async for x in y} {**x async for x in y} (*x async for x in y) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/pos_only_py38.py000064400000000000000000000000761046102023000255470ustar00# parse_options: {"target-version": "3.8"} def foo(a, /): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/read_from_debug.py000064400000000000000000000000401046102023000261150ustar00if __debug__: ... x = __debug__ ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/simple_stmts_in_block.py000064400000000000000000000001241046102023000273770ustar00if True: pass if True: pass; if True: pass; continue if True: pass; continue; x = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/simple_stmts_with_semicolons.py000064400000000000000000000000631046102023000310270ustar00return; import a; from x import y; z; type T = int single_parenthesized_item_context_manager_py38.py000064400000000000000000000001601046102023000343020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.8"} with ( open('foo.txt')) as foo: ... with ( open('foo.txt')): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/single_star_in_tuple.py000064400000000000000000000001241046102023000272250ustar00def f(): yield (*x,) def f(): return (*x,) for _ in (*x,): ... for (*x,) in xs: ... single_starred_assignment_target.py000064400000000000000000000000441046102023000315410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok(*a,) = (1,) *a, = (1,) [*a] = (1,) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/star_index_py311.py000064400000000000000000000004451046102023000261170ustar00# parse_options: {"target-version": "3.11"} lst[*index] # simple index class Array(Generic[DType, *Shape]): ... # motivating example from the PEP lst[a, *b, c] # different positions lst[a, b, *c] # different positions lst[*a, *b] # multiple unpacks array[3:5, *idxs] # mixed with slices ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/starred_comprehension_target.py000064400000000000000000000000371046102023000307620ustar00[item for (*items,) in source] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/starred_list_comp_py315.py000064400000000000000000000001371046102023000274760ustar00# parse_options: {"target-version": "3.15"} [*x for x in y] [*factor.dims for factor in bases] ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/template_strings_py314.py000064400000000000000000000001311046102023000273360ustar00# parse_options: {"target-version": "3.14"} t"{hey}" t'{there}' t"""what's happening?""" ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/tuple_context_manager_py38.py000064400000000000000000000001251046102023000302670ustar00# parse_options: {"target-version": "3.8"} with ( foo, bar, baz, ) as tup: ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/type_param_default_py313.py000064400000000000000000000001601046102023000276200ustar00# parse_options: {"target-version": "3.13"} type X[T = int] = int def f[T = int](): ... class C[T = int](): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/type_param_param_spec.py000064400000000000000000000001321046102023000273460ustar00type X[**P] = int type X[**P = int] = int type X[T, **P] = int type X[T, **P = int] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/type_param_type_var.py000064400000000000000000000002231046102023000270660ustar00type X[T] = int type X[T = int] = int type X[T: int = int] = int type X[T: (int, int) = int] = int type X[T: int = int, U: (int, int) = int] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/type_param_type_var_tuple.py000064400000000000000000000001631046102023000303020ustar00type X[*Ts] = int type X[*Ts = int] = int type X[*Ts = *int] = int type X[T, *Ts] = int type X[T, *Ts = int] = int ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py000064400000000000000000000000711046102023000260030ustar00# parse_options: {"target-version": "3.12"} type x = int unparenthesized_named_expr_index_py39.py000064400000000000000000000000651046102023000324260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.9"} lst[x:=1] unparenthesized_named_expr_py39.py000064400000000000000000000001301046102023000312300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.9"} {x := 1, 2, 3} {last := x for x in range(3)} ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py000064400000000000000000000002111046102023000275270ustar00class F(y := list): ... def f(): class G((yield 1)): ... class H((yield from 1)): ... async def f(): class G((await 1)): ... valid_annotation_function_py313.py000064400000000000000000000004741046102023000311420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok# parse_options: {"target-version": "3.13"} def f() -> (y := 3): ... def g(arg: (x := 1)): ... def outer(): def i(x: (yield 1)): ... def k() -> (yield 1): ... def m(x: (yield from 1)): ... def o() -> (yield from 1): ... async def outer(): def f() -> (await 1): ... def g(arg: (await 1)): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/valid_annotation_py313.py000064400000000000000000000002201046102023000273010ustar00# parse_options: {"target-version": "3.13"} a: (x := 1) def outer(): b: (yield 1) c: (yield from 1) async def outer(): d: (await 1) ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/valid_future_feature.py000064400000000000000000000000431046102023000272200ustar00from __future__ import annotations ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/ok/walrus_py38.py000064400000000000000000000000661046102023000252210ustar00# parse_options: { "target-version": "3.8" } (x := 1) yield_after_comma_parenthesized.py000064400000000000000000000000261046102023000313260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/inline/okdef f(): 1, (yield 1) double_starred.py000064400000000000000000000000671046102023000320670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(**yield x) call(** *x) call(***x) call(**x := 1) duplicate_keyword_arguments.py000064400000000000000000000000341046102023000346660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentsfoo(a=1, b=2, c=3, b=4, a=5)invalid_expression.py000064400000000000000000000001031046102023000327650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(x + y = 1) call(x := 1 = 1) call(yield x) call(yield from x) invalid_keyword_expression.py000064400000000000000000000001051046102023000345330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(x = yield y) call(x = yield from y) call(x = *y) call(x = (*y)) invalid_order.py000064400000000000000000000001441046102023000317060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(**kwargs, x) call(x=1, y) call(x=1, **kwargs, y) call(**kwargs, *args) call(**kwargs, (*args)) missing_argument.py000064400000000000000000000000121046102023000324320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(x,,y)missing_comma.py000064400000000000000000000000111046102023000317030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall(x y)missing_expression.py000064400000000000000000000000461046102023000330160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/argumentscall( = 1) call(x = ) call(*, y) foo ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/arguments/starred.py000064400000000000000000000001001046102023000306000ustar00call(*data for data in iter) call(*yield x) call(*yield from x) ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_0.py000064400000000000000000000000321046102023000311730ustar00call( def foo(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_1.py000064400000000000000000000000331046102023000311750ustar00call(x def foo(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_2.py000064400000000000000000000000341046102023000311770ustar00call(x, def foo(): passinvalid_member.py000064400000000000000000000000201046102023000320310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/attributex.1 x.1.0 x.[0] multiple_dots.py000064400000000000000000000000561046102023000317510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/attributeextra..dot multiple....dots multiple.....dots ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/attribute/no_member.py000064400000000000000000000002151046102023000311040ustar00# The `second` is a variable on another line and not part of the attribute expression. first. second # No member access after the dot. last.no_expression_0.py000064400000000000000000000001111046102023000312710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/await# No expression after `await`, an expression on another line await x + yno_expression_1.py000064400000000000000000000001251046102023000312770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/await# No expression after `await`, a statement on another line await def foo(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/await/recover.py000064400000000000000000000004341046102023000277130ustar00# The parser parses all of the following expressions but reports an error for # invalid expressions. # Nested await await await x # Starred expressions await *x await (*x) # Invalid expression as per precedence await yield x await lambda x: x await +x await -x await ~x await not xinvalid_rhs_expression.py000064400000000000000000000000341046102023000331050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_opx + lambda y: y x - yield yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_lhs.py000064400000000000000000000000121046102023000307160ustar00/ y 1 + 2ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_rhs_0.py000064400000000000000000000000121046102023000311430ustar000 + 1 + 2ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_rhs_1.py000064400000000000000000000000221046102023000311450ustar001 + 2 - 3 * 4 + 5ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_op/multiple_ops.py000064400000000000000000000000231046102023000311150ustar00x++ 1 + 2 x-- 1 - 2named_expression.py000064400000000000000000000000321046102023000316650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_opx - y := (1, 2) x / y := 2starred_expression.py000064400000000000000000000000161046102023000322470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bin_opx + *y x ** *yinvalid_rhs_expression.py000064400000000000000000000000371046102023000332730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bool_opx and lambda y: y x or yield yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bool_op/missing_lhs.py000064400000000000000000000000051046102023000311030ustar00and yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bool_op/missing_rhs.py000064400000000000000000000000141046102023000311110ustar00x and 1 + 2named_expression.py000064400000000000000000000000301046102023000320460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bool_opx and a := b x or a := bstarred_expression.py000064400000000000000000000000201046102023000324250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/bool_opx and *y x or *yinvalid_order.py000064400000000000000000000002031046102023000313230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex in not y # `=>` instead of `>=` x => y # Same here as well, `not` without `in` is considered to be a unary operator x not is y invalid_rhs_expression.py000064400000000000000000000000421046102023000332640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex not in lambda y: y x == yield yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/compare/missing_lhs.py000064400000000000000000000000121046102023000310760ustar00> y 1 + 2missing_rhs_0.py000064400000000000000000000000121046102023000312440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex > 1 + 2missing_rhs_1.py000064400000000000000000000001071046102023000312520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/compare# Without the `in`, this is considered to be a unary `not` x not 1 + 2missing_rhs_2.py000064400000000000000000000000171046102023000312530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex is not 1 + 2multiple_equals.py000064400000000000000000000000511046102023000317100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/compare# This is not JavaScript x === y x !== y named_expression.py000064400000000000000000000000371046102023000320520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex not in y := (1, 2) x > y := 2starred_expression.py000064400000000000000000000000471046102023000324330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/comparex >= *y x not in *y *x < y *x is not yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict/comprehension.py000064400000000000000000000005521046102023000307360ustar00# Invalid target {x: y for 1 in y} {x: y for 'a' in y} {x: y for call() in y} {x: y for {a, b} in y} # Invalid iter {x: y for x in *y} {x: y for x in yield y} {x: y for x in yield from y} {x: y for x in lambda y: y} # Invalid if {x: y for x in data if *y} {x: y for x in data if yield y} {x: y for x in data if yield from y} {x: y for x in data if lambda y: y}ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict/double_star.py000064400000000000000000000004261046102023000303700ustar00# Double star expression starts with bitwise OR precedence. Make sure we don't parse # the ones which are higher than that. {**x := 1} {a: 1, **x if True else y} {**lambda x: x, b: 2} {a: 1, **x or y} {**x and y, b: 2} {a: 1, **not x, b: 2} {**x in y} {**x not in y} {**x < y} double_star_comprehension.py000064400000000000000000000005461046102023000332450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict# Double star means that the parser will try to parse it as a dictionary expression but # it's actually a comprehension. {**x: y for x, y in data} # TODO(dhruvmanila): This test case fails because there's no way to represent `**y` # in the AST. The parser tries to parse it as a binary expression but the range isn't # correct. # {x: **y for x, y in data} missing_closing_brace_0.py000064400000000000000000000000301046102023000325370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict{x: def foo(): passmissing_closing_brace_1.py000064400000000000000000000000121046102023000325400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict{x: 1 + 2missing_closing_brace_2.py000064400000000000000000000000331046102023000325440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict{x: 1, def foo(): passnamed_expression_0.py000064400000000000000000000001241046102023000315630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict# Unparenthesized named expression not allowed in key {x := 1: y, z := 2: a} x + ynamed_expression_1.py000064400000000000000000000001261046102023000315660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict# Unparenthesized named expression not allowed in value {x: y := 1, z: a := 2} x + yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/dict/recover.py000064400000000000000000000005321046102023000275300ustar00# Test cases for dictionary expressions where the parser recovers from a syntax error. {,} {1: 2,,3: 4} {1: 2,,} # Missing comma {1: 2 3: 4} # No value {1: } # No value for double star unpacking {**} {x: y, **, a: b} # This is not a double star unpacking # {* *data} # Star expression not allowed here {*x: y, z: a, *b: c} {x: *y, z: *a} ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/emoji_identifiers.py000064400000000000000000000001001046102023000306170ustar00a = (🐶 # comment 🐶 ) a = (🐶 + # comment 🐶) ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/emoji_statement.py000064400000000000000000000000051046102023000303220ustar00👍 missing_orelse_expr_0.py000064400000000000000000000001301046102023000317500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/if# Missing orelse expression, followed by a statement x if expr else def foo(): passmissing_orelse_expr_1.py000064400000000000000000000001141046102023000317530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/if# Missing orelse expression, followed by an expression x if expr else 1 + 1missing_test_expr_0.py000064400000000000000000000001141046102023000314400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/if# Missing test expression, followed by a statement x if def foo(): passmissing_test_expr_1.py000064400000000000000000000001001046102023000314340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/if# Missing test expression, followed by an expression x if 1 + 1ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/if/recover.py000064400000000000000000000003271046102023000272050ustar00# Invalid test expression x if *expr else y x if lambda x: x else y x if yield x else y x if yield from x else y # Invalid orelse expression x if expr else *orelse x if expr else yield y x if expr else yield from ylambda_default_parameters.py000064400000000000000000000000241046102023000322240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressionslambda a, b=20, c: 1lambda_duplicate_parameters.py000064400000000000000000000001331046102023000325530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressionslambda a, a: 1 lambda a, *, a: 1 lambda a, a=20: 1 lambda a, *a: 1 lambda a, *, **a: 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list/comprehension.py000064400000000000000000000006741046102023000307730ustar00# Invalid target [x for 1 in y] [x for 'a' in y] [x for call() in y] [x for {a, b} in y] # Invalid iter [x for x in *y] [x for x in yield y] [x for x in yield from y] [x for x in lambda y: y] [**x for x in [{1: 2}]] [*x, for x in y] [*x, *y for x in y] # Invalid if [x for x in data if *y] [x for x in data if yield y] [x for x in data if yield from y] [x for x in data if lambda y: y] [*x if x else y for x in z] [x if x else *y for x in z] missing_closing_bracket_0.py000064400000000000000000000000531046102023000331330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list# Missing closing bracket 0: No elements [missing_closing_bracket_1.py000064400000000000000000000002051046102023000331330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list# Missing closing bracket 1: No elements on the same line, the one on the next line # is considered to be part of the list. [ x + ymissing_closing_bracket_2.py000064400000000000000000000002151046102023000331350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list# Missing closing bracket 2: One element on the line, the other one on the next line # will be considered to be part of the list. [1, x + ymissing_closing_bracket_3.py000064400000000000000000000002141046102023000331350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list# Missing closing bracket 3: Multiple elements without a trailing comma and the next # token starts a statement. [1, 2 def foo(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list/recover.py000064400000000000000000000003201046102023000275530ustar00# Test cases for list expressions where the parser recovers from a syntax error. [,] [1,,2] [1,,] # Missing comma [1 2] # Dictionary element in a list [1: 2] # Missing expression [1, x + ] [1; 2] [*] star_expression_precedence.py000064400000000000000000000003101046102023000334330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/list# For list expression, the minimum binding power of star expression is bitwise or. [(*x), y] [*x in y, z] [*not x, z] [*x and y, z] [*x or y, z] [*x if True else y, z] [*lambda x: x, z] [*x := 2, z] ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named/invalid_target.py000064400000000000000000000001551046102023000312210ustar00# Assignment expression target can only be an identifier (x.y := 1) (x[y] := 1) (*x := 1) ([x, y] := [1, 2])missing_expression_0.py000064400000000000000000000001131046102023000323070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named# There are no parentheses, so this isn't parsed as named expression. x :=missing_expression_1.py000064400000000000000000000000411046102023000323100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named# EOF after the `:=` token (x :=missing_expression_2.py000064400000000000000000000001271046102023000323160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named# Missing expression, instead there's a function definition (x := def foo(): passmissing_expression_3.py000064400000000000000000000001601046102023000323140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named# An expression is present, but it's most likely not what was intended for the # assignment value. (x := x + ymissing_expression_4.py000064400000000000000000000001161046102023000323160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/named# No expression on the right side of the assignment expression (x := ) x + ygenerator.py000064400000000000000000000000251046102023000317110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized(x := 1, for x in y) missing_closing_paren_0.py000064400000000000000000000000571046102023000345230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# Missing closing parentheses 0: No elements (missing_closing_paren_1.py000064400000000000000000000002111046102023000345140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# Missing closing parentheses 1: No elements on the same line, the one on the next line # is considered to be part of the list. ( x + ymissing_closing_paren_2.py000064400000000000000000000002221046102023000345170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# Missing closing parentheses 2: One element on the line, the other one on the next line # will be considered to be part of the tuple. (1, x + ymissing_closing_paren_3.py000064400000000000000000000002201046102023000345160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# Missing closing parentheses 3: Multiple elements without a trailing comma and the next # token starts a statement. (1, 2 def foo(): passparenthesized.py000064400000000000000000000001751046102023000325760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# Starred expression isn't allowed in a parenthesized expression. (*x) # Unparenthesized named expression is allowed. x := 1ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized/tuple.py000064400000000000000000000004131046102023000311340ustar00# Test cases for tuple expressions where the parser recovers from a syntax error. (,) (1,,2) (1,,) # Missing comma (1 2) # Dictionary element in a list (1: 2) # Missing expression (1, x + ) (1; 2) # Unparenthesized named expression is not allowed x, y := 2, ztuple_starred_expr.py000064400000000000000000000010241046102023000336360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/parenthesized# For tuple expression, the minimum binding power of star expression is bitwise or. # Test the first and any other element as there are two separate calls. (*x in y, z, *x in y) (*not x, z, *not x) (*x and y, z, *x and y) (*x or y, z, *x or y) (*x if True else y, z, *x if True else y) (*lambda x: x, z, *lambda x: x) (*x := 2, z, *x := 2) # Non-parenthesized *x in y, z, *x in y *not x, z, *not x *x and y, z, *x and y *x or y, z, *x or y *x if True else y, z, *x if True else y *lambda x: x, z, *lambda x: x *x := 2, z, *x := 2ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set/comprehension.py000064400000000000000000000005071046102023000306060ustar00# Invalid target {x for 1 in y} {x for 'a' in y} {x for call() in y} {x for {a, b} in y} # Invalid iter {x for x in *y} {x for x in yield y} {x for x in yield from y} {x for x in lambda y: y} # Invalid if {x for x in data if *y} {x for x in data if yield y} {x for x in data if yield from y} {x for x in data if lambda y: y} missing_closing_curly_brace_0.py000064400000000000000000000000571046102023000336360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set# Missing closing curly brace 0: No elements {missing_closing_curly_brace_1.py000064400000000000000000000002101046102023000336260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set# Missing closing curly brace 1: No elements on the same line, the one on the next line # is considered to be part of the set. { x + ymissing_closing_curly_brace_2.py000064400000000000000000000002201046102023000336300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set# Missing closing curly brace 2: One element on the line, the other one on the next line # will be considered to be part of the set. {1, x + ymissing_closing_curly_brace_3.py000064400000000000000000000002201046102023000336310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set# Missing closing curly brace 3: Multiple elements without a trailing comma and the next # token starts a statement. {1, 2 def foo(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set/recover.py000064400000000000000000000005031046102023000273760ustar00# Test cases for set expressions where the parser recovers from a syntax error. # There are valid expressions in between invalid ones to verify that. # These are same as for the list expressions. {,} {1,,2} {1,,} # Missing comma {1 2} # Dictionary element in a list {1: 2} # Missing expression {1, x + } {1; 2} [*] star_expression_precedence.py000064400000000000000000000003061046102023000332600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/set# For set expression, the minimum binding power of star expression is bitwise or. {(*x), y} {*x in y, z} {*not x, z} {*x and y, z} {*x or y, z} {*x if True else y, z} {*lambda x: x, z} {*x := 2, z}invalid_slice_element.py000064400000000000000000000002051046102023000334120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/subscriptx[x := 1:] # Starred expression x[*x:] x[:*x] x[::*x] # Empty slice x[] # Mixed starred expression and named expression x[*x := 1]unclosed_slice_0.py000064400000000000000000000000121046102023000323020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/subscriptx[: x + yunclosed_slice_1.py000064400000000000000000000000311046102023000323040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/subscriptx[:: def foo(): passnamed_expression.py000064400000000000000000000000221046102023000315540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/unary-x := 1 not x := 1no_expression_0.py000064400000000000000000000000121046102023000313220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/unarynot x + yno_expression_1.py000064400000000000000000000000101046102023000313210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/unary+ x + yast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/unary.py000064400000000000000000000000121046102023000262670ustar00not x := 1named_expression.py000064400000000000000000000001251046102023000315300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/yield# Unparenthesized named expressions are not allowed yield x := 1 yield 1, x := 2, 3 star_expression.py000064400000000000000000000001031046102023000314110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/yield# Cannot use starred expression here yield (*x) yield *x and y, z starred_expression.py000064400000000000000000000001441046102023000331340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/yield_from# Yield from doesn't allow top-level starred expression unlike yield yield from *x yield from *x, yunparenthesized.py000064400000000000000000000003001046102023000324130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/expressions/yield_from# Unparenthesized named expression yield from x := 1 # Unparenthesized tuple expression yield from x, y # This is a tuple expression parsing # vvvvvvvvvvvvv yield from (x, *x and y)ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lex_logical_token.py000064400000000000000000000017231046102023000267310ustar00# No indentation before the function definition if call(foo def bar(): pass # Indented function definition if call(foo def bar(): pass # There are multiple non-logical newlines (blank lines) in the `if` body if call(foo def bar(): pass # There are trailing whitespaces in the blank line inside the `if` body if call(foo def bar(): pass # The lexer is nested with multiple levels of parentheses if call(foo, [a, b def bar(): pass # The outer parenthesis is closed but the inner bracket isn't if call(foo, [a, b) def bar(): pass # The parser tries to recover from an unclosed `]` when the current token is `)`. This # test is to make sure it emits a `NonLogicalNewline` token after `b`. if call(foo, [a, b ) def bar(): pass # F-strings uses normal list parsing, so test those as well if call(f"hello {x def bar(): pass if call(f"hello def bar(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lex_logical_token_mac_eol.py000064400000000000000000000000561046102023000304060ustar00if call(foo, [a, b def bar(): passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lex_logical_token_windows_eol.py000064400000000000000000000000621046102023000313350ustar00if call(foo, [a, b def bar(): pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing/fstring_format_spec_1.py000064400000000000000000000004521046102023000310110ustar00# The newline character is being escaped which means that the lexer shouldn't be moved # back to that position. # https://github.com/astral-sh/ruff/issues/12004 f'middle {'string':\ 'format spec'} f'middle {'string':\\ 'format spec'} f'middle {'string':\\\ 'format spec'}ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing/line_continuation_1.py000064400000000000000000000000441046102023000304710ustar00call(a, b, \\\ def bar(): pass line_continuation_windows_eol.py000064400000000000000000000000561046102023000326060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexingcall(a, b, # comment \ def bar(): passtriple_quoted_fstring_1.py000064400000000000000000000003061046102023000313060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing# There are trailing whitespace before the newline character but those whitespaces are # part of the comment token. # https://github.com/astral-sh/ruff/issues/11929 f"""hello {x # comment y = 1triple_quoted_fstring_2.py000064400000000000000000000002671046102023000313150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing# The lexer can't be moved back for a triple-quoted f-string because the newlines are # part of the f-string itself. # https://github.com/astral-sh/ruff/issues/11937 f'''{foo:.3f '''triple_quoted_fstring_3.py000064400000000000000000000004061046102023000313110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing# Here, the nesting level is 2 when the parser is trying to recover from an unclosed `{` # This test demonstrates that we need to reduce the nesting level when recovering from # within an f-string but the lexer shouldn't go back. if call(f'''{x:.3f ''' passast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/re_lexing/ty_1828.py000064400000000000000000000001601046102023000256450ustar00# Regression test for https://github.com/astral-sh/ty/issues/1828 (c: int = 1,f"""{d=[ def a( class A: pass function_type_parameters.py000064400000000000000000000017341046102023000320040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements# FIXME: The type param related error message and the parser recovery are looking pretty good **except** # that the lexer never recovers from the unclosed `[`, resulting in it lexing `NonLogicalNewline` tokens instead of `Newline` tokens. # That's because the parser has no way of feeding the error recovery back to the lexer, # so they don't agree on the state of the world which can lead to all kind of errors further down in the file. # This is not just a problem with parentheses but also with the transformation made by the # `SoftKeywordTransformer` because the `Parser` and `Transformer` may not agree if they're # currently in a position where the `type` keyword is allowed or not. # That roughly means that any kind of recovery can lead to unrelated syntax errors # on following lines. def keyword[A, await](): ... def not_a_type_param[A, |, B](): ... def multiple_commas[A,,B](): ... def multiple_trailing_commas[A,,](): ... def multiple_commas_and_recovery[A,,100](): ... if_extra_closing_parentheses.py000064400000000000000000000001561046102023000326100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements# FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) if True)): pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/if_extra_indent.py000064400000000000000000000016111046102023000301060ustar00# On invalid indentation, recover as if the indentation wasn't there if True: pass a + b pass a = 10 # Multiple nested unexpected indents. if True: before_nested first_nested second_nested after_nested outside_nested # A valid compound statement inside recovered indentation. if True: before_compound if condition: nested_compound recovered_compound after_compound outside_compound # Multiple independent unexpected-indent regions in the same body. if True: before_regions first_region middle_region second_region after_region outside_regions # An independent syntax error inside recovered indentation stays visible. if True: before_error broken(,) after_error outside_error # Outstanding unexpected indents are flushed at EOF. if True: before_eof final_eof invalid_assignment_targets.py000064400000000000000000000014241046102023000322760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements# Regression test: https://github.com/astral-sh/ruff/issues/6895 # First we test, broadly, that various kinds of assignments are now # rejected by the parser. e.g., `5 = 3`, `5 += 3`, `(5): int = 3`. 5 = 3 5 += 3 (5): int = 3 # Now we exhaustively test all possible cases where assignment can fail. x or y = 42 (x := 5) = 42 x + y = 42 -x = 42 (lambda _: 1) = 42 a if b else c = 42 {"a": 5} = 42 {a} = 42 [x for x in xs] = 42 {x for x in xs} = 42 {x: x * 2 for x in xs} = 42 (x for x in xs) = 42 await x = 42 (yield x) = 42 (yield from xs) = 42 a < b < c = 42 foo() = 42 f"{quux}" = 42 f"{foo} and {bar}" = 42 "foo" = 42 b"foo" = 42 123 = 42 True = 42 None = 42 ... = 42 *foo() = 42 [x, foo(), y] = [42, 42, 42] [[a, b], [[42]], d] = [[1, 2], [[3]], 4] (x, foo(), y) = (42, 42, 42) invalid_augmented_assignment_target.py000064400000000000000000000011431046102023000341420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements# This is similar to `./invalid_assignment_targets.py`, but for augmented # assignment targets. x or y += 42 (x := 5) += 42 x + y += 42 -x += 42 (lambda _: 1) += 42 a if b else c += 42 {"a": 5} += 42 {a} += 42 [x for x in xs] += 42 {x for x in xs} += 42 {x: x * 2 for x in xs} += 42 (x for x in xs) += 42 await x += 42 (yield x) += 42 (yield from xs) += 42 a < b < c += 42 foo() += 42 f"{quux}" += 42 f"{foo} and {bar}" += 42 "foo" += 42 b"foo" += 42 123 += 42 True += 42 None += 42 ... += 42 *foo() += 42 [x, foo(), y] += [42, 42, 42] [[a, b], [[42]], d] += [[1, 2], [[3]], 4] (x, foo(), y) += (42, 42, 42) ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_0.py000064400000000000000000000003061046102023000304170ustar00match subject: # Parser shouldn't confuse this as being a # class pattern # v case (x as y)(a, b): # ^^^^^^ # as-pattern pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_1.py000064400000000000000000000003221046102023000304160ustar00match subject: # Parser shouldn't confuse this as being a # complex literal pattern # v case (x as y) + 1j: # ^^^^^^ # as-pattern pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_2.py000064400000000000000000000002761046102023000304270ustar00match subject: # This `as` pattern is unparenthesied so the parser never takes the path # where it might be confused as a complex literal pattern. case x as y + 1j: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_3.py000064400000000000000000000002101046102023000304140ustar00match subject: # Not in the mapping start token set, so the list parsing bails # v case {(x as y): 1}: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_4.py000064400000000000000000000002731046102023000304260ustar00match subject: # This `as` pattern is unparenthesized so the parser never takes the path # where it might be confused as a mapping key pattern. case {x as y: 1}: pass invalid_class_pattern.py000064400000000000000000000005771046102023000323430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match# Invalid keyword pattern in class argument match subject: case Foo(x as y = 1): pass case Foo(x | y = 1): pass case Foo([x, y] = 1): pass case Foo({False: 0} = 1): pass case Foo(1=1): pass case Foo(Bar()=1): pass # Positional pattern cannot follow keyword pattern # case Foo(x, y=1, z): # pass invalid_lhs_or_rhs_pattern.py000064400000000000000000000012671046102023000333750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/matchmatch invalid_lhs_pattern: case Foo() + 1j: pass case x + 2j: pass case _ + 3j: pass case (1 | 2) + 4j: pass case [1, 2] + 5j: pass case {True: 1} + 6j: pass case 1j + 2j: pass case -1j + 2j: pass case Foo(a as b) + 1j: pass match invalid_rhs_pattern: case 1 + Foo(): pass case 2 + x: pass case 3 + _: pass case 4 + (1 | 2): pass case 5 + [1, 2]: pass case 6 + {True: 1}: pass case 1 + 2: pass case 1 + Foo(a as b): pass match invalid_lhs_rhs_pattern: case Foo() + Bar(): pass invalid_mapping_pattern.py000064400000000000000000000007751046102023000326710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match# Starred expression is not allowed as a mapping pattern key match subject: case {*key}: pass case {*key: 1}: pass case {*key 1}: pass case {*key, None: 1}: pass # Pattern cannot follow a double star pattern # Multiple double star patterns are not allowed match subject: case {**rest, None: 1}: pass case {**rest1, **rest2, None: 1}: pass case {**rest1, None: 1, **rest2}: pass match subject: case {Foo(a as b): 1}: ...star_pattern_usage.py000064400000000000000000000010161046102023000316520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match# Star pattern is only allowed inside a sequence pattern match subject: case *_: pass case *_ as x: pass case *foo: pass case *foo | 1: pass case 1 | *foo: pass case Foo(*_): pass case Foo(x=*_): pass case {*_}: pass case {*_: 1}: pass case {None: *_}: pass case 1 + *_: pass # Sequence pattern can contain at most one star pattern match subject: case [*head, middle, *tail]: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/match/unary_add_usage.py000064400000000000000000000004151046102023000311730ustar00# Unary addition isn't allowed but we parse it for better error recovery. match subject: case +1: pass case 1 | +2 | -3: pass case [1, +2, -3]: pass case Foo(x=+1, y=-2): pass case {True: +1, False: -2}: pass ambiguous_lpar_with_items.py000064400000000000000000000016661046102023000331170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/with# This file contains test cases where the with items has an ambiguous left parenthesis. # These cases should raise the correct syntax error and recover properly. with (item1, item2),: ... with (item1, item2), as f: ... with (item1, item2), item3,: ... with (*item): ... with (*item) as f: ... with (item := 10 as f): ... with (item1, item2 := 10 as f): ... with (x for x in range(10), item): ... with (item, x for x in range(10)): ... # Make sure the parser doesn't report the same error twice with ((*item)): ... with (*x for x in iter, item): ... with (item1, *x for x in iter, item2): ... with (x as f, *y): ... with (*x, y as f): ... with (x, yield y): ... with (x, yield y, z): ... with (x, yield from y): ... with (x as f, y) as f: ... with (x for x in iter as y): ... # The inner `(...)` is parsed as parenthesized expression with ((item as f)): ... with (item as f), x: ... with (item as f1) as f2: ... with (item1 as f, item2 := 0): ...ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/with/empty_with_items.py000064400000000000000000000001511046102023000313070ustar00# There are no with items present. # The parser should recover from this syntax error. with : ... x + yunclosed_ambiguous_lpar.py000064400000000000000000000000161046102023000325430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/withwith (: x + yunclosed_ambiguous_lpar_eof.py000064400000000000000000000000061046102023000333730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/withwith (unparenthesized_with_items.py000064400000000000000000000003711046102023000333060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/invalid/statements/with# For parenthesized with items test cases, refer to `./ambiguous_lpar_with_items.py` with item,: pass with item as x,: pass with *item: pass with *item as x: pass with *item1, item2 as f: pass with item1 as f, *item2: pass with item := 0 as f: passast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/arguments.py000064400000000000000000000014451046102023000266220ustar00# This only tests the call arguments and not the expression before the opening parenthesis. # Simple call() call(x, y) call(x, y,) # Trailing comma call(x=1, y=2) call(*x) call(**x) # Order call(x, y=1) call(x, *y) call(x, **y) call(x=1, *y) call(x=1, **y) call(*x, **y) call(*x, y, z) call(**x, y=1, z=2) call(*x1, *x2, **y1, **y2) call(x=1, **y, z=1) # Keyword expression call(x=1 if True else 2) call(x=await y) call(x=lambda y: y) call(x=(y := 1)) # Yield expression call((yield x)) call((yield from x)) # Named expression call(x := 1) call(x := 1 for i in iter) # Starred expressions call(*x and y) call(*x | y) call(*await x) call(*lambda x: x) call(*x if True else y) # Double starred call(**x) call(**x and y) call(**await x) call(**x if True else y) call(**(yield x)) call(**lambda x: x) ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/attribute.py000064400000000000000000000001321046102023000266100ustar00value.attr value.attr() value().attr value().attr().foo value.attr.foo (value).attr().foo ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/await.py000064400000000000000000000003231046102023000257140ustar00await x await x + 1 await a and b await f() await [1, 2] await {3, 4} await {i: 5} await 7, 8 await (9, 10) await 1 == 1 await x if True else None await (*x,) await (lambda x: x) await x ** -x await x ** await yast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/bin_op.py000064400000000000000000000006151046102023000260610ustar00# Simple 1 + 2 1 - 2 1 * 2 1 / 2 1 // 2 1 % 2 1 ** 2 1 | 2 1 ^ 2 1 & 2 1 >> 2 1 << 2 1 @ 2 # Same precedence 1 + 2 - 3 + 4 1 * 2 / 3 // 4 @ 5 % 6 1 << 2 >> 3 >> 4 << 5 # Different precedence 1 + 2 * 3 1 * 2 + 3 1 ** 2 * 3 - 4 @ 5 + 6 - 7 // 8 # With bitwise operators 1 | 2 & 3 ^ 4 + 5 @ 6 << 7 // 8 >> 9 # Associativity 1 + (2 + 3) + 4 1 + 2 + (3 + 4 + 5) # Addition with a unary plus x ++ y ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/bool_op.py000064400000000000000000000002161046102023000262410ustar00a and b a and b and c a or b a or b or c a and b or c a and b and c or d or e and f or g a and not b or c yield a and b or c not a and b or c ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/call.py000064400000000000000000000005351046102023000255270ustar00# This only tests the expression before the opening parenthesis for the call expression # and not the arguments. call() attr.expr() subscript[1, 2]() slice[:1]() [1, 2, 3]() (1, 2, 3)() (x for x in iter)() {1, 2, 3}() {1: 2, 3: 4}() (yield x)() # These are `TypeError`, so make sure it parses correctly. True() False() None() "string"() 1() 1.0() ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/compare.py000064400000000000000000000010361046102023000262370ustar00# Simple a == b b < a b > a a >= b a <= b a != b a is c a in b a not in c a is not b # Double operator mixed a not in b is not c not in d not in e is not f # Precedence check a | b < c | d not in e & f # ^ ^^^^^^ # Higher precedence than bitwise operators # unary `not` is higher precedence, but is allowed at the start of the expression # but not anywhere else not x not in y x or y not in z and a x == await y x is not await y # All operators have the same precedence a < b == c > d is e not in f is not g <= h >= i != j ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/dictionary.py000064400000000000000000000011561046102023000267610ustar00# Simple {} {1: 2} {1: 2, a: 1, b: 'hello'} # Mixed indentations { } { 1: 2, 3 :4 } # Nested {{1: 2}: {3: {4: 5}}} # Lambda expressions {lambda x: x: 1} {'A': lambda p: None, 'B': C,} # Named expressions {(x := 1): y} {(x := 1): (y := 2)} # Double star unpacking {**d} {a: b, **d} {**a, **b} {"a": "b", **c, "d": "e"} {1: 2, **{'nested': 'dict'}} {x * 1: y ** 2, **call()} # Here, `not` isn't allowed but parentheses resets the precedence {**(not x)} # Random expressions {1: x if True else y} {x if True else y: y for x in range(10) for y in range(10)} {{1, 2}: 3, x: {1: 2,},} {(x): (y), (z): (a)} dictionary_comprehension.py000064400000000000000000000011151046102023000316260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions{y for y in (1, 2, 3)} {x1: x2 for y in z} {x + 1: 'x' for i in range(5)} {b: c * 2 for c in d if x in w if y and yy if z} {a: a ** 2 for b in c if d and e for f in j if k > h} {a: b for b in c if d and e async for f in j if k > h} {a: a for b, c in d} # Non-parenthesized iter/if for the following expressions aren't allowed, so make sure # it parses correctly for the parenthesized cases {x: y for x in (yield y)} {x: y for x in (yield from y)} {x: y for x in (lambda y: y)} {x: y for x in data if (yield y)} {x: y for x in data if (yield from y)} {x: y for x in data if (lambda y: y)} ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/f_string.py000064400000000000000000000017231046102023000264270ustar00# Empty f-strings f"" F"" f'' f"""""" f'''''' f"{" f"}" f"{foo!s}" f"{3,}" f"{3!=4:}" f'{3:{"}"}>10}' f'{3:{"{"}>10}' f"{ foo = }" f"{ foo = :.3f }" f"{ foo = !s }" f"{ 1, 2 = }" f'{f"{3.1415=:.1f}":*^20}' {"foo " f"bar {x + y} " "baz": 10} match foo: case "one": pass case "implicitly " "concatenated": pass f"\{foo}\{bar:\}" f"\\{{foo\\}}" f"""{ foo:x y z }""" f"{ ( foo ) = }" f"normal {foo} {{another}} {bar} {{{three}}}" f"normal {foo!a} {bar!s} {baz!r} {foobar}" f"normal {x:y + 2}" f"{x:{{1}.pop()}}" f"{(lambda x:{x})}" f"{x =}" f"{ x = }" f"{x=!a}" f"{x:.3f!r =}" f"{x = !r :.3f}" f"{x:.3f=!r}" "hello" f"{x}" f"{x}" f"{y}" f"{x}" "world" f"Invalid args in command: {command, *args}" "foo" f"{x}" "bar" ( f"a" F"b" "c" rf"d" fr"e" ) # With unicode strings u"foo" f"{bar}" "baz" " some" "foo" f"{bar}" u"baz" " some" "foo" f"{bar}" "baz" u" some" u"foo" f"bar {baz} really" u"bar" "no" ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/generator.py000064400000000000000000000007421046102023000266020ustar00(x for target in iter) (x async for target in iter) (x for target in iter if x in y if a and b if c) (x for target1 in iter1 if x and y for target2 in iter2 if a > b) (x for target1 in iter1 if x and y async for target2 in iter2 if a > b) # Named expression (x := y + 1 for y in z) # If expression (x if y else y for y in z) # Arguments " ".join( sql for sql in ( "LIMIT %d" % limit if limit else None, ("OFFSET %d" % offset) if offset else None, ) ) ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/if.py000064400000000000000000000006471046102023000252160ustar00a if True else b f() if x else None a if b else c if d else e 1 + x if 1 < 0 else -1 a and b if x else False x <= y if y else x True if a and b else False 1, 1 if a else c # Lambda is allowed in orelse expression x if True else lambda y: y # These test expression are only allowed when parenthesized x if (yield x) else y x if (yield from x) else y x if (lambda x: x) else y # Split across multiple lines (x if y else z)ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/lambda.py000064400000000000000000000010221046102023000260240ustar00lambda: a lambda: 1 lambda x: 1 lambda x, y: ... lambda a, b, c: 1 lambda a, b=20, c=30: 1 lambda x, y: x * y lambda y, z=1: z * y lambda *a: a lambda *a, z, x=0: ... lambda *, a, b, c: 1 lambda *, a, b=20, c=30: 1 lambda a, b, c, *, d, e: 0 lambda **kwargs: f() lambda *args, **kwargs: f() + 1 lambda *args, a, b=1, **kwargs: f() + 1 lambda a, /: ... lambda a, /, b: ... lambda a=1, /,: ... lambda a, b, /, *, c: ... lambda kw=1, *, a: ... lambda a, b=20, /, c=30: 1 lambda a, b, /, c, *, d, e: 0 lambda a, b, /, c, *d, e, **f: 0ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/list.py000064400000000000000000000006151046102023000255660ustar00# Simple lists [] [1] [1,] [1, 2, 3] [1, 2, 3,] # Mixed with indentations [ ] [ 1 ] [ 1, 2, ] # Nested [[[1]]] [[1, 2], [3, 4]] # Named expression [x := 2] [x := 2,] [1, x := 2, 3] # Star expression [1, *x, 3] [1, *x | y, 3] # Random expressions [1 + 2, [1, 2, 3, 4], (a, b + c, d), {a, b, c}, {a: 1}, x := 2] [call1(call2(value.attr()) for element in iter)] [item in xs] ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/list_comprehension.py000064400000000000000000000014101046102023000305110ustar00x = [y for y in (1, 2, 3)] [x for i in range(5)] [b for c in d if x in w if y and yy if z] [a for b in c if d and e for f in j if k > h] [a for b in c if d and e async for f in j if k > h] [1 for i in x in a] [a for a, b in G] [ await x for a, b in C ] [i for i in await x if entity is not None] [x for x in (l if True else L) if T] [i for i in (await x if True else X) if F] [i for i in await (x if True else X) if F] [f for f in c(x if True else [])] # Non-parenthesized iter/if for the following expressions aren't allowed, so make sure # it parses correctly for the parenthesized cases [x for x in (yield y)] [x for x in (yield from y)] [x for x in (lambda y: y)] [x for x in data if (yield y)] [x for x in data if (yield from y)] [x for x in data if (lambda y: y)] ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/name.py000064400000000000000000000001141046102023000255250ustar00_ (_) __ __init__ name (name) # Soft keywords used as name match case type ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/named.py000064400000000000000000000002351046102023000256750ustar00(name := 0) (name := (x * y)) (name := 1 + 1) (name := (*x, y)) (name := x if True else y) (name := lambda x: x) (name := (yield x)) (name := (yield from x))ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/number_literal.py000064400000000000000000000012741046102023000276210ustar00x = 123456789 x = 123456 x = .1 x = 1. x = 1E+1 x = 1E-1 x = 1.000_000_01 x = 123456789.123456789 x = 123456789.123456789E123456789 x = 123456789E123456789 x = 123456789J x = 123456789.123456789J x = 0XB1ACC x = 0B1011 x = 0O777 x = 0.000000006 x = 10000 x = 133333 # Attribute access x = 1. .imag x = 1E+1.imag x = 1E-1.real x = 123456789.123456789.hex() x = 123456789.123456789E123456789 .real x = 123456789E123456789 .conjugate() x = 123456789J.real x = 123456789.123456789J.__add__(0b1011.bit_length()) x = 0XB1ACC.conjugate() x = 0B1011 .conjugate() x = 0O777 .real x = 0.000000006 .hex() x = -100.0000J if 10 .real: ... # This is a type error, not a syntax error y = 100[no] y = 100(no)ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/parenthesized.py000064400000000000000000000001341046102023000274540ustar00(expr) (expr)() (expr)()()() (a and b or c) (lambda x: x) (x := 2) (yield x) (yield from x)ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/set.py000064400000000000000000000004711046102023000254060ustar00# Simple sets {} {1} {1,} {1, 2, 3} {1, 2, 3,} # Mixed with indentations { } { 1 } { 1, 2, } # Nested {{1}} {{1, 2}, {3, 4}} # Named expression {x := 2} {1, x := 2, 3} {1, (x := 2),} # Star expression {1, *x, 3} {1, *x | y, 3} # Random expressions {1 + 2, (a, b), {1, 2, 3}, {a: b, **d}} ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/set_comprehension.py000064400000000000000000000007541046102023000303430ustar00{x for i in ll} {b for c in d if x in w if y and yy if z} {a for b in c if d and e for f in j if k > h} {a for b in c if d and e async for f in j if k > h} {a for a, b in G} # Non-parenthesized iter/if for the following expressions aren't allowed, so make sure # it parses correctly for the parenthesized cases {x for x in (yield y)} {x for x in (yield from y)} {x for x in (lambda y: y)} {x for x in data if (yield y)} {x for x in data if (yield from y)} {x for x in data if (lambda y: y)} ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/slice.py000064400000000000000000000003231046102023000257060ustar00# Various combinations x[:] x[1:] x[:2] x[1:2] x[::] x[1::] x[:2:] x[1:2:] x[::3] x[1::3] x[:2:3] x[1:2:3] # Named expression x[y := 2] x[(y := 2):] x[y := 2,] # These are two separate slice elements x[1,:2,] ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/starred.py000064400000000000000000000002541046102023000262560ustar00*a *(a + 1) *x.attr array_slice = array[0, *indexes, -1] array[0, *indexes, -1] = array_slice array[*indexes_to_select, *indexes_to_select] array[3:5, *indexes_to_select] ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/string.py000064400000000000000000000002431046102023000261160ustar00'Hello World' "😎" 'Foo' 'Bar' ( 'A' 'B' 'C' ) '''Olá, Mundo!''' """ABCDE""" ( '''aB''' '''cD''' ) b'hello world' b'bytes' b'concatenated' ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/subscript.py000064400000000000000000000004121046102023000266240ustar00data[0][0] data[0, 1] data[0:,] data[0:, 1] data[0:1, 2] data[0:1:2, 3, a:b + 1] data[a := b] data[:, :11] data[1, 2, 3] data[~flag] data[(a := 0):] data[(a := 0):y] # This is a single element tuple with a starred expression data[*x] data[*x and y] data[*(x := y)] ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/t_string.py000064400000000000000000000015401046102023000264420ustar00# Empty t-strings t"" t"" t'' t"""""" t'''''' t"{" t"}" t"{foo!s}" t"{3,}" t"{3!=4:}" t'{3:{"}"}>10}' t'{3:{"{"}>10}' t"{ foo = }" t"{ foo = :.3f }" t"{ foo = !s }" t"{ 1, 2 = }" t'{t"{3.1415=:.1f}":*^20}' {t"foo " t"bar {x + y} " t"baz": 10} match foo: case "one": pass case "implicitly " "concatenated": pass t"\{foo}\{bar:\}" t"\\{{foo\\}}" t"""{ foo:x y z }""" t"{ ( foo ) = }" t"normal {foo} {{another}} {bar} {{{three}}}" t"normal {foo!a} {bar!s} {baz!r} {foobar}" t"normal {x:y + 2}" t"{x:{{1}.pop()}}" t"{(lambda x:{x})}" t"{x =}" t"{ x = }" t"{x=!a}" t"{x:.3f!r =}" t"{x = !r :.3f}" t"{x:.3f=!r}" t"hello" t"{x}" t"{x}" t"{y}" t"{x}" t"world" t"Invalid args in command: {command, *args}" t"foo" t"{x}" t"bar" ( t"a" t"b" t"c" rt"d" tr"e" ) # Nesting t"{f"{t"{this}"}"}" ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/tuple.py000064400000000000000000000004241046102023000257420ustar00# With parentheses () (()) ((()), ()) (a,) (a, b) (a, b,) ((a, b)) # Without parentheses a, a, b a, b, # Starred expression *a, a, *b *a | b, *await x, (), *() (*a,) (a, *b) (*a | b, *await x, (), *()) # Named expression (x := 1,) (x, y := 2) (x, y := 2, z) x, (y := 2), z ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/unary_op.py000064400000000000000000000004241046102023000264450ustar00# Simple -1 +1 ~1 not x # Multiple ---1 -+~1 not-+~1 not not x # Precedence check - await 1 + await 1 ** -2 ~(1, 2) -1 + 2 # Precedence check for `not` operator because it is higher than other unary operators not a and b or not c | d and not e not (x := 1) not a | (not b) ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/yield.py000064400000000000000000000002461046102023000257210ustar00yield yield x yield x + 1 yield x and y yield call() yield [1, 2] yield {3, 4} yield {x: 5} yield x, y yield (x, y) yield x == y yield (x := 1) yield x, *y yield *x, ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/expressions/yield_from.py000064400000000000000000000003071046102023000267420ustar00yield from x yield from x + 1 yield from x and y yield from call() yield from [1, 2] yield from {3, 4} yield from {x: 5} yield from (x, y) yield from x == y yield from (x := 1) yield from (x, *x | y)ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/other/atom.py000064400000000000000000000001111046102023000243010ustar00... True False None # Other atoms are tested in their respective files. ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/other/decorator.py000064400000000000000000000006271046102023000253370ustar00@function_decorator def test(): pass @class_decorator class Test: pass @decorator def f(): ... @a.b.c def f(): ... @a @a.b.c def f(): ... @a @1 | 2 @a.b.c class T: ... @x := 1 @x if True else y @lambda x: x @x and y @(yield x) @(*x, *y) def f(): ... # This is not multiple decorators on the same line but rather a binary (`@`) expression @x @y def foo(): ... @x @y def foo(): ...ambiguous_lpar_with_items.py000064400000000000000000000070441046102023000314260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement# These test cases specifically tests out parsing a list of with items that start with a # left parenthesis. This makes parsing ambiguous as to whether the left parenthesis is to # parenthesize the with items or part of a parenthesized expression. It's not to test the # with statement itself. # The following sections basically separates between which node does the # start parenthesis belongs to. # Parenthesized with items # ------------------------ # # - The opening parenthesis belongs to the with statement. # - The range of the first with item shouldn't include the parenthesis. with (item): ... with (item,): ... # with a trailing comma with (((item))): ... with (item1, item2): ... with (item1, item2,): ... # with a trailing comma with ((item1), (item2), item3 as f, (item4)): ... with ((item1, item2), item3): ... with ((x, y) as f): ... with (item1 as f1, item2 as f2): ... with (item1 as f1, item2 as f2,): ... # with a trailing comma with (item == 10,): ... with ((item := 10)): ... with ((item := 10,)): ... with ((*item,)): ... with ((item1 := 10), item2): ... with (item1 as f, (item2 := 10)): ... with (foo()): ... with (foo(),): ... with (foo() as f): ... with (f"{item := 42}"): ... with (f"{(item := 42)}"): ... with ((x for x in range(10)), item): ... with (item, (x for x in range(10))): ... with (item, (x for x in range(10)), item): ... with (data[1:2]): ... with (data[1:2] as f): ... with ((x for x in iter) as y): ... # Parenthesized expression # ------------------------ # # - The opening parenthesis belongs to the context expression of the first with item. # - The range of the first with item should include the parenthesis. with (item) as f: ... with (item := 10): ... with (item := 10) as f: ... with ( item := 1 ): ... with (item1 := 42), item2: ... with (root + filename).read(): ... # Postfix expression with (root + filename).read() as f: ... # Postfix expression with (foo)(): ... # Postfix expression with (foo)() as f: ... # Postfix expression with (foo()) as f: ... with (data[1:2]) as f: ... with (1, 2, 3)[0]: ... # Postfix expression with (1, 2, 3)[0] as f: ... # Postfix expression with (item1), (item2): ... with (open('a.py')), (open('b.py')): ... with (yield x): ... with ((yield x)): ... with (yield from x): ... with ((yield from x)): ... with (yield x) as f: ... with (yield x,) as f: ... # Tuple expression # ---------------- # # - This is a sub-case of the parenthesized expression and requires transforming the list of # with items from the speculative parsing to a single with item containing a tuple expression. # - The opening parenthesis belongs to the tuple expression of the first with item. # - The range of the first with item should include the parenthesis. with (): ... with () as f: ... with (item := 42,): ... with (1, item := 2): ... with (item1 := 10, item2): ... with (item1, item2 := 2, item3) as f: ... with (item,) as f: ... with (*item,): ... with (*item,) as f: ... with (item1, item2) as f: ... with (item1, item2,) as f: ... with (item1, item2), item3: ... with ((item1, item2), item3) as f: ... with (item1,), item2, (item3, item4) as f: ... with (item1, item2) as f1, item3 as f2: ... with (item1, *item2): ... with (item1, *item2) as f: ... with (item1 := 10, *item2): ... with ((item1 := 10), *item2): ... # Parenthesized generator expression # ---------------------------------- # # - The opening parenthesis belongs to the generator expression # - The range of the with item should include the parenthesis with (x for x in range(10)): ... with (x async for x in range(10)): ... with (x for x in range(10)), item: ...ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/annotated_assignment.py000064400000000000000000000001471046102023000304420ustar00x: int x: int = 1 (x): 1 + 2 x: tuple[int] | int = (1,) x: int if True else str = 1 x: lambda x: y = 1 ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/assert.py000064400000000000000000000002721046102023000255350ustar00assert 1 < 2 assert call() assert a and b assert lambda x: y assert await x assert x if True else y assert x, "error" assert x, lambda x: y assert x, await x assert x, x if True else y ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/assignment.py000064400000000000000000000013311046102023000264010ustar00x = (1, 2, 3) (x, y) = (1, 2, 3) [x, y] = (1, 2, 3) x.y = (1, 2, 3) x[y] = (1, 2, 3) (x, *y) = (1, 2, 3) # This last group of tests checks that assignments we expect to be parsed # (including some interesting ones) continue to be parsed successfully. [x, y, z] = [1, 2, 3] (x, y, z) = (1, 2, 3) x[0] = 42 # This is actually a type error, not a syntax error. So check that it # doesn't fail parsing. 5[0] = 42 x[1:2] = [42] # This is actually a type error, not a syntax error. So check that it # doesn't fail parsing. 5[1:2] = [42] foo.bar = 42 # This is actually an attribute error, not a syntax error. So check that # it doesn't fail parsing. "foo".y = 42 foo = 42 [] = (*data,) () = (*data,) a, b = ab a = b = cast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/augmented_assignment.py000064400000000000000000000003241046102023000304330ustar00x += 1 x.y += (1, 2, 3) x[y] += (1, 2, 3) # All possible augmented assignment tokens x += 1 x -= 1 x *= 1 x /= 1 x //= 1 x %= 1 x **= 1 x &= 1 x |= 1 x ^= 1 x <<= 1 x >>= 1 x @= 1 # Mixed a //= (a + b) - c ** 2ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/class.py000064400000000000000000000017771046102023000253540ustar00class Test: ... class Test(): def __init__(self): pass class Test(a=1, *A, **k): ... class Test: def method(): a, b = data class Test(A, B): def __init__(self): pass def method_with_default(self, arg='default'): pass # Class with generic types: # TypeVar class Test[T](): ... # TypeVar with default class Test[T = str](): ... # TypeVar with bound class Test[T: str](): ... # TypeVar with bound and default class Test[T: int | str = int](): ... # TypeVar with tuple bound class Test[T: (str, bytes)](): ... # Multiple TypeVar class Test[T, U](): ... # Trailing comma class Test[T, U,](): ... # TypeVarTuple class Test[*Ts](): ... # TypeVarTuple with default class Test[*Ts = Unpack[tuple[int, str]]](): ... # TypeVarTuple with starred default class Test[*Ts = *tuple[int, str]](): ... # ParamSpec class Test[**P](): ... # ParamSpec with default class Test[**P = [int, str]](): ... # Mixed types class Test[X, Y: str, *U, **P](): pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/delete.py000064400000000000000000000001721046102023000254750ustar00del x del (x) del a, b, del a, (b, c), d del [a, b] del [a, [b, c], d] del x.y del x[y] del ( x, x.y, x[y], ) ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/for.py000064400000000000000000000010131046102023000250140ustar00for target in iter: pass for target in (1, 2, 3): pass for target.attr in call(): pass for target[0] in x.attr: pass for target in x <= y: pass for target in a and b: pass for a, b, c, in iter: pass for (a, b) in iter: pass for target in [1, 2]: pass for target in await x: ... for target in lambda x: x: ... for target in x if True else y: ... if x: for target in iter: pass # This `else` is not part of the `try` statement, so don't raise an error else: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/from_import.py000064400000000000000000000004031046102023000265650ustar00from a import b # comment from . import a from foo.bar import baz as b, FooBar as fb from .a import b from ... import c from .......................... import d from ..........................a.b.c import d from module import (a, b as B, c,) from a import * ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/function.py000064400000000000000000000045371046102023000260710ustar00def no_parameters(): pass def positional_parameters(a, b, c): pass def positional_parameters_with_default_values(a, b=20, c=30): pass def positional_parameters_with_default_values2(a, b=20, /, c=30): pass def positional_only_and_positional_parameters(a, /, b, c): pass def pos_args_with_defaults_and_varargs_and_kwargs(a, b=20, /, c=30, *args, **kwargs): pass def keyword_only_parameters(*, a, b, c): pass def keyword_only_parameters_with_defaults(*, a, b=20, c=30): pass def kw_only_args_with_defaults_and_varargs(*args, a, b=20, c=30): pass def kw_only_args_with_defaults_and_kwargs(*, a, b=20, c=30, **kwargs): pass def kw_only_args_with_defaults_and_varargs_and_kwargs(*args, a, b=20, c=30, **kwargs): pass def pos_and_kw_only_args(a, b, /, c, *, d, e, f): pass def pos_and_kw_only_args_with_defaults(a, b, /, c, *, d, e=20, f=30): pass def pos_and_kw_only_args_with_defaults_and_varargs(a, b, /, c, *args, d, e=20, f=30): pass def pos_and_kw_only_args_with_defaults_and_kwargs( a, b, /, c, *, d, e=20, f=30, **kwargs ): pass def pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs( a, b, /, c, *args, d, e=20, f=30, **kwargs ): pass def positional_and_keyword_parameters(a, b, c, *, d, e, f): pass def positional_and_keyword_parameters_with_defaults(a, b, c, *, d, e=20, f=30): pass def positional_and_keyword_parameters_with_defaults_and_varargs( a, b, c, *args, d, e=20, f=30 ): pass def positional_and_keyword_parameters_with_defaults_and_varargs_and_kwargs( a, b, c, *args, d, e=20, f=30, **kwargs ): pass # Function definitions with type parameters def func[T](a: T) -> T: pass def func[T: str](a: T) -> T: pass def func[T: (str, bytes)](a: T) -> T: pass def func[*Ts](*a: *Ts) -> Tuple[*Ts]: pass def func[**P](*args: P.args, **kwargs: P.kwargs): pass def func[T, U: str, *Ts, **P](): pass def ellipsis(): ... def multiple_statements() -> int: call() pass ... def foo(*args): pass def foo(**kwargs): pass def foo(*args, **kwargs): pass def foo(a, /): pass def foo(a, /, b): pass def foo(a=1, /,): pass def foo(a, b, /, *, c): pass def foo(kw=1, *, a): pass def foo(x: int, y: "str", z: 1 + 2): pass def foo(self, a=1, b=2, c=3): pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/if.py000064400000000000000000000005671046102023000246410ustar00if 1: 10 elif 2: 20 else: 30 if True: 1 ... if x < 1: ... else: pass if a: pass elif b: ... if a and b: ... elif True: ... elif c: ... elif d: ... else: f() # Valid test expression if a := b: ... elif a := b: ... if lambda x: x: ... elif lambda x: x: ... if await x: ... elif await x: ... if (yield x): ... elif (yield x): ... ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/import.py000064400000000000000000000001341046102023000255430ustar00import a import a.b.c import a.b.c as d import a, b, c import foo.bar as a, a.b.c.d as abcd ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/match.py000064400000000000000000000132121046102023000253260ustar00# Cases sampled from Lib/test/test_patma.py # case test_patma_098 match x: case -0j: y = 0 # case test_patma_142 match x: case bytes(z): y = 0 # case test_patma_073 match x: case 0 if 0: y = 0 case 0 if 1: y = 1 # case test_patma_006 match 3: case 0 | 1 | 2 | 3: x = True # case test_patma_049 match x: case [0, 1] | [1, 0]: y = 0 # case black_check_sequence_then_mapping match x: case [*_]: return "seq" case {}: return "map" # case test_patma_035 match x: case {0: [1, 2, {}]}: y = 0 case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: y = 1 case []: y = 2 # case test_patma_107 match x: case 0.25 + 1.75j: y = 0 # case test_patma_097 match x: case -0j: y = 0 # case test_patma_007 match 4: case 0 | 1 | 2 | 3: x = True # case test_patma_154 match x: case 0 if x: y = 0 # case test_patma_134 match x: case {1: 0}: y = 0 case {0: 0}: y = 1 case {**z}: y = 2 # case test_patma_185 match Seq(): case [*_]: y = 0 # case test_patma_063 match x: case 1: y = 0 case 1: y = 1 # case test_patma_248 match x: case {"foo": bar}: y = bar # case test_patma_019 match (0, 1, 2): case [0, 1, *x, 2]: y = 0 # case test_patma_052 match x: case [0]: y = 0 case [1, 0] if (x := x[:0]): y = 1 case [1, 0]: y = 2 # case test_patma_191 match w: case [x, y, *_]: z = 0 # case test_patma_110 match x: case -0.25 - 1.75j: y = 0 # case test_patma_151 match (x,): case [y]: z = 0 # case test_patma_114 match x: case A.B.C.D: y = 0 # case test_patma_232 match x: case None: y = 0 # case test_patma_058 match x: case 0: y = 0 # case test_patma_233 match x: case False: y = 0 # case test_patma_078 match x: case []: y = 0 case [""]: y = 1 case "": y = 2 # case test_patma_156 match x: case z: y = 0 # case test_patma_189 match w: case [x, y, *rest]: z = 0 # case test_patma_042 match x: case (0 as z) | (1 as z) | (2 as z) if z == x % 2: y = 0 # case test_patma_034 match x: case {0: [1, 2, {}]}: y = 0 case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: y = 1 case []: y = 2 # case test_patma_123 match (0, 1, 2): case 0, *x: y = 0 # case test_patma_126 match (0, 1, 2): case *x, 2,: y = 0 # case test_patma_151 match x,: case y,: z = 0 # case test_patma_152 match w, x: case y, z: v = 0 # case test_patma_153 match w := x,: case y as v,: z = 0 match x: # F-strings aren't allowed as patterns but it's a soft syntax error in Python. case f"{y}": pass match {"test": 1}: case { **rest, }: print(rest) match {"label": "test"}: case { "label": str() | None as label, }: print(label) match x: case [0, 1,]: y = 0 match x: case (0, 1,): y = 0 match x: case (0,): y = 0 match x,: case z: pass match x, y: case z: pass match x, y,: case z: pass # PatternMatchSingleton match x: case None: ... case True: ... case False: ... # PatternMatchValue match x: case a.b: ... case a.b.c: ... case '': ... case b'': ... case 1: ... case 1.0: ... case 1.0J: ... case 1 + 1j: ... case -1: ... case -1.: ... case -0b01: ... case (1): ... # PatternMatchOr match x: case 1 | 2: ... case '' | 1.1 | -1 | 1 + 1j | a.b: ... # PatternMatchAs match x: case a: ... match x: case a as b: ... match x: case 1 | 2 as two: ... case 1 + 3j as sum: ... case a.b as ab: ... case _ as x: ... match x: case _: ... # PatternMatchSequence match x: case 1, 2, 3: ... case (1, 2, 3,): ... case (1 + 2j, a, None, a.b): ... case (1 as X, b) as S: ... case [1, 2, 3 + 1j]: ... case ([1,2], 3): ... case [1]: ... # PatternMatchStar match x: case *a,: ... case *_,: ... case [1, 2, *rest]: ... case (*_, 1, 2): ... # PatternMatchClass match x: case Point(): ... case a.b.Point(): ... case Point2D(x=0): ... case Point2D(x=0, y=0,): ... case Point2D(0, 1): ... case Point2D([0, 1], y=1): ... case Point2D(x=[0, 1], y=1): ... # PatternMatchMapping match x := b: case {1: _}: ... case {'': a, None: (1, 2), **rest}: ... # Pattern guard match y: case a if b := c: ... case e if 1 < 2: ... # `match` as an identifier match *a + b, c # ((match * a) + b), c match *(a + b), c # (match * (a + b)), c match (*a + b, c) # match ((*(a + b)), c) match -a * b + c # (match - (a * b)) + c match -(a * b) + c # (match - (a * b)) + c match (-a) * b + c # (match (-(a * b))) + c match ().a # (match()).a match (()).a # (match(())).a match ((),).a # (match(())).a match [a].b # (match[a]).b match [a,].b # (match[(a,)]).b (not (match[a]).b) match [(a,)].b # (match[(a,)]).b match()[a: b] # (match())[a: b] if match := 1: pass match match: case 1: pass case 2: pass match = lambda query: query == event print(match(12)) ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/raise.py000064400000000000000000000004411046102023000253350ustar00# raise raise raise a raise (a, b) raise 1 < 2 raise a and b raise lambda x: y raise await x raise x if True else y # raise ... from ... raise x from a raise x from (a, b) raise x from 1 < 2 raise x from a and b raise x from lambda x: y raise x from await x raise x from x if True else y ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/return.py000064400000000000000000000002471046102023000255550ustar00return return x return *x, *y return (x := 1) return None return x and y return 1 < 2 return 1, 2, return call() return attr.value() return await x return lambda x: y ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/simple.py000064400000000000000000000002541046102023000255250ustar00# Other simple statements are contained in their own files. continue break if x: ... if True: pass 1; 2; pass 1; ...; a if b else c if c: B; del A else: C if x: yield x;ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/try.py000064400000000000000000000023071046102023000250530ustar00try: ... except: ... try: ... except Exception1 as e: ... except Exception2 as e: ... try: ... except Exception as e: ... except: ... finally: ... try: ... except: ... else: ... try: ... except: ... else: ... finally: ... try: ... finally: ... try: ... else: ... finally: ... try: ... except* GroupA as eg: ... except* ExceptionGroup: ... try: raise ValueError(1) except TypeError as e: print(f"caught {type(e)}") except OSError as e: print(f"caught {type(e)}") try: raise ExceptionGroup("eg", [ValueError(1), TypeError(2), OSError(3), OSError(4)]) except* TypeError as e: print(f"caught {type(e)} with nested {e.exceptions}") except* OSError as e: print(f"caught {type(e)} with nested {e.exceptions}") try: pass except "exception": pass except 1: pass except True: pass except 1 + 1: pass except a | b: pass except x and y: pass except await x: pass except lambda x: x: pass except x if True else y: pass if True: try: pass finally: pass # This `else` is not part of the `try` statement, so don't raise an error else: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/type.py000064400000000000000000000034441046102023000252210ustar00type 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) type X[T = int] = T | str type X[T: int | str = int] = T | int | str type X[*Ts = *tuple[int, str]] = tuple[int, *Ts, str] type X[**P = [int, str]] = Callable[P, str] # Soft keyword as alias name type type = int type match = int type case = int # Soft keyword as value type foo = type type foo = match type foo = case # Multine definitions type \ X = int type X \ = int type X = \ int type X = ( int ) type \ X[T] = T type X \ [T] = T type X[T] \ = T # Simple statements type X = int; type X = str; type X = type class X: type X = int type Point = tuple[float, float] type Point[T] = tuple[T, T] type IntFunc[**P] = Callable[P, int] # ParamSpec type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple type HashableSequence[T: Hashable] = Sequence[T] # TypeVar with bound type IntOrStrSequence[T: (int, str)] = Sequence[T] # TypeVar with constraints # Type as an identifier type *a + b, c # ((type * a) + b), c type *(a + b), c # (type * (a + b)), c type (*a + b, c) # type ((*(a + b)), c) type -a * b + c # (type - (a * b)) + c type -(a * b) + c # (type - (a * b)) + c type (-a) * b + c # (type (-(a * b))) + c type ().a # (type()).a type (()).a # (type(())).a type ((),).a # (type(())).a type [a].b # (type[a]).b type [a,].b # (type[(a,)]).b (not (type[a]).b) type [(a,)].b # (type[(a,)]).b type()[a: b] # (type())[a: b] if type := 1: pass type = lambda query: query == event print(type(12)) type(type) a = ( type in C ) a = ( type(b) ) type ( X = int ) type = 1 type = x = 1 x = type = 1 lambda x: typeast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/while.py000064400000000000000000000004721046102023000253460ustar00while x: ... while (x > 1) and y: pass else: ... while x and y: ... print('Hello World!') else: print('Olá, Mundo!') ... while a := b: ... while (a := b) and c: ... while lambda x: x: ... while await x: ... if True: while x: pass else: pass else: pass ast_serialize-0.13.1/crates/ruff_python_parser/resources/valid/statement/with.py000064400000000000000000000005511046102023000252070ustar00# This file only contains unparenthesized with items. Refer to ./ambiguous_lpar_with_items.py # for parenthesized with items test cases with item: ... with item as f: ... with item1, item2: ... with item1 as f1, item2 as f2: ... with x if True else y: ... with x if True else y as f: ... # Postfix expressions with open() as f: ... with open() as f.attr: ...ast_serialize-0.13.1/crates/ruff_python_parser/src/error.rs000064400000000000000000001257211046102023000210420ustar00use std::fmt::{self, Display}; use ruff_python_ast::PythonVersion; use ruff_python_ast::token::TokenKind; use ruff_text_size::{Ranged, TextRange}; use crate::string::InterpolatedStringKind; /// Represents represent errors that occur during parsing and are /// returned by the `parse_*` functions. #[derive(Debug, PartialEq, Eq, Clone, get_size2::GetSize)] pub struct ParseError { pub error: ParseErrorType, pub location: TextRange, } impl std::ops::Deref for ParseError { type Target = ParseErrorType; fn deref(&self) -> &Self::Target { &self.error } } impl std::error::Error for ParseError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) } } impl fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{} at byte range {:?}", self.error, self.location) } } impl From for ParseError { fn from(error: LexicalError) -> Self { ParseError { location: error.location(), error: ParseErrorType::Lexical(error.into_error()), } } } impl Ranged for ParseError { fn range(&self) -> TextRange { self.location } } impl ParseError { pub fn error(self) -> ParseErrorType { self.error } } /// Represents the different types of errors that can occur during parsing of an f-string or t-string. #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)] pub enum InterpolatedStringErrorType { /// Expected a right brace after an opened left brace. UnclosedLbrace, /// An invalid conversion flag was encountered. InvalidConversionFlag, /// A single right brace was encountered. SingleRbrace, /// Unterminated string. UnterminatedString, /// Unterminated triple-quoted string. UnterminatedTripleQuotedString, /// A lambda expression without parentheses was encountered. LambdaWithoutParentheses, /// Conversion flag does not immediately follow exclamation. ConversionFlagNotImmediatelyAfterExclamation, /// Newline inside of a format spec for a single quoted f- or t-string. NewlineInFormatSpec, } impl std::fmt::Display for InterpolatedStringErrorType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::UnclosedLbrace => write!(f, "expecting `}}`"), Self::InvalidConversionFlag => write!(f, "invalid conversion character"), Self::SingleRbrace => write!(f, "single `}}` is not allowed"), Self::UnterminatedString => write!(f, "unterminated string"), Self::UnterminatedTripleQuotedString => write!(f, "unterminated triple-quoted string"), Self::LambdaWithoutParentheses => { write!(f, "lambda expressions are not allowed without parentheses") } Self::ConversionFlagNotImmediatelyAfterExclamation => write!( f, "conversion type must come right after the exclamation mark" ), Self::NewlineInFormatSpec => { write!( f, "newlines are not allowed in format specifiers when using single quotes" ) } } } } /// Represents the different types of errors that can occur during parsing. #[derive(Debug, PartialEq, Eq, Clone, get_size2::GetSize)] pub enum ParseErrorType { /// An unexpected error occurred. OtherError(String), /// An error specific to stringified annotations occurred. StringAnnotationError(&'static str), /// An empty slice was found during parsing, e.g `data[]`. EmptySlice, /// An empty global names list was found during parsing. EmptyGlobalNames, /// An empty nonlocal names list was found during parsing. EmptyNonlocalNames, /// An empty delete targets list was found during parsing. EmptyDeleteTargets, /// An empty import names list was found during parsing. EmptyImportNames, /// An empty type parameter list was found during parsing. EmptyTypeParams, /// An unparenthesized named expression was found where it is not allowed. UnparenthesizedNamedExpression, /// An unparenthesized tuple expression was found where it is not allowed. UnparenthesizedTupleExpression, /// An unparenthesized generator expression was found where it is not allowed. UnparenthesizedGeneratorExpression, /// An invalid usage of a lambda expression was found. InvalidLambdaExpressionUsage, /// An invalid usage of a yield expression was found. InvalidYieldExpressionUsage, /// An invalid usage of a starred expression was found. InvalidStarredExpressionUsage, /// A star pattern was found outside a sequence pattern. InvalidStarPatternUsage, /// An underscore was used as a binding target in a match pattern. InvalidMatchPatternTarget, /// A parameter was found after a vararg. ParamAfterVarKeywordParam, /// A non-default parameter follows a default parameter. NonDefaultParamAfterDefaultParam, /// A default value was found for a `*` or `**` parameter. VarParameterWithDefault, /// A keyword argument was repeated. DuplicateKeywordArgumentError(String), /// An invalid expression was found in the assignment target. InvalidAssignmentTarget, /// An invalid expression was found in the named assignment target. InvalidNamedAssignmentTarget, /// An invalid expression was found in the annotated assignment target. InvalidAnnotatedAssignmentTarget, /// An invalid expression was found in the augmented assignment target. InvalidAugmentedAssignmentTarget, /// An invalid expression was found in the delete target. InvalidDeleteTarget, /// A positional argument was found after a keyword argument. PositionalAfterKeywordArgument, /// A positional argument was found after a keyword argument unpacking. PositionalAfterKeywordUnpacking, /// An iterable argument unpacking was found after keyword argument unpacking. InvalidArgumentUnpackingOrder, /// An invalid usage of iterable unpacking in a comprehension was found. IterableUnpackingInComprehension, /// Multiple simple statements were found in the same line without a `;` separating them. SimpleStatementsOnSameLine, /// A simple statement and a compound statement was found in the same line. SimpleAndCompoundStatementOnSameLine, /// Expected one or more keyword parameter after `*` separator. ExpectedKeywordParam, /// Expected a real number for a complex literal pattern. ExpectedRealNumber, /// Expected an imaginary number for a complex literal pattern. ExpectedImaginaryNumber, /// Expected an expression at the current parser location. ExpectedExpression, /// The parser expected a specific token that was not found. ExpectedToken { expected: TokenKind, found: TokenKind, }, /// An unexpected indentation was found during parsing. UnexpectedIndentation, /// The statement being parsed cannot be `async`. UnexpectedTokenAfterAsync(TokenKind), /// Ipython escape command was found UnexpectedIpythonEscapeCommand, /// An unexpected token was found at the end of an expression parsing UnexpectedExpressionToken, /// An f-string error containing the [`InterpolatedStringErrorType`]. FStringError(InterpolatedStringErrorType), /// A t-string error containing the [`InterpolatedStringErrorType`]. TStringError(InterpolatedStringErrorType), /// Parser encountered an error during lexing. Lexical(LexicalErrorType), /// Parser aborted because [`crate::ParseOptions::max_recursion_depth`] was exceeded. RecursionLimitExceeded, } impl ParseErrorType { pub(crate) fn from_interpolated_string_error( error: InterpolatedStringErrorType, string_kind: InterpolatedStringKind, ) -> Self { match string_kind { InterpolatedStringKind::FString => Self::FStringError(error), InterpolatedStringKind::TString => Self::TStringError(error), } } } impl std::error::Error for ParseErrorType {} impl std::fmt::Display for ParseErrorType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { ParseErrorType::OtherError(msg) => f.write_str(msg), ParseErrorType::StringAnnotationError(msg) => f.write_str(msg), ParseErrorType::ExpectedToken { found, expected } => { write!(f, "Expected {expected}, found {found}") } ParseErrorType::Lexical(lex_error) => write!(f, "{lex_error}"), ParseErrorType::SimpleStatementsOnSameLine => { f.write_str("Simple statements must be separated by newlines or semicolons") } ParseErrorType::SimpleAndCompoundStatementOnSameLine => f.write_str( "Compound statements are not allowed on the same line as simple statements", ), ParseErrorType::UnexpectedTokenAfterAsync(kind) => { write!( f, "Expected `def`, `with` or `for` to follow `async`, found {kind}", ) } ParseErrorType::InvalidArgumentUnpackingOrder => { f.write_str("Iterable argument unpacking cannot follow keyword argument unpacking") } ParseErrorType::IterableUnpackingInComprehension => { f.write_str("Iterable unpacking cannot be used in a comprehension") } ParseErrorType::UnparenthesizedNamedExpression => { f.write_str("Unparenthesized named expression cannot be used here") } ParseErrorType::UnparenthesizedTupleExpression => { f.write_str("Unparenthesized tuple expression cannot be used here") } ParseErrorType::UnparenthesizedGeneratorExpression => { f.write_str("Unparenthesized generator expression cannot be used here") } ParseErrorType::InvalidYieldExpressionUsage => { f.write_str("Yield expression cannot be used here") } ParseErrorType::InvalidLambdaExpressionUsage => { f.write_str("Lambda expression cannot be used here") } ParseErrorType::InvalidStarredExpressionUsage => { f.write_str("Starred expression cannot be used here") } ParseErrorType::PositionalAfterKeywordArgument => { f.write_str("Positional argument cannot follow keyword argument") } ParseErrorType::PositionalAfterKeywordUnpacking => { f.write_str("Positional argument cannot follow keyword argument unpacking") } ParseErrorType::EmptySlice => f.write_str("Expected index or slice expression"), ParseErrorType::EmptyGlobalNames => { f.write_str("Global statement must have at least one name") } ParseErrorType::EmptyNonlocalNames => { f.write_str("Nonlocal statement must have at least one name") } ParseErrorType::EmptyDeleteTargets => { f.write_str("Delete statement must have at least one target") } ParseErrorType::EmptyImportNames => { f.write_str("Expected one or more symbol names after import") } ParseErrorType::EmptyTypeParams => f.write_str("Type parameter list cannot be empty"), ParseErrorType::ParamAfterVarKeywordParam => { f.write_str("Parameter cannot follow var-keyword parameter") } ParseErrorType::NonDefaultParamAfterDefaultParam => { f.write_str("Parameter without a default cannot follow a parameter with a default") } ParseErrorType::ExpectedKeywordParam => { f.write_str("Expected one or more keyword parameter after `*` separator") } ParseErrorType::VarParameterWithDefault => { f.write_str("Parameter with `*` or `**` cannot have default value") } ParseErrorType::InvalidStarPatternUsage => { f.write_str("Star pattern cannot be used here") } ParseErrorType::InvalidMatchPatternTarget => f.write_str("cannot use '_' as a target"), ParseErrorType::ExpectedRealNumber => { f.write_str("Expected a real number in complex literal pattern") } ParseErrorType::ExpectedImaginaryNumber => { f.write_str("Expected an imaginary number in complex literal pattern") } ParseErrorType::ExpectedExpression => f.write_str("Expected an expression"), ParseErrorType::UnexpectedIndentation => f.write_str("Unexpected indentation"), ParseErrorType::InvalidAssignmentTarget => f.write_str("Invalid assignment target"), ParseErrorType::InvalidAnnotatedAssignmentTarget => { f.write_str("Invalid annotated assignment target") } ParseErrorType::InvalidNamedAssignmentTarget => { f.write_str("Assignment expression target must be an identifier") } ParseErrorType::InvalidAugmentedAssignmentTarget => { f.write_str("Invalid augmented assignment target") } ParseErrorType::InvalidDeleteTarget => f.write_str("Invalid delete target"), ParseErrorType::DuplicateKeywordArgumentError(arg_name) => { write!(f, "Duplicate keyword argument {arg_name:?}") } ParseErrorType::UnexpectedIpythonEscapeCommand => { f.write_str("IPython escape commands are only allowed in `Mode::Ipython`") } ParseErrorType::FStringError(fstring_error) => { write!(f, "f-string: {fstring_error}") } ParseErrorType::TStringError(tstring_error) => { write!(f, "t-string: {tstring_error}") } ParseErrorType::UnexpectedExpressionToken => { write!(f, "Unexpected token at the end of an expression") } ParseErrorType::RecursionLimitExceeded => f.write_str("Source is too deeply nested"), } } } /// Represents an error that occur during lexing and are /// returned by the `parse_*` functions in the iterator in the /// [lexer] implementation. /// /// [lexer]: crate::lexer #[derive(Debug, Clone, PartialEq)] pub struct LexicalError { /// The type of error that occurred. error: LexicalErrorType, /// The location of the error. location: TextRange, } impl LexicalError { /// Creates a new `LexicalError` with the given error type and location. pub fn new(error: LexicalErrorType, location: TextRange) -> Self { Self { error, location } } pub fn error(&self) -> &LexicalErrorType { &self.error } pub fn into_error(self) -> LexicalErrorType { self.error } pub fn location(&self) -> TextRange { self.location } } impl std::ops::Deref for LexicalError { type Target = LexicalErrorType; fn deref(&self) -> &Self::Target { self.error() } } impl std::error::Error for LexicalError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(self.error()) } } impl std::fmt::Display for LexicalError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "{} at byte offset {}", self.error(), u32::from(self.location().start()) ) } } /// Represents the different types of errors that can occur during lexing. #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)] pub enum LexicalErrorType { // TODO: Can probably be removed, the places it is used seem to be able // to use the `UnicodeError` variant instead. #[doc(hidden)] StringError, /// A string literal without the closing quote. UnclosedStringError, /// Decoding of a unicode escape sequence in a string literal failed. UnicodeError, /// Missing the `{` for unicode escape sequence. MissingUnicodeLbrace, /// Missing the `}` for unicode escape sequence. MissingUnicodeRbrace, /// The indentation is not consistent. IndentationError, /// An unrecognized token was encountered. UnrecognizedToken { tok: char }, /// An f-string error containing the [`InterpolatedStringErrorType`]. FStringError(InterpolatedStringErrorType), /// A t-string error containing the [`InterpolatedStringErrorType`]. TStringError(InterpolatedStringErrorType), /// Invalid character encountered in a byte literal. InvalidByteLiteral, /// An unexpected character was encountered after a line continuation. LineContinuationError, /// An unexpected end of file was encountered. Eof, /// An unexpected error occurred. OtherError(Box), } impl std::error::Error for LexicalErrorType {} impl LexicalErrorType { pub(crate) fn from_interpolated_string_error( error: InterpolatedStringErrorType, string_kind: InterpolatedStringKind, ) -> Self { match string_kind { InterpolatedStringKind::FString => Self::FStringError(error), InterpolatedStringKind::TString => Self::TStringError(error), } } } impl std::fmt::Display for LexicalErrorType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::StringError => write!(f, "Got unexpected string"), Self::FStringError(error) => write!(f, "f-string: {error}"), Self::TStringError(error) => write!(f, "t-string: {error}"), Self::InvalidByteLiteral => { write!(f, "bytes can only contain ASCII literal characters") } Self::UnicodeError => write!(f, "Got unexpected unicode"), Self::IndentationError => { write!(f, "unindent does not match any outer indentation level") } Self::UnrecognizedToken { tok } => { write!(f, "Got unexpected token {tok}") } Self::LineContinuationError => { write!(f, "Expected a newline after line continuation character") } Self::Eof => write!(f, "unexpected EOF while parsing"), Self::OtherError(msg) => write!(f, "{msg}"), Self::UnclosedStringError => { write!(f, "missing closing quote in string literal") } Self::MissingUnicodeLbrace => { write!(f, "Missing `{{` in Unicode escape sequence") } Self::MissingUnicodeRbrace => { write!(f, "Missing `}}` in Unicode escape sequence") } } } } /// Represents a version-related syntax error detected during parsing. /// /// An example of a version-related error is the use of a `match` statement before Python 3.10, when /// it was first introduced. See [`UnsupportedSyntaxErrorKind`] for other kinds of errors. #[derive(Debug, PartialEq, Clone, get_size2::GetSize)] pub struct UnsupportedSyntaxError { pub kind: UnsupportedSyntaxErrorKind, pub range: TextRange, /// The target [`PythonVersion`] for which this error was detected. pub target_version: PythonVersion, } impl Ranged for UnsupportedSyntaxError { fn range(&self) -> TextRange { self.range } } /// The type of tuple unpacking for [`UnsupportedSyntaxErrorKind::StarTuple`]. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, get_size2::GetSize)] pub enum StarTupleKind { Return, Yield, } /// The type of PEP 701 f-string error for [`UnsupportedSyntaxErrorKind::Pep701FString`]. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, get_size2::GetSize)] pub enum FStringKind { Backslash, Comment, LineBreak, NestedQuote, } /// The type of PEP 798 unpacking-comprehension error for /// [`UnsupportedSyntaxErrorKind::UnpackingInComprehension`]. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, get_size2::GetSize)] pub enum ComprehensionUnpackingKind { IterableInList, IterableInSet, IterableInGenerator, DictInDict, } #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, get_size2::GetSize)] pub enum UnparenthesizedNamedExprKind { SequenceIndex, SetLiteral, SetComprehension, } #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, get_size2::GetSize)] pub enum UnsupportedSyntaxErrorKind { Match, Walrus, ExceptStar, /// Represents the use of an unparenthesized named expression (`:=`) in a set literal, set /// comprehension, or sequence index before Python 3.10. /// /// ## Examples /// /// These are allowed on Python 3.10: /// /// ```python /// {x := 1, 2, 3} # set literal /// {last := x for x in range(3)} # set comprehension /// lst[x := 1] # sequence index /// ``` /// /// But on Python 3.9 the named expression needs to be parenthesized: /// /// ```python /// {(x := 1), 2, 3} # set literal /// {(last := x) for x in range(3)} # set comprehension /// lst[(x := 1)] # sequence index /// ``` /// /// However, unparenthesized named expressions are never allowed in slices: /// /// ```python /// lst[x:=1:-1] # syntax error /// lst[1:x:=1] # syntax error /// lst[1:3:x:=1] # syntax error /// /// lst[(x:=1):-1] # ok /// lst[1:(x:=1)] # ok /// lst[1:3:(x:=1)] # ok /// ``` /// /// ## References /// /// - [Python 3.10 Other Language Changes](https://docs.python.org/3/whatsnew/3.10.html#other-language-changes) UnparenthesizedNamedExpr(UnparenthesizedNamedExprKind), /// Represents the use of a parenthesized keyword argument name after Python 3.8. /// /// ## Example /// /// From [BPO 34641] it sounds like this was only accidentally supported and was removed when /// noticed. Code like this used to be valid: /// /// ```python /// f((a)=1) /// ``` /// /// After Python 3.8, you have to omit the parentheses around `a`: /// /// ```python /// f(a=1) /// ``` /// /// [BPO 34641]: https://github.com/python/cpython/issues/78822 ParenthesizedKeywordArgumentName, /// Represents the use of unparenthesized tuple unpacking in a `return` statement or `yield` /// expression before Python 3.8. /// /// ## Examples /// /// Before Python 3.8, this syntax was allowed: /// /// ```python /// rest = (4, 5, 6) /// /// def f(): /// t = 1, 2, 3, *rest /// return t /// /// def g(): /// t = 1, 2, 3, *rest /// yield t /// ``` /// /// But this was not: /// /// ```python /// rest = (4, 5, 6) /// /// def f(): /// return 1, 2, 3, *rest /// /// def g(): /// yield 1, 2, 3, *rest /// ``` /// /// Instead, parentheses were required in the `return` and `yield` cases: /// /// ```python /// rest = (4, 5, 6) /// /// def f(): /// return (1, 2, 3, *rest) /// /// def g(): /// yield (1, 2, 3, *rest) /// ``` /// /// This was reported in [BPO 32117] and updated in Python 3.8 to allow the unparenthesized /// form. /// /// [BPO 32117]: https://github.com/python/cpython/issues/76298 StarTuple(StarTupleKind), /// Represents the use of a "relaxed" [PEP 614] decorator before Python 3.9. /// /// ## Examples /// /// Prior to Python 3.9, decorators were defined to be [`dotted_name`]s, optionally followed by /// an argument list. For example: /// /// ```python /// @buttons.clicked.connect /// def foo(): ... /// /// @buttons.clicked.connect(1, 2, 3) /// def foo(): ... /// ``` /// /// As pointed out in the PEP, this prevented reasonable extensions like subscripts: /// /// ```python /// buttons = [QPushButton(f'Button {i}') for i in range(10)] /// /// @buttons[0].clicked.connect /// def spam(): ... /// ``` /// /// Python 3.9 removed these restrictions and expanded the [decorator grammar] to include any /// assignment expression and include cases like the example above. /// /// [PEP 614]: https://peps.python.org/pep-0614/ /// [`dotted_name`]: https://docs.python.org/3.8/reference/compound_stmts.html#grammar-token-dotted-name /// [decorator grammar]: https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-decorator RelaxedDecorator(RelaxedDecoratorError), /// Represents the use of a [PEP 570] positional-only parameter before Python 3.8. /// /// ## Examples /// /// Python 3.8 added the `/` syntax for marking preceding parameters as positional-only: /// /// ```python /// def foo(a, b, /, c): ... /// ``` /// /// This means `a` and `b` in this case can only be provided by position, not by name. In other /// words, this code results in a `TypeError` at runtime: /// /// ```pycon /// >>> def foo(a, b, /, c): ... /// ... /// >>> foo(a=1, b=2, c=3) /// Traceback (most recent call last): /// File "", line 1, in /// foo(a=1, b=2, c=3) /// ~~~^^^^^^^^^^^^^^^ /// TypeError: foo() got some positional-only arguments passed as keyword arguments: 'a, b' /// ``` /// /// [PEP 570]: https://peps.python.org/pep-0570/ PositionalOnlyParameter, /// Represents the use of a [type parameter list] before Python 3.12. /// /// ## Examples /// /// Before Python 3.12, generic parameters had to be declared separately using a class like /// [`typing.TypeVar`], which could then be used in a function or class definition: /// /// ```python /// from typing import Generic, TypeVar /// /// T = TypeVar("T") /// /// def f(t: T): ... /// class C(Generic[T]): ... /// ``` /// /// [PEP 695], included in Python 3.12, introduced the new type parameter syntax, which allows /// these to be written more compactly and without a separate type variable: /// /// ```python /// def f[T](t: T): ... /// class C[T]: ... /// ``` /// /// [type parameter list]: https://docs.python.org/3/reference/compound_stmts.html#type-parameter-lists /// [PEP 695]: https://peps.python.org/pep-0695/ /// [`typing.TypeVar`]: https://docs.python.org/3/library/typing.html#typevar TypeParameterList, LazyImportStatement, TypeAliasStatement, TypeParamDefault, /// Represents the use of a [PEP 701] f-string before Python 3.12. /// /// ## Examples /// /// As described in the PEP, each of these cases were invalid before Python 3.12: /// /// ```python /// # nested quotes /// f'Magic wand: { bag['wand'] }' /// /// # escape characters /// f"{'\n'.join(a)}" /// /// # comments /// f'''A complex trick: { /// bag['bag'] # recursive bags! /// }''' /// /// # line breaks in a non-triple-quoted replacement field /// f"{ /// 1 /// }" /// /// # arbitrary nesting /// f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" /// ``` /// /// These restrictions were lifted in Python 3.12, meaning that all of these examples are now /// valid. /// /// [PEP 701]: https://peps.python.org/pep-0701/ Pep701FString(FStringKind), /// Represents the use of a parenthesized `with` item before Python 3.9. /// /// ## Examples /// /// As described in [BPO 12782], `with` uses like this were not allowed on Python 3.8: /// /// ```python /// with (open("a_really_long_foo") as foo, /// open("a_really_long_bar") as bar): /// pass /// ``` /// /// because parentheses were not allowed within the `with` statement itself (see [this comment] /// in particular). However, parenthesized expressions were still allowed, including the cases /// below, so the issue can be pretty subtle and relates specifically to parenthesized items /// with `as` bindings. /// /// ```python /// with (foo, bar): ... # okay /// with ( /// open('foo.txt')) as foo: ... # also okay /// with ( /// foo, /// bar, /// baz, /// ): ... # also okay, just a tuple /// with ( /// foo, /// bar, /// baz, /// ) as tup: ... # also okay, binding the tuple /// ``` /// /// This restriction was lifted in 3.9 but formally included in the [release notes] for 3.10. /// /// [BPO 12782]: https://github.com/python/cpython/issues/56991 /// [this comment]: https://github.com/python/cpython/issues/56991#issuecomment-1093555141 /// [release notes]: https://docs.python.org/3/whatsnew/3.10.html#summary-release-highlights ParenthesizedContextManager, /// Represents the use of a [PEP 646] star expression in an index. /// /// ## Examples /// /// Before Python 3.11, star expressions were not allowed in index/subscript operations (within /// square brackets). This restriction was lifted in [PEP 646] to allow for star-unpacking of /// `typing.TypeVarTuple`s, also added in Python 3.11. As such, this is the primary motivating /// example from the PEP: /// /// ```python /// from typing import TypeVar, TypeVarTuple /// /// DType = TypeVar('DType') /// Shape = TypeVarTuple('Shape') /// /// class Array(Generic[DType, *Shape]): ... /// ``` /// /// But it applies to simple indexing as well: /// /// ```python /// vector[*x] /// array[a, *b] /// ``` /// /// [PEP 646]: https://peps.python.org/pep-0646/#change-1-star-expressions-in-indexes StarExpressionInIndex, /// Represents the use of a [PEP 646] star annotations in a function definition. /// /// ## Examples /// /// Before Python 3.11, star annotations were not allowed in function definitions. This /// restriction was lifted in [PEP 646] to allow type annotations for `typing.TypeVarTuple`, /// also added in Python 3.11: /// /// ```python /// from typing import TypeVarTuple /// /// Ts = TypeVarTuple('Ts') /// /// def foo(*args: *Ts): ... /// ``` /// /// Unlike [`UnsupportedSyntaxErrorKind::StarExpressionInIndex`], this does not include any /// other annotation positions: /// /// ```python /// x: *Ts # Syntax error /// def foo(x: *Ts): ... # Syntax error /// ``` /// /// [PEP 646]: https://peps.python.org/pep-0646/#change-2-args-as-a-typevartuple StarAnnotation, /// Represents the use of iterable or dictionary unpacking inside a comprehension before Python /// 3.15. /// /// ## Examples /// /// Before Python 3.15, comprehensions could not use iterable or dictionary unpacking in their /// element expression: /// /// ```python /// [*x for x in y] # SyntaxError /// {*x for x in y} # SyntaxError /// (*x for x in y) # SyntaxError /// {**d for d in dicts} # SyntaxError /// ``` /// /// Starting with Python 3.15, [PEP 798] allows unpacking within comprehensions: /// /// ```python /// [*x for x in y] /// {*x for x in y} /// (*x for x in y) /// {**d for d in dicts} /// ``` /// /// [PEP 798]: https://peps.python.org/pep-0798/ UnpackingInComprehension(ComprehensionUnpackingKind), /// Represents the use of tuple unpacking in a `for` statement iterator clause before Python /// 3.9. /// /// ## Examples /// /// Like [`UnsupportedSyntaxErrorKind::StarTuple`] in `return` and `yield` statements, prior to /// Python 3.9, tuple unpacking in the iterator clause of a `for` statement required /// parentheses: /// /// ```python /// # valid on Python 3.8 and earlier /// for i in (*a, *b): ... /// ``` /// /// Omitting the parentheses was invalid: /// /// ```python /// for i in *a, *b: ... # SyntaxError /// ``` /// /// This was changed as part of the [PEG parser rewrite] included in Python 3.9 but not /// documented directly until the [Python 3.11 release]. /// /// [PEG parser rewrite]: https://peps.python.org/pep-0617/ /// [Python 3.11 release]: https://docs.python.org/3/whatsnew/3.11.html#other-language-changes UnparenthesizedUnpackInFor, /// Represents the use of multiple exception names in an except clause without an `as` binding, before Python 3.14. /// /// ## Examples /// Before Python 3.14, catching multiple exceptions required /// parentheses like so: /// /// ```python /// try: /// ... /// except (ExceptionA, ExceptionB, ExceptionC): /// ... /// ``` /// /// Starting with Python 3.14, thanks to [PEP 758], it was permitted /// to omit the parentheses: /// /// ```python /// try: /// ... /// except ExceptionA, ExceptionB, ExceptionC: /// ... /// ``` /// /// However, parentheses are still required in the presence of an `as`: /// /// ```python /// try: /// ... /// except (ExceptionA, ExceptionB, ExceptionC) as e: /// ... /// ``` /// /// /// [PEP 758]: https://peps.python.org/pep-0758/ UnparenthesizedExceptionTypes, /// Represents the use of a template string (t-string) /// literal prior to the implementation of [PEP 750] /// in Python 3.14. /// /// [PEP 750]: https://peps.python.org/pep-0750/ TemplateStrings, } impl Display for UnsupportedSyntaxError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let kind = match self.kind { UnsupportedSyntaxErrorKind::Match => "Cannot use `match` statement", UnsupportedSyntaxErrorKind::Walrus => "Cannot use named assignment expression (`:=`)", UnsupportedSyntaxErrorKind::ExceptStar => "Cannot use `except*`", UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SequenceIndex, ) => "Cannot use unparenthesized assignment expression in a sequence index", UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SetLiteral, ) => "Cannot use unparenthesized assignment expression as an element in a set literal", UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SetComprehension, ) => { "Cannot use unparenthesized assignment expression as an element in a set comprehension" } UnsupportedSyntaxErrorKind::ParenthesizedKeywordArgumentName => { "Cannot use parenthesized keyword argument name" } UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Return) => { "Cannot use iterable unpacking in return statements" } UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Yield) => { "Cannot use iterable unpacking in yield expressions" } UnsupportedSyntaxErrorKind::RelaxedDecorator(relaxed_decorator_error) => { return match relaxed_decorator_error { RelaxedDecoratorError::CallExpression => { write!( f, "Cannot use a call expression in a decorator on Python {} \ unless it is the top-level expression or it occurs \ in the argument list of a top-level call expression \ (relaxed decorator syntax was {changed})", self.target_version, changed = self.kind.changed_version(), ) } RelaxedDecoratorError::Other(description) => write!( f, "Cannot use {description} outside function call arguments in a decorator on Python {} \ (syntax was {changed})", self.target_version, changed = self.kind.changed_version(), ), }; } UnsupportedSyntaxErrorKind::PositionalOnlyParameter => { "Cannot use positional-only parameter separator" } UnsupportedSyntaxErrorKind::TypeParameterList => "Cannot use type parameter lists", UnsupportedSyntaxErrorKind::LazyImportStatement => "Cannot use `lazy` import statement", UnsupportedSyntaxErrorKind::TypeAliasStatement => "Cannot use `type` alias statement", UnsupportedSyntaxErrorKind::TypeParamDefault => { "Cannot set default type for a type parameter" } UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::Backslash) => { "Cannot use an escape sequence (backslash) in f-strings" } UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::Comment) => { "Cannot use comments in f-strings" } UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::LineBreak) => { "Cannot use line breaks in non-triple-quoted f-string replacement fields" } UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::NestedQuote) => { "Cannot reuse outer quote character in f-strings" } UnsupportedSyntaxErrorKind::ParenthesizedContextManager => { "Cannot use parentheses within a `with` statement" } UnsupportedSyntaxErrorKind::StarExpressionInIndex => { "Cannot use star expression in index" } UnsupportedSyntaxErrorKind::StarAnnotation => "Cannot use star annotation", UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInList, ) => "Cannot use iterable unpacking in a list comprehension", UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInSet, ) => "Cannot use iterable unpacking in a set comprehension", UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInGenerator, ) => "Cannot use iterable unpacking in a generator expression", UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::DictInDict, ) => "Cannot use dictionary unpacking in a dict comprehension", UnsupportedSyntaxErrorKind::UnparenthesizedUnpackInFor => { "Cannot use iterable unpacking in `for` statements" } UnsupportedSyntaxErrorKind::UnparenthesizedExceptionTypes => { "Multiple exception types must be parenthesized" } UnsupportedSyntaxErrorKind::TemplateStrings => "Cannot use t-strings", }; write!( f, "{kind} on Python {} (syntax was {changed})", self.target_version, changed = self.kind.changed_version(), ) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum RelaxedDecoratorError { CallExpression, Other(&'static str), } /// Represents the kind of change in Python syntax between versions. enum Change { Added(PythonVersion), Removed(PythonVersion), } impl Display for Change { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Change::Added(version) => write!(f, "added in Python {version}"), Change::Removed(version) => write!(f, "removed in Python {version}"), } } } impl UnsupportedSyntaxErrorKind { /// Returns the Python version when the syntax associated with this error was changed, and the /// type of [`Change`] (added or removed). const fn changed_version(self) -> Change { match self { UnsupportedSyntaxErrorKind::Match => Change::Added(PythonVersion::PY310), UnsupportedSyntaxErrorKind::Walrus => Change::Added(PythonVersion::PY38), UnsupportedSyntaxErrorKind::ExceptStar => Change::Added(PythonVersion::PY311), UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr(_) => { Change::Added(PythonVersion::PY39) } UnsupportedSyntaxErrorKind::StarTuple(_) => Change::Added(PythonVersion::PY38), UnsupportedSyntaxErrorKind::RelaxedDecorator { .. } => { Change::Added(PythonVersion::PY39) } UnsupportedSyntaxErrorKind::PositionalOnlyParameter => { Change::Added(PythonVersion::PY38) } UnsupportedSyntaxErrorKind::ParenthesizedKeywordArgumentName => { Change::Removed(PythonVersion::PY38) } UnsupportedSyntaxErrorKind::TypeParameterList => Change::Added(PythonVersion::PY312), UnsupportedSyntaxErrorKind::LazyImportStatement => Change::Added(PythonVersion::PY315), UnsupportedSyntaxErrorKind::TypeAliasStatement => Change::Added(PythonVersion::PY312), UnsupportedSyntaxErrorKind::TypeParamDefault => Change::Added(PythonVersion::PY313), UnsupportedSyntaxErrorKind::Pep701FString(_) => Change::Added(PythonVersion::PY312), UnsupportedSyntaxErrorKind::ParenthesizedContextManager => { Change::Added(PythonVersion::PY39) } UnsupportedSyntaxErrorKind::StarExpressionInIndex => { Change::Added(PythonVersion::PY311) } UnsupportedSyntaxErrorKind::StarAnnotation => Change::Added(PythonVersion::PY311), UnsupportedSyntaxErrorKind::UnpackingInComprehension(_) => { Change::Added(PythonVersion::PY315) } UnsupportedSyntaxErrorKind::UnparenthesizedUnpackInFor => { Change::Added(PythonVersion::PY39) } UnsupportedSyntaxErrorKind::UnparenthesizedExceptionTypes => { Change::Added(PythonVersion::PY314) } UnsupportedSyntaxErrorKind::TemplateStrings => Change::Added(PythonVersion::PY314), } } /// Returns whether or not this kind of syntax is unsupported on `target_version`. pub(crate) fn is_unsupported(self, target_version: PythonVersion) -> bool { match self.changed_version() { Change::Added(version) => target_version < version, Change::Removed(version) => target_version >= version, } } /// Returns `true` if this kind of syntax is supported on `target_version`. pub(crate) fn is_supported(self, target_version: PythonVersion) -> bool { !self.is_unsupported(target_version) } } #[cfg(target_pointer_width = "64")] mod sizes { use crate::error::{LexicalError, LexicalErrorType}; use static_assertions::assert_eq_size; assert_eq_size!(LexicalErrorType, [u8; 24]); assert_eq_size!(LexicalError, [u8; 32]); } ast_serialize-0.13.1/crates/ruff_python_parser/src/lexer/cursor.rs000064400000000000000000000127061046102023000223430ustar00use std::str::Chars; use ruff_text_size::{TextLen, TextSize}; pub(crate) const EOF_CHAR: char = '\0'; /// A cursor represents a pointer in the source code. /// /// Based on [`rustc`'s `Cursor`](https://github.com/rust-lang/rust/blob/d1b7355d3d7b4ead564dbecb1d240fcc74fff21b/compiler/rustc_lexer/src/cursor.rs) #[derive(Clone, Debug)] pub(super) struct Cursor<'src> { /// An iterator over the [`char`]'s of the source code. chars: Chars<'src>, /// Length of the source code. This is used as a marker to indicate the start of the current /// token which is being lexed. source_length: TextSize, /// Stores the previous character for debug assertions. #[cfg(debug_assertions)] prev_char: char, } impl<'src> Cursor<'src> { pub(crate) fn new(source: &'src str) -> Self { Self { source_length: source.text_len(), chars: source.chars(), #[cfg(debug_assertions)] prev_char: EOF_CHAR, } } /// Returns the previous character. Useful for debug assertions. #[cfg(debug_assertions)] pub(super) const fn previous(&self) -> char { self.prev_char } /// Peeks the next character from the input stream without consuming it. /// Returns [`EOF_CHAR`] if the position is past the end of the file. pub(super) fn first(&self) -> char { 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(super) fn second(&self) -> char { let mut chars = self.chars.clone(); chars.next(); chars.next().unwrap_or(EOF_CHAR) } /// Returns the remaining text to lex. /// /// Use [`Cursor::text_len`] to get the length of the remaining text. pub(super) fn rest(&self) -> &'src str { self.chars.as_str() } /// Returns the length of the remaining text. /// /// Use [`Cursor::rest`] to get the remaining text. // SAFETY: The `source.text_len` call in `new` would panic if the string length is larger than a `u32`. #[expect(clippy::cast_possible_truncation)] pub(super) fn text_len(&self) -> TextSize { TextSize::new(self.chars.as_str().len() as u32) } /// Returns the length of the current token length. /// /// This is to be used after setting the start position of the token using /// [`Cursor::start_token`]. pub(super) fn token_len(&self) -> TextSize { self.source_length - self.text_len() } /// Mark the current position of the cursor as the start of the token which is going to be /// lexed. /// /// Use [`Cursor::token_len`] to get the length of the lexed token. pub(super) fn start_token(&mut self) { self.source_length = self.text_len(); } /// Returns `true` if the cursor is at the end of file. pub(super) fn is_eof(&self) -> bool { self.chars.as_str().is_empty() } /// Moves the cursor to the next character, returning the previous character. /// Returns [`None`] if there is no next character. pub(super) fn bump(&mut self) -> Option { let prev = self.chars.next()?; #[cfg(debug_assertions)] { self.prev_char = prev; } Some(prev) } pub(super) fn eat_char(&mut self, c: char) -> bool { if self.first() == c { self.bump(); true } else { false } } pub(super) fn eat_char2(&mut self, c1: char, c2: char) -> bool { let mut chars = self.chars.clone(); if chars.next() == Some(c1) && chars.next() == Some(c2) { self.bump(); self.bump(); true } else { false } } pub(super) fn eat_char3(&mut self, c1: char, c2: char, c3: char) -> bool { let mut chars = self.chars.clone(); if chars.next() == Some(c1) && chars.next() == Some(c2) && chars.next() == Some(c3) { self.bump(); self.bump(); self.bump(); true } else { false } } pub(super) fn eat_if(&mut self, mut predicate: F) -> Option where F: FnMut(char) -> bool, { if predicate(self.first()) && !self.is_eof() { self.bump() } else { None } } /// Eats symbols while predicate returns true or until the end of file is reached. #[inline] pub(super) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { // It was tried making optimized version of this for eg. line comments, but // LLVM can inline all of this and compile it down to fast iteration over bytes. while predicate(self.first()) && !self.is_eof() { self.bump(); } } /// Skips the next `count` bytes. /// /// ## Panics /// - If `count` is larger than the remaining bytes in the input stream. /// - If `count` indexes into a multi-byte character. pub(super) fn skip_bytes(&mut self, count: usize) { #[cfg(debug_assertions)] { self.prev_char = self.chars.as_str()[..count] .chars() .next_back() .unwrap_or('\0'); } self.chars = self.chars.as_str()[count..].chars(); } /// Skips to the end of the input stream. pub(super) fn skip_to_end(&mut self) { self.chars = "".chars(); } } ast_serialize-0.13.1/crates/ruff_python_parser/src/lexer/indentation.rs000064400000000000000000000114261046102023000233400ustar00use static_assertions::assert_eq_size; use std::cmp::Ordering; use std::fmt::Debug; use ruff_python_trivia::tab_offset_u32; /// The column index of an indentation. /// /// A space increments the column by one. A tab adds up to 2 (if tab size is 2) indices, but just one /// if the column isn't even. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)] pub(super) struct Column(u32); impl Column { const fn new(column: u32) -> Self { Self(column) } } /// The number of characters in an indentation. Each character accounts for 1. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)] pub(super) struct Character(u32); impl Character { const fn new(characters: u32) -> Self { Self(characters) } } /// The [Indentation](https://docs.python.org/3/reference/lexical_analysis.html#indentation) of a logical line. #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] pub(super) struct Indentation { column: Column, character: Character, } impl Indentation { const TAB_SIZE: u32 = 2; pub(super) const fn root() -> Self { Self { column: Column::new(0), character: Character::new(0), } } #[cfg(test)] const fn new(column: Column, character: Character) -> Self { Self { column, character } } #[must_use] pub(super) fn add_space(self) -> Self { Self { character: Character(self.character.0 + 1), column: Column(self.column.0 + 1), } } #[must_use] pub(super) fn add_tab(self) -> Self { Self { character: Character(self.character.0 + 1), // Compute the column index: // * Adds `TAB_SIZE` if `column` is a multiple of `TAB_SIZE` // * Rounds `column` up to the next multiple of `TAB_SIZE` otherwise. // https://github.com/python/cpython/blob/2cf99026d6320f38937257da1ab014fc873a11a6/Parser/tokenizer.c#L1818 column: Column(self.column.0 + tab_offset_u32(self.column.0, Self::TAB_SIZE)), } } pub(super) fn try_compare(self, other: Indentation) -> Result { let column_ordering = self.column.cmp(&other.column); let character_ordering = self.character.cmp(&other.character); if column_ordering == character_ordering { Ok(column_ordering) } else { Err(UnexpectedIndentation) } } } #[derive(Debug, Copy, Clone, PartialEq)] pub(super) struct UnexpectedIndentation; /// The indentations stack is used to keep track of the current indentation level /// [See Indentation](docs.python.org/3/reference/lexical_analysis.html#indentation). #[derive(Debug, Clone, Default)] pub(super) struct Indentations { stack: Vec, } impl Indentations { pub(super) fn indent(&mut self, indent: Indentation) { debug_assert_eq!(self.current().try_compare(indent), Ok(Ordering::Less)); self.stack.push(indent); } /// Dedent one level to eventually reach `new_indentation`. /// /// Returns `Err` if the `new_indentation` is greater than the new current indentation level. pub(super) fn dedent_one( &mut self, new_indentation: Indentation, ) -> Result, UnexpectedIndentation> { let previous = self.dedent(); match new_indentation.try_compare(*self.current())? { Ordering::Less | Ordering::Equal => Ok(previous), // ```python // if True: // pass // pass <- The indentation is greater than the expected indent of 0. // ``` Ordering::Greater => Err(UnexpectedIndentation), } } pub(super) fn dedent(&mut self) -> Option { self.stack.pop() } pub(super) fn current(&self) -> &Indentation { static ROOT: Indentation = Indentation::root(); self.stack.last().unwrap_or(&ROOT) } pub(crate) fn checkpoint(&self) -> IndentationsCheckpoint { IndentationsCheckpoint(self.stack.clone()) } pub(crate) fn rewind(&mut self, checkpoint: IndentationsCheckpoint) { self.stack = checkpoint.0; } } #[derive(Debug, Clone)] pub(crate) struct IndentationsCheckpoint(Vec); assert_eq_size!(Indentation, u64); #[cfg(test)] mod tests { use super::{Character, Column, Indentation}; use std::cmp::Ordering; #[test] fn indentation_try_compare() { let tab = Indentation::new(Column::new(8), Character::new(1)); assert_eq!(tab.try_compare(tab), Ok(Ordering::Equal)); let two_tabs = Indentation::new(Column::new(16), Character::new(2)); assert_eq!(two_tabs.try_compare(tab), Ok(Ordering::Greater)); assert_eq!(tab.try_compare(two_tabs), Ok(Ordering::Less)); } } ast_serialize-0.13.1/crates/ruff_python_parser/src/lexer/interpolated_string.rs000064400000000000000000000122541046102023000251040ustar00use ruff_python_ast::StringFlags; use crate::string::InterpolatedStringKind; use super::TokenFlags; /// The context representing the current f-string or t-string that the lexer is in. #[derive(Clone, Debug)] pub(crate) struct InterpolatedStringContext { flags: TokenFlags, /// The level of nesting for the lexer when it entered the current f/t-string. /// The nesting level includes all kinds of parentheses i.e., round, square, /// and curly. nesting: u32, /// The current depth of format spec for the current f/t-string. This is because /// there can be multiple format specs nested for the same f-string. /// For example, `{a:{b:{c}}}` has 3 format specs. format_spec_depth: u32, } impl InterpolatedStringContext { pub(crate) const fn new(flags: TokenFlags, nesting: u32) -> Option { if flags.is_interpolated_string() { Some(Self { flags, nesting, format_spec_depth: 0, }) } else { None } } pub(crate) fn kind(&self) -> InterpolatedStringKind { if self.flags.is_f_string() { InterpolatedStringKind::FString } else if self.flags.is_t_string() { InterpolatedStringKind::TString } else { unreachable!("Can only be constructed when f-string or t-string flag is present") } } pub(crate) const fn flags(&self) -> TokenFlags { self.flags } pub(crate) const fn nesting(&self) -> u32 { self.nesting } /// Returns the quote character for the current f-string. pub(crate) fn quote_char(&self) -> char { self.flags.quote_style().as_char() } /// Returns the triple quotes for the current f-string if it is a triple-quoted /// f-string, `None` otherwise. pub(crate) fn triple_quotes(&self) -> Option<&'static str> { if self.is_triple_quoted() { Some(self.flags.quote_str()) } else { None } } /// Returns `true` if the current f-string is a raw f-string. pub(crate) fn is_raw_string(&self) -> bool { self.flags.is_raw_string() } /// Returns `true` if the current f-string is a triple-quoted f-string. pub(crate) fn is_triple_quoted(&self) -> bool { self.flags.is_triple_quoted() } /// Calculates the number of open parentheses for the current f-string /// based on the current level of nesting for the lexer. const fn open_parentheses_count(&self, current_nesting: u32) -> u32 { current_nesting.saturating_sub(self.nesting) } /// Returns `true` if the lexer is in an f-string expression or t-string interpolation i.e., between /// two curly braces. pub(crate) const fn is_in_interpolation(&self, current_nesting: u32) -> bool { self.open_parentheses_count(current_nesting) > self.format_spec_depth } /// Returns `true` if the lexer is in a f-string format spec i.e., after a colon. pub(crate) const fn is_in_format_spec(&self, current_nesting: u32) -> bool { self.format_spec_depth > 0 && !self.is_in_interpolation(current_nesting) } /// Returns `true` if the context is in a valid position to start format spec /// i.e., at the same level of nesting as the opening parentheses token. /// Increments the format spec depth if it is. /// /// This assumes that the current character for the lexer is a colon (`:`). pub(crate) fn try_start_format_spec(&mut self, current_nesting: u32) -> bool { if self .open_parentheses_count(current_nesting) .saturating_sub(self.format_spec_depth) == 1 { self.format_spec_depth += 1; true } else { false } } /// Decrements the format spec depth if the current f-string is in a format /// spec. pub(crate) fn try_end_format_spec(&mut self, current_nesting: u32) { if self.is_in_format_spec(current_nesting) { self.format_spec_depth = self.format_spec_depth.saturating_sub(1); } } } /// The interpolated strings stack is used to keep track of all the f-strings and t-strings that the /// lexer encounters. This is necessary because f-strings and t-strings can be nested. #[derive(Debug, Default)] pub(crate) struct InterpolatedStrings { stack: Vec, } impl InterpolatedStrings { pub(crate) fn push(&mut self, context: InterpolatedStringContext) { self.stack.push(context); } pub(crate) fn pop(&mut self) -> Option { self.stack.pop() } pub(crate) fn current(&self) -> Option<&InterpolatedStringContext> { self.stack.last() } pub(crate) fn current_mut(&mut self) -> Option<&mut InterpolatedStringContext> { self.stack.last_mut() } pub(crate) fn checkpoint(&self) -> InterpolatedStringsCheckpoint { InterpolatedStringsCheckpoint(self.stack.clone()) } pub(crate) fn rewind(&mut self, checkpoint: InterpolatedStringsCheckpoint) { self.stack = checkpoint.0; } } #[derive(Debug, Clone)] pub(crate) struct InterpolatedStringsCheckpoint(Vec); ast_serialize-0.13.1/crates/ruff_python_parser/src/lexer.rs000064400000000000000000002647211046102023000210340ustar00//! This module takes care of lexing Python source text. //! //! This means source code is scanned and translated into separate tokens. The rules //! governing what is and is not a valid token are defined in the Python reference //! guide section on [Lexical analysis]. //! //! [Lexical analysis]: https://docs.python.org/3/reference/lexical_analysis.html use std::cmp::Ordering; use unicode_ident::{is_xid_continue, is_xid_start}; use ruff_python_ast::StringFlags; use ruff_python_ast::str_prefix::{AnyStringPrefix, StringLiteralPrefix}; use ruff_python_ast::token::{TokenFlags, TokenKind}; use ruff_python_trivia::is_python_whitespace; use ruff_text_size::{TextLen, TextRange, TextSize}; use crate::Mode; use crate::error::{InterpolatedStringErrorType, LexicalError, LexicalErrorType}; use crate::lexer::cursor::{Cursor, EOF_CHAR}; use crate::lexer::indentation::{Indentation, Indentations, IndentationsCheckpoint}; use crate::lexer::interpolated_string::{ InterpolatedStringContext, InterpolatedStrings, InterpolatedStringsCheckpoint, }; use crate::string::InterpolatedStringKind; mod cursor; mod indentation; mod interpolated_string; const BOM: char = '\u{feff}'; /// A lexer for Python source code. #[derive(Debug)] pub struct Lexer<'src> { /// Source code to be lexed. source: &'src str, /// A pointer to the current character of the source code which is being lexed. cursor: Cursor<'src>, /// The kind of the current token. current_kind: TokenKind, /// The range of the current token. current_range: TextRange, /// Flags for the current token. current_flags: TokenFlags, /// Lexer state. state: State, /// Represents the current level of nesting in the lexer, indicating the depth of parentheses. /// The lexer is within a parenthesized context if the value is greater than 0. nesting: u32, /// A stack of indentation representing the current indentation level. indentations: Indentations, pending_indentation: Option, /// Lexer mode. mode: Mode, /// F-string and t-string contexts. interpolated_strings: InterpolatedStrings, /// Errors encountered while lexing. errors: Vec, } impl<'src> Lexer<'src> { /// Create a new lexer for the given input source which starts at the given offset. /// /// If the start offset is greater than 0, the cursor is moved ahead that many bytes. /// This means that the input source should be the complete source code and not the /// sliced version. pub(crate) fn new(source: &'src str, mode: Mode, start_offset: TextSize) -> Self { assert!( u32::try_from(source.len()).is_ok(), "Lexer only supports files with a size up to 4GB" ); let (state, nesting) = if mode == Mode::ParenthesizedExpression { (State::Other, 1) } else { (State::AfterNewline, 0) }; let mut lexer = Lexer { source, cursor: Cursor::new(source), state, current_kind: TokenKind::EndOfFile, current_range: TextRange::empty(start_offset), current_flags: TokenFlags::empty(), nesting, indentations: Indentations::default(), pending_indentation: None, mode, interpolated_strings: InterpolatedStrings::default(), errors: Vec::new(), }; if start_offset == TextSize::new(0) { // TODO: Handle possible mismatch between BOM and explicit encoding declaration. lexer.cursor.eat_char(BOM); } else { lexer.cursor.skip_bytes(start_offset.to_usize()); } lexer } /// Returns the kind of the current token. pub(crate) const fn current_kind(&self) -> TokenKind { self.current_kind } /// Returns the range of the current token. pub(crate) const fn current_range(&self) -> TextRange { self.current_range } /// Returns the current parenthesis, bracket, and brace nesting level. #[inline] pub(crate) const fn nesting(&self) -> u32 { self.nesting } /// Returns the flags for the current token. pub(crate) const fn current_flags(&self) -> TokenFlags { self.current_flags } /// Helper function to push the given error, updating the current range with the error location /// and return the [`TokenKind::Unknown`] token. fn push_error(&mut self, error: LexicalError) -> TokenKind { self.current_range = error.location(); self.errors.push(error); TokenKind::Unknown } /// Lex the next token. pub fn next_token(&mut self) -> TokenKind { // `lex_token` marks the start on the path that lexes each token. self.current_flags = TokenFlags::empty(); self.current_kind = self.lex_token(); // For `Unknown` token, the `push_error` method updates the current range. if !matches!(self.current_kind, TokenKind::Unknown) { self.current_range = self.token_range(); } self.current_kind } fn lex_token(&mut self) -> TokenKind { if let Some(interpolated_string) = self.interpolated_strings.current() { if !interpolated_string.is_in_interpolation(self.nesting) { self.cursor.start_token(); if let Some(token) = self.lex_interpolated_string_middle_or_end() { if token.is_interpolated_string_end() { self.interpolated_strings.pop(); } return token; } } } // Return dedent tokens until the current indentation level matches the indentation of the next token. // Avoid `Option::take` here: this check runs for every token, and `take` writes `None` // even when there is no pending indentation. else if let Some(indentation) = self.pending_indentation { self.pending_indentation = None; self.cursor.start_token(); match self.indentations.current().try_compare(indentation) { Ok(Ordering::Greater) => { self.pending_indentation = Some(indentation); if self.indentations.dedent_one(indentation).is_err() { return self.push_error(LexicalError::new( LexicalErrorType::IndentationError, self.token_range(), )); } return TokenKind::Dedent; } Ok(_) => {} Err(_) => { return self.push_error(LexicalError::new( LexicalErrorType::IndentationError, self.token_range(), )); } } } if self.state.is_after_newline() { // Indent and dedent tokens include leading whitespace in their ranges. self.cursor.start_token(); if let Some(indentation) = self.eat_indentation() { return indentation; } } else { if let Err(error) = self.skip_whitespace() { return self.push_error(error); } } // Whitespace between tokens is not part of the next token's range. self.cursor.start_token(); if let Some(c) = self.cursor.bump() { if c.is_ascii() { self.consume_ascii_character(c) } else if is_unicode_identifier_start(c) { let identifier = self.lex_identifier(c); self.state = State::Other; identifier } else { self.push_error(LexicalError::new( LexicalErrorType::UnrecognizedToken { tok: c }, self.token_range(), )) } } else { // Reached the end of the file. Emit a trailing newline token if not at the beginning of a logical line, // empty the dedent stack, and finally, return the EndOfFile token. self.consume_end() } } fn eat_indentation(&mut self) -> Option { let mut indentation = Indentation::root(); loop { match self.cursor.first() { ' ' => { self.cursor.bump(); indentation = indentation.add_space(); } '\t' => { self.cursor.bump(); indentation = indentation.add_tab(); } '\\' => { self.cursor.bump(); if self.cursor.eat_char('\r') { self.cursor.eat_char('\n'); } else if !self.cursor.eat_char('\n') { return Some(self.push_error(LexicalError::new( LexicalErrorType::LineContinuationError, TextRange::at(self.offset() - '\\'.text_len(), '\\'.text_len()), ))); } if self.cursor.is_eof() { return Some(self.push_error(LexicalError::new( LexicalErrorType::Eof, self.token_range(), ))); } // test_ok backslash_continuation_indentation // if True: // \ // 1 // \ // 2 // else:\ // 3 // test_err backslash_continuation_indentation_error // if True: // 1 // \ // 2 // > Indentation cannot be split over multiple physical lines using backslashes; // > the whitespace up to the first backslash determines the indentation. // > // > https://docs.python.org/3/reference/lexical_analysis.html#indentation // // Skip whitespace after the continuation-line without accumulating it into // `indentation`. However, if the backslash is at column 0 (no prior // indentation), let the loop continue so the next line's whitespace is // accumulated normally. // // See also: https://github.com/python/cpython/issues/90249 if indentation != Indentation::root() { self.cursor.eat_while(is_python_whitespace); } } // Form feed '\x0C' => { self.cursor.bump(); indentation = Indentation::root(); } _ => break, } } // Handle indentation if this is a new, not all empty, logical line if !matches!(self.cursor.first(), '\n' | '\r' | '#' | EOF_CHAR) { self.state = State::NonEmptyLogicalLine; // Set to false so that we don't handle indentation on the next call. return self.handle_indentation(indentation); } None } fn handle_indentation(&mut self, indentation: Indentation) -> Option { match self.indentations.current().try_compare(indentation) { // Dedent Ok(Ordering::Greater) => { self.pending_indentation = Some(indentation); if self.indentations.dedent_one(indentation).is_err() { return Some(self.push_error(LexicalError::new( LexicalErrorType::IndentationError, self.token_range(), ))); } // The lexer might've eaten some whitespaces to calculate the `indentation`. For // example: // // ```py // if first: // if second: // pass // foo // # ^ // ``` // // Here, the cursor is at `^` and the `indentation` contains the whitespaces before // the `pass` token. self.cursor.start_token(); Some(TokenKind::Dedent) } Ok(Ordering::Equal) => None, // Indent Ok(Ordering::Less) => { self.indentations.indent(indentation); Some(TokenKind::Indent) } Err(_) => Some(self.push_error(LexicalError::new( LexicalErrorType::IndentationError, self.token_range(), ))), } } fn skip_whitespace(&mut self) -> Result<(), LexicalError> { let whitespace_start = if matches!(self.cursor.first(), ' ' | '\t' | '\\' | '\x0C') { self.offset() } else { return Ok(()); }; loop { match self.cursor.first() { ' ' => { self.cursor.bump(); } '\t' => { self.cursor.bump(); } '\\' => { self.cursor.bump(); if self.cursor.eat_char('\r') { self.cursor.eat_char('\n'); } else if !self.cursor.eat_char('\n') { return Err(LexicalError::new( LexicalErrorType::LineContinuationError, TextRange::at(self.offset() - '\\'.text_len(), '\\'.text_len()), )); } if self.cursor.is_eof() { return Err(LexicalError::new( LexicalErrorType::Eof, TextRange::new(whitespace_start, self.offset()), )); } } // Form feed '\x0C' => { self.cursor.bump(); } _ => break, } } Ok(()) } // Dispatch based on the given character. fn consume_ascii_character(&mut self, c: char) -> TokenKind { let token = match c { c if is_ascii_identifier_start(c) => self.lex_identifier(c), '0'..='9' => self.lex_number(c), '#' => return self.lex_comment(), '\'' | '"' => self.lex_string(c), '=' => { if self.cursor.eat_char('=') { TokenKind::EqEqual } else { self.state = State::AfterEqual; return TokenKind::Equal; } } '+' => { if self.cursor.eat_char('=') { TokenKind::PlusEqual } else { TokenKind::Plus } } '*' => { if self.cursor.eat_char('=') { TokenKind::StarEqual } else if self.cursor.eat_char('*') { if self.cursor.eat_char('=') { TokenKind::DoubleStarEqual } else { TokenKind::DoubleStar } } else { TokenKind::Star } } '%' | '!' if self.mode == Mode::Ipython && self.state.is_after_equal() && self.nesting == 0 => { self.lex_ipython_escape_command() } '%' | '!' | '?' | '/' | ';' | ',' if self.mode == Mode::Ipython && self.state.is_new_logical_line() => { self.lex_ipython_escape_command() } '?' if self.mode == Mode::Ipython => TokenKind::Question, '/' => { if self.cursor.eat_char('=') { TokenKind::SlashEqual } else if self.cursor.eat_char('/') { if self.cursor.eat_char('=') { TokenKind::DoubleSlashEqual } else { TokenKind::DoubleSlash } } else { TokenKind::Slash } } '%' => { if self.cursor.eat_char('=') { TokenKind::PercentEqual } else { TokenKind::Percent } } '|' => { if self.cursor.eat_char('=') { TokenKind::VbarEqual } else { TokenKind::Vbar } } '^' => { if self.cursor.eat_char('=') { TokenKind::CircumflexEqual } else { TokenKind::CircumFlex } } '&' => { if self.cursor.eat_char('=') { TokenKind::AmperEqual } else { TokenKind::Amper } } '-' => { if self.cursor.eat_char('=') { TokenKind::MinusEqual } else if self.cursor.eat_char('>') { TokenKind::Rarrow } else { TokenKind::Minus } } '@' => { if self.cursor.eat_char('=') { TokenKind::AtEqual } else { TokenKind::At } } '!' => { if self.cursor.eat_char('=') { TokenKind::NotEqual } else { TokenKind::Exclamation } } '~' => TokenKind::Tilde, '(' => { self.nesting += 1; TokenKind::Lpar } ')' => { self.nesting = self.nesting.saturating_sub(1); TokenKind::Rpar } '[' => { self.nesting += 1; TokenKind::Lsqb } ']' => { self.nesting = self.nesting.saturating_sub(1); TokenKind::Rsqb } '{' => { self.nesting += 1; TokenKind::Lbrace } '}' => { if let Some(interpolated_string) = self.interpolated_strings.current_mut() { if interpolated_string.nesting() == self.nesting { let error_type = LexicalErrorType::from_interpolated_string_error( InterpolatedStringErrorType::SingleRbrace, interpolated_string.kind(), ); return self.push_error(LexicalError::new(error_type, self.token_range())); } interpolated_string.try_end_format_spec(self.nesting); } self.nesting = self.nesting.saturating_sub(1); TokenKind::Rbrace } ':' => { if self .interpolated_strings .current_mut() .is_some_and(|interpolated_string| { interpolated_string.try_start_format_spec(self.nesting) }) { TokenKind::Colon } else if self.cursor.eat_char('=') { TokenKind::ColonEqual } else { TokenKind::Colon } } ';' => TokenKind::Semi, '<' => { if self.cursor.eat_char('<') { if self.cursor.eat_char('=') { TokenKind::LeftShiftEqual } else { TokenKind::LeftShift } } else if self.cursor.eat_char('=') { TokenKind::LessEqual } else { TokenKind::Less } } '>' => { if self.cursor.eat_char('>') { if self.cursor.eat_char('=') { TokenKind::RightShiftEqual } else { TokenKind::RightShift } } else if self.cursor.eat_char('=') { TokenKind::GreaterEqual } else { TokenKind::Greater } } ',' => TokenKind::Comma, '.' => { if self.cursor.first().is_ascii_digit() { self.lex_decimal_number('.') } else if self.cursor.eat_char2('.', '.') { TokenKind::Ellipsis } else { TokenKind::Dot } } '\n' => { return if self.nesting == 0 && !self.state.is_new_logical_line() { self.state = State::AfterNewline; TokenKind::Newline } else { if let Some(interpolated_string) = self.interpolated_strings.current_mut() { interpolated_string.try_end_format_spec(self.nesting); } TokenKind::NonLogicalNewline }; } '\r' => { self.cursor.eat_char('\n'); return if self.nesting == 0 && !self.state.is_new_logical_line() { self.state = State::AfterNewline; TokenKind::Newline } else { if let Some(interpolated_string) = self.interpolated_strings.current_mut() { interpolated_string.try_end_format_spec(self.nesting); } TokenKind::NonLogicalNewline }; } _ => { self.state = State::Other; return self.push_error(LexicalError::new( LexicalErrorType::UnrecognizedToken { tok: c }, self.token_range(), )); } }; self.state = State::Other; token } /// Lex an identifier. Also used for keywords and string/bytes literals with a prefix. fn lex_identifier(&mut self, first: char) -> TokenKind { // Detect potential string like rb'' b'' f'' t'' u'' r'' let quote = if let Some(prefix) = single_char_prefix(first) { match self.cursor.first() { quote @ ('\'' | '"') => { self.current_flags |= prefix; self.cursor.bump(); Some(quote) } second if let quote = self.cursor.second() && is_quote(quote) => { self.try_double_char_prefix([first, second]).then(|| { self.cursor.bump(); self.cursor.bump(); quote }) } _ => None, } } else { None }; if let Some(quote) = quote { if self.current_flags.is_interpolated_string() { if let Some(kind) = self.lex_interpolated_string_start(quote) { return kind; } } return self.lex_string(quote); } // Keep track of whether the identifier is ASCII-only or not. // // This is important because Python applies NFKC normalization to // identifiers: https://docs.python.org/3/reference/lexical_analysis.html#identifiers. // The parser needs to do the same when cooking the name, but applying // NFKC normalization unconditionally is extremely expensive. If we know // an identifier is ASCII-only (by far the most common case), the parser // can skip NFKC normalization. let mut is_ascii = first.is_ascii(); self.cursor .eat_while(|c| is_identifier_continuation(c, &mut is_ascii)); if !is_ascii { self.current_flags |= TokenFlags::NON_ASCII_NAME; return TokenKind::Name; } let text = self.token_text(); // No Python keyword is longer than eight bytes. if text.len() > 8 { return TokenKind::Name; } match text.as_bytes() { b"False" => TokenKind::False, b"None" => TokenKind::None, b"True" => TokenKind::True, b"and" => TokenKind::And, b"as" => TokenKind::As, b"assert" => TokenKind::Assert, b"async" => TokenKind::Async, b"await" => TokenKind::Await, b"break" => TokenKind::Break, b"case" => TokenKind::Case, b"class" => TokenKind::Class, b"continue" => TokenKind::Continue, b"def" => TokenKind::Def, b"del" => TokenKind::Del, b"elif" => TokenKind::Elif, b"else" => TokenKind::Else, b"except" => TokenKind::Except, b"finally" => TokenKind::Finally, b"for" => TokenKind::For, b"from" => TokenKind::From, b"global" => TokenKind::Global, b"if" => TokenKind::If, b"import" => TokenKind::Import, b"in" => TokenKind::In, b"is" => TokenKind::Is, b"lazy" => TokenKind::Lazy, b"lambda" => TokenKind::Lambda, b"match" => TokenKind::Match, b"nonlocal" => TokenKind::Nonlocal, b"not" => TokenKind::Not, b"or" => TokenKind::Or, b"pass" => TokenKind::Pass, b"raise" => TokenKind::Raise, b"return" => TokenKind::Return, b"try" => TokenKind::Try, b"type" => TokenKind::Type, b"while" => TokenKind::While, b"with" => TokenKind::With, b"yield" => TokenKind::Yield, _ => TokenKind::Name, } } /// Try lexing the double character string prefix, updating the token flags accordingly. /// Returns `true` if it matches. fn try_double_char_prefix(&mut self, value: [char; 2]) -> bool { match value { ['r', 'f' | 'F'] | ['f' | 'F', 'r'] => { self.current_flags |= TokenFlags::F_STRING | TokenFlags::RAW_STRING_LOWERCASE; } ['R', 'f' | 'F'] | ['f' | 'F', 'R'] => { self.current_flags |= TokenFlags::F_STRING | TokenFlags::RAW_STRING_UPPERCASE; } ['r', 't' | 'T'] | ['t' | 'T', 'r'] => { self.current_flags |= TokenFlags::T_STRING | TokenFlags::RAW_STRING_LOWERCASE; } ['R', 't' | 'T'] | ['t' | 'T', 'R'] => { self.current_flags |= TokenFlags::T_STRING | TokenFlags::RAW_STRING_UPPERCASE; } ['r', 'b' | 'B'] | ['b' | 'B', 'r'] => { self.current_flags |= TokenFlags::BYTE_STRING | TokenFlags::RAW_STRING_LOWERCASE; } ['R', 'b' | 'B'] | ['b' | 'B', 'R'] => { self.current_flags |= TokenFlags::BYTE_STRING | TokenFlags::RAW_STRING_UPPERCASE; } _ => return false, } true } /// Lex a f-string or t-string start token if positioned at the start of an f-string or t-string. fn lex_interpolated_string_start(&mut self, quote: char) -> Option { #[cfg(debug_assertions)] debug_assert_eq!(self.cursor.previous(), quote); if quote == '"' { self.current_flags |= TokenFlags::DOUBLE_QUOTES; } if self.cursor.eat_char2(quote, quote) { self.current_flags |= TokenFlags::TRIPLE_QUOTED_STRING; } let ftcontext = InterpolatedStringContext::new(self.current_flags, self.nesting)?; let kind = ftcontext.kind(); self.interpolated_strings.push(ftcontext); Some(kind.start_token()) } /// Lex an f-string or t-string middle or end token. fn lex_interpolated_string_middle_or_end(&mut self) -> Option { // SAFETY: Safe because the function is only called when `self.fstrings` is not empty. let interpolated_string = self.interpolated_strings.current().unwrap(); let string_kind = interpolated_string.kind(); let interpolated_flags = interpolated_string.flags(); // Check if we're at the end of the f-string. if interpolated_string.is_triple_quoted() { let quote_char = interpolated_string.quote_char(); if self.cursor.eat_char3(quote_char, quote_char, quote_char) { self.current_flags = interpolated_string.flags(); return Some(string_kind.end_token()); } } else if self.cursor.eat_char(interpolated_string.quote_char()) { self.current_flags = interpolated_string.flags(); return Some(string_kind.end_token()); } // This isn't going to change for the duration of the loop. let in_format_spec = interpolated_string.is_in_format_spec(self.nesting); let mut in_named_unicode = false; loop { match self.cursor.first() { // The condition is to differentiate between the `NUL` (`\0`) character // in the source code and the one returned by `self.cursor.first()` when // we reach the end of the source code. EOF_CHAR if self.cursor.is_eof() => { let error = if interpolated_string.is_triple_quoted() { InterpolatedStringErrorType::UnterminatedTripleQuotedString } else { InterpolatedStringErrorType::UnterminatedString }; self.nesting = interpolated_string.nesting(); self.interpolated_strings.pop(); self.current_flags |= TokenFlags::UNCLOSED_STRING; self.push_error(LexicalError::new( LexicalErrorType::from_interpolated_string_error(error, string_kind), self.token_range(), )); break; } '\n' | '\r' if !interpolated_string.is_triple_quoted() => { // https://github.com/astral-sh/ruff/issues/18632 let error_type = if in_format_spec { InterpolatedStringErrorType::NewlineInFormatSpec } else { InterpolatedStringErrorType::UnterminatedString }; self.nesting = interpolated_string.nesting(); self.interpolated_strings.pop(); self.current_flags |= TokenFlags::UNCLOSED_STRING; self.push_error(LexicalError::new( LexicalErrorType::from_interpolated_string_error(error_type, string_kind), self.token_range(), )); break; } '\\' => { self.cursor.bump(); // '\' if matches!(self.cursor.first(), '{' | '}') { // Don't consume `{` or `}` as we want them to be emitted as tokens. // They will be handled in the next iteration. continue; } else if !interpolated_string.is_raw_string() { if self.cursor.eat_char2('N', '{') { in_named_unicode = true; continue; } } // Consume the escaped character. if self.cursor.eat_char('\r') { self.cursor.eat_char('\n'); } else { self.cursor.bump(); } } quote @ ('\'' | '"') if quote == interpolated_string.quote_char() => { if let Some(triple_quotes) = interpolated_string.triple_quotes() { if self.cursor.rest().starts_with(triple_quotes) { break; } self.cursor.bump(); } else { break; } } '{' => { if self.cursor.second() == '{' && !in_format_spec { self.cursor.bump(); self.cursor.bump(); // Skip the second `{` } else { break; } } '}' => { if in_named_unicode { in_named_unicode = false; self.cursor.bump(); } else if self.cursor.second() == '}' && !in_format_spec { self.cursor.bump(); self.cursor.bump(); // Skip the second `}` } else { break; } } _ => { self.cursor.bump(); } } } let range = self.token_range(); if range.is_empty() { return None; } self.current_flags = interpolated_flags; Some(string_kind.middle_token()) } /// Lex a string literal. fn lex_string(&mut self, quote: char) -> TokenKind { #[cfg(debug_assertions)] debug_assert_eq!(self.cursor.previous(), quote); if quote == '"' { self.current_flags |= TokenFlags::DOUBLE_QUOTES; } // If the next two characters are also the quote character, then we have a triple-quoted // string; consume those two characters and ensure that we require a triple-quote to close if self.cursor.eat_char2(quote, quote) { self.current_flags |= TokenFlags::TRIPLE_QUOTED_STRING; } let quote_byte = u8::try_from(quote).expect("char that fits in u8"); if self.current_flags.is_triple_quoted() { // For triple-quoted strings, scan until we find the closing quote (ignoring escaped // quotes) or the end of the file. loop { let Some(index) = memchr::memchr(quote_byte, self.cursor.rest().as_bytes()) else { self.cursor.skip_to_end(); self.current_flags |= TokenFlags::UNCLOSED_STRING; self.push_error(LexicalError::new( LexicalErrorType::UnclosedStringError, self.token_range(), )); break; }; // Rare case: if there are an odd number of backslashes before the quote, then // the quote is escaped and we should continue scanning. let num_backslashes = self.cursor.rest().as_bytes()[..index] .iter() .rev() .take_while(|&&c| c == b'\\') .count(); // Advance the cursor past the quote and continue scanning. self.cursor.skip_bytes(index + 1); // If the character is escaped, continue scanning. if num_backslashes % 2 == 1 { continue; } // Otherwise, if it's followed by two more quotes, then we're done. if self.cursor.eat_char2(quote, quote) { break; } } } else { // For non-triple-quoted strings, scan until we find the closing quote, but end early // if we encounter a newline or the end of the file. loop { let Some(index) = memchr::memchr3(quote_byte, b'\r', b'\n', self.cursor.rest().as_bytes()) else { self.cursor.skip_to_end(); self.current_flags |= TokenFlags::UNCLOSED_STRING; self.push_error(LexicalError::new( LexicalErrorType::UnclosedStringError, self.token_range(), )); break; }; // Rare case: if there are an odd number of backslashes before the quote, then // the quote is escaped and we should continue scanning. let num_backslashes = self.cursor.rest().as_bytes()[..index] .iter() .rev() .take_while(|&&c| c == b'\\') .count(); // Skip up to the current character. self.cursor.skip_bytes(index); // Lookahead because we want to bump only if it's a quote or being escaped. let quote_or_newline = self.cursor.first(); // If the character is escaped, continue scanning. if num_backslashes % 2 == 1 { self.cursor.bump(); if quote_or_newline == '\r' { self.cursor.eat_char('\n'); } continue; } match quote_or_newline { '\r' | '\n' => { self.current_flags |= TokenFlags::UNCLOSED_STRING; self.push_error(LexicalError::new( LexicalErrorType::UnclosedStringError, self.token_range(), )); break; } ch if ch == quote => { self.cursor.bump(); break; } _ => unreachable!("memchr2 returned an index that is not a quote or a newline"), } } } TokenKind::String } /// Numeric lexing. The feast can start! fn lex_number(&mut self, first: char) -> TokenKind { if first == '0' { if self.cursor.eat_if(|c| matches!(c, 'x' | 'X')).is_some() { self.lex_number_radix(Radix::Hex) } else if self.cursor.eat_if(|c| matches!(c, 'o' | 'O')).is_some() { self.lex_number_radix(Radix::Octal) } else if self.cursor.eat_if(|c| matches!(c, 'b' | 'B')).is_some() { self.lex_number_radix(Radix::Binary) } else { self.lex_decimal_number(first) } } else { self.lex_decimal_number(first) } } /// Lex a hex/octal/decimal/binary number without a decimal point. fn lex_number_radix(&mut self, radix: Radix) -> TokenKind { #[cfg(debug_assertions)] debug_assert!(matches!( self.cursor.previous().to_ascii_lowercase(), 'x' | 'o' | 'b' )); let number = self.radix_run(radix); if !number.has_digit { let err = u64::from_str_radix("", radix.as_u32()).unwrap_err(); return self.push_error(LexicalError::new( LexicalErrorType::OtherError(format!("{err:?}").into_boxed_str()), self.token_range(), )); } TokenKind::Int } /// Lex a normal number, that is, no octal, hex or binary number. fn lex_decimal_number(&mut self, first_digit_or_dot: char) -> TokenKind { #[cfg(debug_assertions)] debug_assert!(self.cursor.previous().is_ascii_digit() || self.cursor.previous() == '.'); let start_is_zero = first_digit_or_dot == '0'; let mut integer_part = RadixRun { has_digit: first_digit_or_dot != '.', has_nonzero_digit: first_digit_or_dot != '.' && first_digit_or_dot != '0', }; if first_digit_or_dot != '.' { integer_part.has_nonzero_digit |= self.radix_run(Radix::Decimal).has_nonzero_digit; } let is_float = if first_digit_or_dot == '.' || self.cursor.eat_char('.') { if self.cursor.eat_char('_') { return self.push_error(LexicalError::new( LexicalErrorType::OtherError("Invalid Syntax".to_string().into_boxed_str()), TextRange::new(self.offset() - TextSize::new(1), self.offset()), )); } self.radix_run(Radix::Decimal); true } else { // Normal number: false }; let is_float = match self.cursor.rest().as_bytes() { [b'e' | b'E', b'0'..=b'9', ..] | [b'e' | b'E', b'-' | b'+', b'0'..=b'9', ..] => { // 'e' | 'E' self.cursor.bump(); self.cursor.eat_if(|c| matches!(c, '+' | '-')); self.radix_run(Radix::Decimal); true } _ => is_float, }; if self.cursor.eat_if(|c| matches!(c, 'j' | 'J')).is_some() { TokenKind::Complex } else if is_float { TokenKind::Float } else if start_is_zero && integer_part.has_nonzero_digit { // Leading zeros in decimal integer literals are not permitted. self.push_error(LexicalError::new( LexicalErrorType::OtherError( "Invalid decimal integer literal" .to_string() .into_boxed_str(), ), self.token_range(), )) } else { TokenKind::Int } } /// Consume a sequence of numbers with the given radix, /// the digits can be decorated with underscores /// like this: '`1_2_3_4`' == '1234' fn radix_run(&mut self, radix: Radix) -> RadixRun { let mut run = RadixRun::default(); loop { if let Some(c) = self.cursor.eat_if(|c| radix.is_digit(c)) { run.has_digit = true; run.has_nonzero_digit |= c != '0'; } // Number that contains `_` separators. else if self.cursor.first() == '_' && radix.is_digit(self.cursor.second()) { // Skip over `_` self.cursor.bump(); } else { break; } } run } /// Lex a single comment. fn lex_comment(&mut self) -> TokenKind { #[cfg(debug_assertions)] debug_assert_eq!(self.cursor.previous(), '#'); let bytes = self.cursor.rest().as_bytes(); let offset = memchr::memchr2(b'\n', b'\r', bytes).unwrap_or(bytes.len()); self.cursor.skip_bytes(offset); TokenKind::Comment } /// Lex a single IPython escape command. fn lex_ipython_escape_command(&mut self) -> TokenKind { loop { match self.cursor.first() { '\\' => { // Consume an escaped newline so it doesn't terminate the command. A normal // backslash is consumed by itself and remains part of the token range. self.cursor.bump(); self.cursor.eat_char('\r'); self.cursor.eat_char('\n'); } '\n' | '\r' | EOF_CHAR => return TokenKind::IpyEscapeCommand, _ => { self.cursor.bump(); } } } } fn consume_end(&mut self) -> TokenKind { // We reached end of file. // First, finish any unterminated interpolated-strings. while let Some(interpolated_string) = self.interpolated_strings.pop() { self.nesting = interpolated_string.nesting(); self.push_error(LexicalError::new( LexicalErrorType::from_interpolated_string_error( InterpolatedStringErrorType::UnterminatedString, interpolated_string.kind(), ), self.token_range(), )); } // Second, finish all nestings. // For Mode::ParenthesizedExpression we start with nesting level 1. // So we check if we end with that level. let init_nesting = u32::from(self.mode == Mode::ParenthesizedExpression); if self.nesting > init_nesting { // Reset the nesting to avoid going into infinite loop. self.nesting = 0; return self.push_error(LexicalError::new(LexicalErrorType::Eof, self.token_range())); } // Next, insert a trailing newline, if required. if !self.state.is_new_logical_line() { self.state = State::AfterNewline; TokenKind::Newline } // Next, flush the indentation stack to zero. else if self.indentations.dedent().is_some() { TokenKind::Dedent } else { TokenKind::EndOfFile } } /// Re-lex the [`NonLogicalNewline`] token at the given position in the context of a logical /// line. /// /// Returns a boolean indicating whether the lexer's position has changed. This could result /// into the new current token being different than the previous current token but is not /// necessarily true. If the return value is `true` then the caller is responsible for updating /// it's state accordingly. /// /// This method is a no-op if the lexer isn't in a parenthesized context. /// /// ## Explanation /// /// The lexer emits two different kinds of newline token based on the context. If it's in a /// parenthesized context, it'll emit a [`NonLogicalNewline`] token otherwise it'll emit a /// regular [`Newline`] token. Based on the type of newline token, the lexer will consume and /// emit the indentation tokens appropriately which affects the structure of the code. /// /// For example: /// ```py /// if call(foo /// def bar(): /// pass /// ``` /// /// Here, the lexer emits a [`NonLogicalNewline`] token after `foo` which means that the lexer /// doesn't emit an `Indent` token before the `def` keyword. This leads to an AST which /// considers the function `bar` as part of the module block and the `if` block remains empty. /// /// This method is to facilitate the parser if it recovers from these kind of scenarios so that /// the lexer can then re-lex a [`NonLogicalNewline`] token to a [`Newline`] token which in /// turn helps the parser to build the correct AST. /// /// In the above snippet, it would mean that this method would move the lexer back to the /// newline character after the `foo` token and emit it as a [`Newline`] token instead of /// [`NonLogicalNewline`]. This means that the next token emitted by the lexer would be an /// `Indent` token. /// /// There are cases where the lexer's position will change but the re-lexed token will remain /// the same. This is to help the parser to add the error message at an appropriate location. /// Consider the following example: /// /// ```py /// if call(foo, [a, b /// def bar(): /// pass /// ``` /// /// Here, the parser recovers from two unclosed parenthesis. The inner unclosed `[` will call /// into the re-lexing logic and reduce the nesting level from 2 to 1. And, the re-lexing logic /// will move the lexer at the newline after `b` but still emit a [`NonLogicalNewline`] token. /// Only after the parser recovers from the outer unclosed `(` does the re-lexing logic emit /// the [`Newline`] token. /// /// [`Newline`]: TokenKind::Newline /// [`NonLogicalNewline`]: TokenKind::NonLogicalNewline pub(crate) fn re_lex_logical_token( &mut self, non_logical_newline_start: Option, ) -> bool { if self.nesting == 0 { return false; } // Reduce the nesting level because the parser recovered from an error inside list parsing // i.e., it recovered from an unclosed parenthesis (`(`, `[`, or `{`). self.nesting -= 1; // The lexer can't be moved back for a triple-quoted f/t-string because the newlines are // part of the f/t-string itself, so there is no newline token to be emitted. if self.current_flags.is_triple_quoted_interpolated_string() { return false; } let Some(new_position) = non_logical_newline_start else { return false; }; // Earlier we reduced the nesting level unconditionally. Now that we know the lexer's // position is going to be moved back, the lexer needs to be put back into a // parenthesized context if the current token is a closing parenthesis. // // ```py // (a, [b, // c // ) // ``` // // Here, the parser would request to re-lex the token when it's at `)` and can recover // from an unclosed `[`. This method will move the lexer back to the newline character // after `c` which means it goes back into parenthesized context. if matches!( self.current_kind, TokenKind::Rpar | TokenKind::Rsqb | TokenKind::Rbrace ) { self.nesting += 1; } self.cursor = Cursor::new(self.source); self.cursor.skip_bytes(new_position.to_usize()); self.state = State::Other; self.next_token(); true } /// Re-lexes an unclosed string token in the context of an interpolated string element. /// /// ```py /// f'{a' /// ``` /// /// This method re-lexes the trailing `'` as the end of the f-string rather than the /// start of a new string token for better error recovery. pub(crate) fn re_lex_string_token_in_interpolation_element( &mut self, kind: InterpolatedStringKind, ) { let Some(interpolated_string) = self.interpolated_strings.current() else { return; }; let current_string_flags = self.current_flags().as_any_string_flags(); // Only unclosed strings, that have the same quote character if !matches!(self.current_kind, TokenKind::String) || !self.current_flags.is_unclosed() || current_string_flags.prefix() != AnyStringPrefix::Regular(StringLiteralPrefix::Empty) || current_string_flags.quote_style().as_char() != interpolated_string.quote_char() || current_string_flags.is_triple_quoted() != interpolated_string.is_triple_quoted() { return; } // Only if the string's first line only contains whitespace, // or ends in a comment (not `f"{"abc`) let first_line = &self.source [(self.current_range.start() + current_string_flags.quote_len()).to_usize()..]; for c in first_line.chars() { if matches!(c, '\n' | '\r' | '#') { break; } // `f'{'ab`, we want to parse `ab` as a normal string and not the closing element of the f-string if !is_python_whitespace(c) { return; } } if self.errors.last().is_some_and(|error| { error.location() == self.current_range && matches!(error.error(), LexicalErrorType::UnclosedStringError) }) { self.errors.pop(); } self.current_range = TextRange::at(self.current_range.start(), self.current_flags.quote_len()); self.current_kind = kind.end_token(); self.current_flags = TokenFlags::empty(); self.nesting = interpolated_string.nesting(); self.interpolated_strings.pop(); self.cursor = Cursor::new(self.source); self.cursor.skip_bytes(self.current_range.end().to_usize()); } /// Re-lex `r"` in a format specifier position. /// /// `r"` in a format specifier position is unlikely to be the start of a raw string. /// Instead, it's the format specifier `!r` followed by the closing quote of the f-string, /// when the `}` is missing. /// /// ```py /// f"{test!r" /// ``` /// /// This function re-lexes the `r"` as `r` (a name token). The next `next_token` call will /// return a unclosed string token for `"`, which [`Self::re_lex_string_token_in_interpolation_element`] /// can then re-lex as the end of the f-string. pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) { // Re-lex `r"` as `NAME r` followed by an unclosed string // `f"{test!r"` -> `f"{test!`, `r`, `"` if matches!(self.current_kind, TokenKind::String) && self.current_flags.is_unclosed() && self.current_flags.prefix() == AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }) { if self.errors.last().is_some_and(|error| { error.location() == self.current_range && matches!(error.error(), LexicalErrorType::UnclosedStringError) }) { self.errors.pop(); } self.current_range = TextRange::at(self.current_range.start(), 'r'.text_len()); self.current_kind = TokenKind::Name; self.current_flags = TokenFlags::empty(); self.cursor = Cursor::new(self.source); self.cursor.skip_bytes(self.current_range.end().to_usize()); } } #[inline] fn token_range(&self) -> TextRange { let end = self.offset(); let len = self.cursor.token_len(); TextRange::at(end - len, len) } #[inline] fn token_text(&self) -> &'src str { &self.source[self.token_range()] } /// Retrieves the current offset of the cursor within the source code. // SAFETY: Lexer doesn't allow files larger than 4GB #[expect(clippy::cast_possible_truncation)] #[inline] fn offset(&self) -> TextSize { TextSize::new(self.source.len() as u32) - self.cursor.text_len() } /// Creates a checkpoint to which the lexer can later return to using [`Self::rewind`]. pub(crate) fn checkpoint(&self) -> LexerCheckpoint { LexerCheckpoint { current_kind: self.current_kind, current_range: self.current_range, current_flags: self.current_flags, cursor_offset: self.offset(), state: self.state, nesting: self.nesting, indentations_checkpoint: self.indentations.checkpoint(), pending_indentation: self.pending_indentation, interpolated_strings_checkpoint: self.interpolated_strings.checkpoint(), errors_position: self.errors.len(), } } /// Restore the lexer to the given checkpoint. pub(crate) fn rewind(&mut self, checkpoint: LexerCheckpoint) { let LexerCheckpoint { current_kind, current_range, current_flags, cursor_offset, state, nesting, indentations_checkpoint, pending_indentation, interpolated_strings_checkpoint, errors_position, } = checkpoint; let mut cursor = Cursor::new(self.source); // We preserve the previous char using this method. cursor.skip_bytes(cursor_offset.to_usize()); self.current_kind = current_kind; self.current_range = current_range; self.current_flags = current_flags; self.cursor = cursor; self.state = state; self.nesting = nesting; self.indentations.rewind(indentations_checkpoint); self.pending_indentation = pending_indentation; self.interpolated_strings .rewind(interpolated_strings_checkpoint); self.errors.truncate(errors_position); } pub(crate) fn finish(self) -> Vec { self.errors } } pub(crate) struct LexerCheckpoint { current_kind: TokenKind, current_range: TextRange, current_flags: TokenFlags, cursor_offset: TextSize, state: State, nesting: u32, indentations_checkpoint: IndentationsCheckpoint, pending_indentation: Option, interpolated_strings_checkpoint: InterpolatedStringsCheckpoint, errors_position: usize, } #[derive(Copy, Clone, Debug)] enum State { /// Lexer is right at the beginning of the file or after a `Newline` token. AfterNewline, /// The lexer is at the start of a new logical line but **after** the indentation NonEmptyLogicalLine, /// Lexer is right after an equal token AfterEqual, /// Inside of a logical line Other, } impl State { const fn is_after_newline(self) -> bool { matches!(self, State::AfterNewline) } const fn is_new_logical_line(self) -> bool { matches!(self, State::AfterNewline | State::NonEmptyLogicalLine) } const fn is_after_equal(self) -> bool { matches!(self, State::AfterEqual) } } #[derive(Copy, Clone, Debug)] enum Radix { Binary, Octal, Decimal, Hex, } impl Radix { const fn as_u32(self) -> u32 { match self { Radix::Binary => 2, Radix::Octal => 8, Radix::Decimal => 10, Radix::Hex => 16, } } const fn is_digit(self, c: char) -> bool { match self { Radix::Binary => matches!(c, '0'..='1'), Radix::Octal => matches!(c, '0'..='7'), Radix::Decimal => c.is_ascii_digit(), Radix::Hex => c.is_ascii_hexdigit(), } } } #[derive(Default)] struct RadixRun { has_digit: bool, has_nonzero_digit: bool, } const fn is_quote(c: char) -> bool { matches!(c, '\'' | '"') } fn single_char_prefix(c: char) -> Option { Some(match c { 'f' | 'F' => TokenFlags::F_STRING, 't' | 'T' => TokenFlags::T_STRING, 'u' | 'U' => TokenFlags::UNICODE_STRING, 'b' | 'B' => TokenFlags::BYTE_STRING, 'r' => TokenFlags::RAW_STRING_LOWERCASE, 'R' => TokenFlags::RAW_STRING_UPPERCASE, _ => return None, }) } const fn is_ascii_identifier_start(c: char) -> bool { matches!(c, 'a'..='z' | 'A'..='Z' | '_') } // Checks if the character c is a valid starting character as described // in https://docs.python.org/3/reference/lexical_analysis.html#identifiers fn is_unicode_identifier_start(c: char) -> bool { is_xid_start(c) } /// Checks if the character c is a valid continuation character as described /// in . /// /// Additionally, this function also keeps track of whether or not the total /// identifier is ASCII-only or not by mutably altering a reference to a /// boolean value passed in. fn is_identifier_continuation(c: char, identifier_is_ascii_only: &mut bool) -> bool { // Arrange things such that ASCII codepoints never // result in the slower `is_xid_continue` getting called. if c.is_ascii() { matches!(c, 'a'..='z' | 'A'..='Z' | '_' | '0'..='9') } else { let is_continuation = is_xid_continue(c); if is_continuation { *identifier_is_ascii_only = false; } is_continuation } } /// Create a new [`Lexer`] for the given source code and [`Mode`]. pub fn lex(source: &str, mode: Mode) -> Lexer<'_> { Lexer::new(source, mode, TextSize::default()) } #[cfg(test)] mod tests { use std::fmt::Write; use insta::assert_snapshot; use ruff_python_ast::token::Token; use ruff_text_size::Ranged; use super::*; const WINDOWS_EOL: &str = "\r\n"; const MAC_EOL: &str = "\r"; const UNIX_EOL: &str = "\n"; struct LexerOutput { tokens: Vec, errors: Vec, } impl std::fmt::Display for LexerOutput { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "## Tokens")?; writeln!(f, "```\n{:#?}\n```", self.tokens)?; if !self.errors.is_empty() { writeln!(f, "## Errors")?; writeln!(f, "```\n{:#?}\n```", self.errors)?; } Ok(()) } } fn lex(source: &str, mode: Mode, start_offset: TextSize) -> LexerOutput { let mut lexer = Lexer::new(source, mode, start_offset); let mut tokens = Vec::new(); loop { let kind = lexer.next_token(); if kind.is_eof() { break; } tokens.push(Token::new( kind, lexer.current_range(), lexer.current_flags(), )); } LexerOutput { tokens, errors: lexer.finish(), } } #[track_caller] fn lex_valid(source: &str, mode: Mode, start_offset: TextSize) -> LexerOutput { let output = lex(source, mode, start_offset); if !output.errors.is_empty() { let mut message = "Unexpected lexical errors for a valid source:\n".to_string(); for error in &output.errors { writeln!(&mut message, "{error:?}").unwrap(); } writeln!(&mut message, "Source:\n{source}").unwrap(); panic!("{message}"); } output } #[track_caller] fn lex_invalid(source: &str, mode: Mode) -> LexerOutput { let output = lex(source, mode, TextSize::default()); assert!( !output.errors.is_empty(), "Expected lexer to generate at least one error for the following source:\n{source}" ); output } #[track_caller] fn lex_source(source: &str) -> LexerOutput { lex_valid(source, Mode::Module, TextSize::default()) } #[track_caller] fn lex_source_with_offset(source: &str, start_offset: TextSize) -> LexerOutput { lex_valid(source, Mode::Module, start_offset) } #[track_caller] fn lex_jupyter_source(source: &str) -> LexerOutput { lex_valid(source, Mode::Ipython, TextSize::default()) } #[test] fn bom() { let source = "\u{feff}x = 1"; assert_snapshot!(lex_source(source)); } #[test] fn bom_with_offset() { let source = "\u{feff}x + y + z"; assert_snapshot!(lex_source_with_offset(source, TextSize::new(7))); } #[test] fn bom_with_offset_edge() { // BOM offsets the first token by 3, so make sure that lexing from offset 11 (variable z) // doesn't panic. Refer https://github.com/astral-sh/ruff/issues/11731 let source = "\u{feff}x + y + z"; assert_snapshot!(lex_source_with_offset(source, TextSize::new(11))); } fn ipython_escape_command_line_continuation_eol(eol: &str) -> LexerOutput { let source = format!("%matplotlib \\{eol} --inline"); lex_jupyter_source(&source) } #[test] fn test_ipython_escape_command_line_continuation_unix_eol() { assert_snapshot!(ipython_escape_command_line_continuation_eol(UNIX_EOL)); } #[test] fn test_ipython_escape_command_line_continuation_mac_eol() { assert_snapshot!(ipython_escape_command_line_continuation_eol(MAC_EOL)); } #[test] fn test_ipython_escape_command_line_continuation_windows_eol() { assert_snapshot!(ipython_escape_command_line_continuation_eol(WINDOWS_EOL)); } fn ipython_escape_command_line_continuation_with_eol_and_eof(eol: &str) -> LexerOutput { let source = format!("%matplotlib \\{eol}"); lex_jupyter_source(&source) } #[test] fn test_ipython_escape_command_line_continuation_with_unix_eol_and_eof() { assert_snapshot!(ipython_escape_command_line_continuation_with_eol_and_eof( UNIX_EOL )); } #[test] fn test_ipython_escape_command_line_continuation_with_mac_eol_and_eof() { assert_snapshot!(ipython_escape_command_line_continuation_with_eol_and_eof( MAC_EOL )); } #[test] fn test_ipython_escape_command_line_continuation_with_windows_eol_and_eof() { assert_snapshot!(ipython_escape_command_line_continuation_with_eol_and_eof( WINDOWS_EOL )); } #[test] fn test_empty_ipython_escape_command() { let source = "%\n%%\n!\n!!\n?\n??\n/\n,\n;"; assert_snapshot!(lex_jupyter_source(source)); } #[test] fn test_ipython_escape_command() { let source = r" ?foo ??foo %timeit a = b %timeit a % 3 %matplotlib \ --inline !pwd \ && ls -a | sed 's/^/\\ /' !!cd /Users/foo/Library/Application\ Support/ /foo 1 2 ,foo 1 2 ;foo 1 2 !ls " .trim(); assert_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_snapshot!(lex_jupyter_source(source)); } #[test] fn test_ipython_escape_command_indentation() { let source = r" if True: %matplotlib \ --inline" .trim(); assert_snapshot!(lex_jupyter_source(source)); } #[test] fn test_ipython_escape_command_assignment() { let source = r" pwd = !pwd foo = %timeit a = b bar = %timeit a % 3 baz = %matplotlib \ inline qux = %foo? quux = !pwd?" .trim(); assert_snapshot!(lex_jupyter_source(source)); } fn assert_no_ipython_escape_command(tokens: &[Token]) { for token in tokens { if matches!(token.kind(), TokenKind::IpyEscapeCommand) { panic!("Unexpected escape command token at {:?}", token.range()) } } } #[test] fn test_ipython_escape_command_not_an_assignment() { let source = r" # Other escape kinds are not valid here (can't test `foo = ?str` because '?' is not a valid token) foo = /func foo = ;func foo = ,func (foo == %timeit a = b) (foo := %timeit a = b) def f(arg=%timeit a = b): pass" .trim(); let output = lex(source, Mode::Ipython, TextSize::default()); assert!(output.errors.is_empty()); assert_no_ipython_escape_command(&output.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 000 0x995DC9BBDF1939FA 0x995DC9BBDF1939FA995DC9BBDF1939FA"; assert_snapshot!(lex_source(source)); } #[test] fn test_invalid_leading_zero_small() { let source = "025"; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn test_invalid_leading_zero_big() { let source = "0252222222222222522222222222225222222222222252222222222222522222222222225222222222222"; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn test_line_comment_long() { let source = "99232 # foo".to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn test_line_comment_whitespace() { let source = "99232 # ".to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn test_line_comment_single_whitespace() { let source = "99232 # ".to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn test_line_comment_empty() { let source = "99232 #".to_string(); assert_snapshot!(lex_source(&source)); } fn comment_until_eol(eol: &str) -> LexerOutput { let source = format!("123 # Foo{eol}456"); lex_source(&source) } #[test] fn test_comment_until_unix_eol() { assert_snapshot!(comment_until_eol(UNIX_EOL)); } #[test] fn test_comment_until_mac_eol() { assert_snapshot!(comment_until_eol(MAC_EOL)); } #[test] fn test_comment_until_windows_eol() { assert_snapshot!(comment_until_eol(WINDOWS_EOL)); } #[test] fn test_assignment() { let source = r"a_variable = 99 + 2-0"; assert_snapshot!(lex_source(source)); } fn indentation_with_eol(eol: &str) -> LexerOutput { let source = format!("def foo():{eol} return 99{eol}{eol}"); lex_source(&source) } #[test] fn test_indentation_with_unix_eol() { assert_snapshot!(indentation_with_eol(UNIX_EOL)); } #[test] fn test_indentation_with_mac_eol() { assert_snapshot!(indentation_with_eol(MAC_EOL)); } #[test] fn test_indentation_with_windows_eol() { assert_snapshot!(indentation_with_eol(WINDOWS_EOL)); } fn double_dedent_with_eol(eol: &str) -> LexerOutput { let source = format!("def foo():{eol} if x:{eol}{eol} return 99{eol}{eol}"); lex_source(&source) } #[test] fn test_double_dedent_with_unix_eol() { assert_snapshot!(double_dedent_with_eol(UNIX_EOL)); } #[test] fn test_double_dedent_with_mac_eol() { assert_snapshot!(double_dedent_with_eol(MAC_EOL)); } #[test] fn test_double_dedent_with_windows_eol() { assert_snapshot!(double_dedent_with_eol(WINDOWS_EOL)); } fn double_dedent_with_tabs_eol(eol: &str) -> LexerOutput { let source = format!("def foo():{eol}\tif x:{eol}{eol}\t\t return 99{eol}{eol}"); lex_source(&source) } #[test] fn test_double_dedent_with_tabs_unix_eol() { assert_snapshot!(double_dedent_with_tabs_eol(UNIX_EOL)); } #[test] fn test_double_dedent_with_tabs_mac_eol() { assert_snapshot!(double_dedent_with_tabs_eol(MAC_EOL)); } #[test] fn test_double_dedent_with_tabs_windows_eol() { assert_snapshot!(double_dedent_with_tabs_eol(WINDOWS_EOL)); } #[test] fn dedent_after_whitespace() { let source = "\ if first: if second: pass foo "; assert_snapshot!(lex_source(source)); } fn newline_in_brackets_eol(eol: &str) -> LexerOutput { let source = r"x = [ 1,2 ,(3, 4, ), { 5, 6,\ 7}] " .replace('\n', eol); lex_source(&source) } #[test] fn test_newline_in_brackets_unix_eol() { assert_snapshot!(newline_in_brackets_eol(UNIX_EOL)); } #[test] fn test_newline_in_brackets_mac_eol() { assert_snapshot!(newline_in_brackets_eol(MAC_EOL)); } #[test] fn test_newline_in_brackets_windows_eol() { assert_snapshot!(newline_in_brackets_eol(WINDOWS_EOL)); } #[test] fn test_non_logical_newline_in_string_continuation() { let source = r"( 'a' 'b' 'c' \ 'd' )"; assert_snapshot!(lex_source(source)); } #[test] fn test_logical_newline_line_comment() { let source = "#Hello\n#World\n"; assert_snapshot!(lex_source(source)); } #[test] fn test_operators() { let source = "//////=/ /"; assert_snapshot!(lex_source(source)); } #[test] fn test_string() { let source = r#""double" 'single' 'can\'t' "\\\"" '\t\r\n' '\g' r'raw\'' '\420' '\200\0a'"#; assert_snapshot!(lex_source(source)); } fn string_continuation_with_eol(eol: &str) -> LexerOutput { let source = format!("\"abc\\{eol}def\""); lex_source(&source) } #[test] fn test_string_continuation_with_unix_eol() { assert_snapshot!(string_continuation_with_eol(UNIX_EOL)); } #[test] fn test_string_continuation_with_mac_eol() { assert_snapshot!(string_continuation_with_eol(MAC_EOL)); } #[test] fn test_string_continuation_with_windows_eol() { assert_snapshot!(string_continuation_with_eol(WINDOWS_EOL)); } #[test] fn test_escape_unicode_name() { let source = r#""\N{EN SPACE}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_non_ascii_name_flag() { let mut lexer = Lexer::new("a€\naβ = β\nascii", Mode::Module, TextSize::default()); let mut flags = Vec::new(); loop { let kind = lexer.next_token(); if kind.is_eof() { break; } if kind == TokenKind::Name { flags.push(lexer.current_flags().is_non_ascii_name()); } } assert_eq!(lexer.finish().len(), 1); assert_eq!(flags, [false, true, true, false]); } fn triple_quoted_eol(eol: &str) -> LexerOutput { let source = format!("\"\"\"{eol} test string{eol} \"\"\""); lex_source(&source) } #[test] fn test_triple_quoted_unix_eol() { assert_snapshot!(triple_quoted_eol(UNIX_EOL)); } #[test] fn test_triple_quoted_mac_eol() { assert_snapshot!(triple_quoted_eol(MAC_EOL)); } #[test] fn test_triple_quoted_windows_eol() { assert_snapshot!(triple_quoted_eol(WINDOWS_EOL)); } fn line_continuation_at_eof_after_newline(eol: &str) -> LexerOutput { let source = format!(r"\{eol}"); lex_invalid(&source, Mode::Module) } #[test] fn test_line_continuation_at_eof_after_newline_unix_eol() { assert_snapshot!(line_continuation_at_eof_after_newline(UNIX_EOL)); } #[test] fn test_line_continuation_at_eof_after_newline_mac_eol() { assert_snapshot!(line_continuation_at_eof_after_newline(MAC_EOL)); } #[test] fn test_line_continuation_at_eof_after_newline_windows_eol() { assert_snapshot!(line_continuation_at_eof_after_newline(WINDOWS_EOL)); } fn line_continuation_at_eof(eol: &str) -> LexerOutput { let source = format!(r"1, \{eol}"); lex_invalid(&source, Mode::Module) } #[test] fn test_line_continuation_at_eof_unix_eol() { assert_snapshot!(line_continuation_at_eof(UNIX_EOL)); } #[test] fn test_line_continuation_at_eof_mac_eol() { assert_snapshot!(line_continuation_at_eof(MAC_EOL)); } #[test] fn test_line_continuation_at_eof_windows_eol() { assert_snapshot!(line_continuation_at_eof(WINDOWS_EOL)); } // This test case is to just make sure that the lexer doesn't go into // infinite loop on invalid input. #[test] fn test_infinite_loop() { let source = "[1"; lex_invalid(source, Mode::Module); } /// Emoji identifiers are a non-standard python feature and are not supported by our lexer. #[test] fn test_emoji_identifier() { let source = "🐦"; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn tet_too_low_dedent() { let source = "if True: pass pass"; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn test_empty_fstrings() { let source = r#"f"" "" F"" f'' '' f"""""" f''''''"#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_prefix() { let source = r#"f"" F"" rf"" rF"" Rf"" RF"" fr"" Fr"" fR"" FR"""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring() { let source = r#"f"normal {foo} {{another}} {bar} {{{three}}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_parentheses() { let source = r#"f"{}" f"{{}}" f" {}" f"{{{}}}" f"{{{{}}}}" f" {} {{}} {{{}}} {{{{}}}} ""#; assert_snapshot!(lex_source(source)); } fn fstring_single_quote_escape_eol(eol: &str) -> LexerOutput { let source = format!(r"f'text \{eol} more text'"); lex_source(&source) } #[test] fn test_fstring_single_quote_escape_unix_eol() { assert_snapshot!(fstring_single_quote_escape_eol(UNIX_EOL)); } #[test] fn test_fstring_single_quote_escape_mac_eol() { assert_snapshot!(fstring_single_quote_escape_eol(MAC_EOL)); } #[test] fn test_fstring_single_quote_escape_windows_eol() { assert_snapshot!(fstring_single_quote_escape_eol(WINDOWS_EOL)); } #[test] fn test_fstring_escape() { let source = r#"f"\{x:\"\{x}} \"\"\ end""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_escape_braces() { let source = r"f'\{foo}' f'\\{foo}' f'\{{foo}}' f'\\{{foo}}'"; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_escape_raw() { let source = r#"rf"\{x:\"\{x}} \"\"\ end""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_named_unicode() { let source = r#"f"\N{BULLET} normal \Nope \N""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_named_unicode_raw() { let source = r#"rf"\N{BULLET} normal""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_named_expression() { let source = r#"f"{x:=10} {(x:=10)} {x,{y:=10}} {[x:=10]}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_format_spec() { let source = r#"f"{foo:} {x=!s:.3f} {x:.{y}f} {'':*^{1:{1}}} {x:{{1}.pop()}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_multiline_format_spec() { // The last f-string is invalid syntactically but we should still lex it. // Note that the `b` is a `Name` token and not a `FStringMiddle` token. let source = r"f'''__{ x:d }__''' f'''__{ x:a b c }__''' "; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_newline_format_spec() { let source = r" f'__{ x:d }__' f'__{ x:a b }__' "; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn test_fstring_conversion() { let source = r#"f"{x!s} {x=!r} {x:.3f!r} {{x!r}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_nested() { let source = r#"f"foo {f"bar {x + f"{wow}"}"} baz" f'foo {f'bar'} some {f"another"}'"#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_expression_multiline() { let source = r#"f"first { x * y } second""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_multiline() { let source = r#"f""" hello world """ f''' world hello ''' f"some {f"""multiline allowed {x}"""} string""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_comments() { let source = r#"f""" # not a comment { # comment { x } # not a comment """"#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_ipy_escape_command() { let source = r#"f"foo {!pwd} bar""#; assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_lambda_expression() { let source = r#" f"{lambda x:{x}}" f"{(lambda x:{x})}" "# .trim(); assert_snapshot!(lex_source(source)); } #[test] fn test_fstring_with_nul_char() { let source = r"f'\0'"; assert_snapshot!(lex_source(source)); } #[test] fn test_empty_tstrings() { let source = r#"t"" "" t"" t'' '' t"""""" t''''''"#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_prefix() { let source = r#"t"" t"" rt"" rt"" Rt"" Rt"" tr"" Tr"" tR"" TR"""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring() { let source = r#"t"normal {foo} {{another}} {bar} {{{three}}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_parentheses() { let source = r#"t"{}" t"{{}}" t" {}" t"{{{}}}" t"{{{{}}}}" t" {} {{}} {{{}}} {{{{}}}} ""#; assert_snapshot!(lex_source(source)); } fn tstring_single_quote_escape_eol(eol: &str) -> LexerOutput { let source = format!(r"t'text \{eol} more text'"); lex_source(&source) } #[test] fn test_tstring_single_quote_escape_unix_eol() { assert_snapshot!(tstring_single_quote_escape_eol(UNIX_EOL)); } #[test] fn test_tstring_single_quote_escape_mac_eol() { assert_snapshot!(tstring_single_quote_escape_eol(MAC_EOL)); } #[test] fn test_tstring_single_quote_escape_windows_eol() { assert_snapshot!(tstring_single_quote_escape_eol(WINDOWS_EOL)); } #[test] fn test_tstring_escape() { let source = r#"t"\{x:\"\{x}} \"\"\ end""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_escape_braces() { let source = r"t'\{foo}' t'\\{foo}' t'\{{foo}}' t'\\{{foo}}'"; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_escape_raw() { let source = r#"rt"\{x:\"\{x}} \"\"\ end""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_named_unicode() { let source = r#"t"\N{BULLET} normal \Nope \N""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_named_unicode_raw() { let source = r#"rt"\N{BULLET} normal""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_named_expression() { let source = r#"t"{x:=10} {(x:=10)} {x,{y:=10}} {[x:=10]}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_format_spec() { let source = r#"t"{foo:} {x=!s:.3f} {x:.{y}f} {'':*^{1:{1}}} {x:{{1}.pop()}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_multiline_format_spec() { // The last t-string is invalid syntactically but we should still lex it. // Note that the `b` is a `Name` token and not a `TStringMiddle` token. let source = r"t'''__{ x:d }__''' t'''__{ x:a b c }__''' "; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_newline_format_spec() { let source = r" t'__{ x:d }__' t'__{ x:a b }__' "; assert_snapshot!(lex_invalid(source, Mode::Module)); } #[test] fn test_tstring_conversion() { let source = r#"t"{x!s} {x=!r} {x:.3f!r} {{x!r}}""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_nested() { let source = r#"t"foo {t"bar {x + t"{wow}"}"} baz" t'foo {t'bar'} some {t"another"}'"#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_expression_multiline() { let source = r#"t"first { x * y } second""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_multiline() { let source = r#"t""" hello world """ t''' world hello ''' t"some {t"""multiline allowed {x}"""} string""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_comments() { let source = r#"t""" # not a comment { # comment { x } # not a comment """"#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_ipy_escape_command() { let source = r#"t"foo {!pwd} bar""#; assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_lambda_expression() { let source = r#" t"{lambda x:{x}}" t"{(lambda x:{x})}" "# .trim(); assert_snapshot!(lex_source(source)); } #[test] fn test_tstring_with_nul_char() { let source = r"t'\0'"; assert_snapshot!(lex_source(source)); } #[test] fn test_nested_t_and_fstring() { let source = r#"t"foo {f"bar {x + t"{wow}"}"} baz" f'foo {t'bar'!r} some {f"another"}'"#; assert_snapshot!(lex_source(source)); } #[test] fn test_match_softkeyword_in_notebook() { let source = r"match foo: case bar: pass"; assert_snapshot!(lex_jupyter_source(source)); } fn lex_fstring_error(source: &str) -> InterpolatedStringErrorType { let output = lex(source, Mode::Module, TextSize::default()); match output .errors .into_iter() .next() .expect("lexer should give at least one error") .into_error() { LexicalErrorType::FStringError(error) => error, err => panic!("Expected FStringError: {err:?}"), } } #[test] fn test_fstring_error() { use InterpolatedStringErrorType::{ SingleRbrace, UnterminatedString, UnterminatedTripleQuotedString, }; assert_eq!(lex_fstring_error("f'}'"), SingleRbrace); assert_eq!(lex_fstring_error("f'{{}'"), SingleRbrace); assert_eq!(lex_fstring_error("f'{{}}}'"), SingleRbrace); assert_eq!(lex_fstring_error("f'foo}'"), SingleRbrace); assert_eq!(lex_fstring_error(r"f'\u007b}'"), SingleRbrace); assert_eq!(lex_fstring_error("f'{a:b}}'"), SingleRbrace); assert_eq!(lex_fstring_error("f'{3:}}>10}'"), SingleRbrace); assert_eq!(lex_fstring_error(r"f'\{foo}\}'"), SingleRbrace); assert_eq!(lex_fstring_error(r#"f""#), UnterminatedString); assert_eq!(lex_fstring_error(r"f'"), UnterminatedString); assert_eq!(lex_fstring_error(r#"f""""#), UnterminatedTripleQuotedString); assert_eq!(lex_fstring_error(r"f'''"), UnterminatedTripleQuotedString); assert_eq!( lex_fstring_error(r#"f"""""#), UnterminatedTripleQuotedString ); assert_eq!( lex_fstring_error(r#"f""""""#), UnterminatedTripleQuotedString ); } fn lex_tstring_error(source: &str) -> InterpolatedStringErrorType { let output = lex(source, Mode::Module, TextSize::default()); match output .errors .into_iter() .next() .expect("lexer should give at least one error") .into_error() { LexicalErrorType::TStringError(error) => error, err => panic!("Expected TStringError: {err:?}"), } } #[test] fn lex_fstring_unclosed() { let source = r#"f"hello"#; assert_snapshot!(lex_invalid(source, Mode::Module), @" ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..7 (flags = DOUBLE_QUOTES | F_STRING), Newline 7..7, ] ``` ## Errors ``` [ LexicalError { error: FStringError( UnterminatedString, ), location: 2..7, }, ] ``` "); } #[test] fn lex_fstring_missing_brace() { let source = "f'{'"; assert_snapshot!(lex_invalid(source, Mode::Module), @" ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), Lbrace 2..3, String 3..4 (flags = UNCLOSED_STRING), Newline 4..4, ] ``` ## Errors ``` [ LexicalError { error: UnclosedStringError, location: 3..4, }, LexicalError { error: FStringError( UnterminatedString, ), location: 4..4, }, ] ``` "); } #[test] fn lex_fstring_missing_brace_after_format_spec() { let source = r#"f"{foo!r""#; assert_snapshot!(lex_invalid(source, Mode::Module), @" ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Name 3..6, Exclamation 6..7, String 7..9 (flags = DOUBLE_QUOTES | RAW_STRING_LOWERCASE | UNCLOSED_STRING), Newline 9..9, ] ``` ## Errors ``` [ LexicalError { error: UnclosedStringError, location: 7..9, }, LexicalError { error: FStringError( UnterminatedString, ), location: 9..9, }, ] ``` "); } #[test] fn test_tstring_error() { use InterpolatedStringErrorType::{ SingleRbrace, UnterminatedString, UnterminatedTripleQuotedString, }; assert_eq!(lex_tstring_error("t'}'"), SingleRbrace); assert_eq!(lex_tstring_error("t'{{}'"), SingleRbrace); assert_eq!(lex_tstring_error("t'{{}}}'"), SingleRbrace); assert_eq!(lex_tstring_error("t'foo}'"), SingleRbrace); assert_eq!(lex_tstring_error(r"t'\u007b}'"), SingleRbrace); assert_eq!(lex_tstring_error("t'{a:b}}'"), SingleRbrace); assert_eq!(lex_tstring_error("t'{3:}}>10}'"), SingleRbrace); assert_eq!(lex_tstring_error(r"t'\{foo}\}'"), SingleRbrace); assert_eq!(lex_tstring_error(r#"t""#), UnterminatedString); assert_eq!(lex_tstring_error(r"t'"), UnterminatedString); assert_eq!(lex_tstring_error(r#"t""""#), UnterminatedTripleQuotedString); assert_eq!(lex_tstring_error(r"t'''"), UnterminatedTripleQuotedString); assert_eq!( lex_tstring_error(r#"t"""""#), UnterminatedTripleQuotedString ); assert_eq!( lex_tstring_error(r#"t""""""#), UnterminatedTripleQuotedString ); } #[test] fn backslash_continuation_indentation() { // The first `\` has 4 spaces before it which matches the indentation level at that point, // so the whitespace before `2` is irrelevant and shouldn't produce an indentation error. // Similarly, the second `\` is also at the same indentation level, so the `3` line is also // valid. let source = r"if True: 1 \ 2 \ 3 else: pass " .to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn backslash_continuation_at_root() { // But, it's a different when the backslash character itself is at the root indentation // level. Then, the whitespaces following it determines the indentation level of the next // line, so `1` is indented with 4 spaces and `2` is indented with 8 spaces, and `3` is // indented with 4 spaces, all of which are valid. let source = r"if True: \ 1 if True: \ 2 else:\ 3 " .to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn multiple_backslash_continuation() { // It's only the first backslash character that determines the indentation level of the next // line, so all the lines after the first `\` are indented with 4 spaces, and the remaining // backslashes are just ignored and don't affect the indentation level. let source = r"if True: 1 \ \ \ \ 2 " .to_string(); assert_snapshot!(lex_source(&source)); } #[test] fn backslash_continuation_mismatch_indentation() { // Indentation doesn't match any previous indentation level let source = r"if True: 1 \ 2 " .to_string(); assert_snapshot!(lex_invalid(&source, Mode::Module)); } } ast_serialize-0.13.1/crates/ruff_python_parser/src/lib.rs000064400000000000000000000532011046102023000204500ustar00//! This crate can be used to parse Python source code into an Abstract //! Syntax Tree. //! //! ## Overview //! //! The process by which source code is parsed into an AST can be broken down //! into two general stages: [lexical analysis] and [parsing]. //! //! During lexical analysis, the source code is converted into a stream of lexical //! tokens that represent the smallest meaningful units of the language. For example, //! the source code `print("Hello world")` would _roughly_ be converted into the following //! stream of tokens: //! //! ```text //! Name("print"), LeftParen, String("Hello world"), RightParen //! ``` //! //! These tokens are then consumed by the `ruff_python_parser`, which matches them against a set of //! grammar rules to verify that the source code is syntactically valid and to construct //! an AST that represents the source code. //! //! During parsing, the `ruff_python_parser` consumes the tokens generated by the lexer and constructs //! a tree representation of the source code. The tree is made up of nodes that represent //! the different syntactic constructs of the language. If the source code is syntactically //! invalid, parsing fails and an error is returned. After a successful parse, the AST can //! be used to perform further analysis on the source code. Continuing with the example //! above, the AST generated by the `ruff_python_parser` would _roughly_ look something like this: //! //! ```text //! node: Expr { //! value: { //! node: Call { //! func: { //! node: Name { //! id: "print", //! ctx: Load, //! }, //! }, //! args: [ //! node: Constant { //! value: Str("Hello World"), //! kind: None, //! }, //! ], //! keywords: [], //! }, //! }, //! }, //!``` //! //! **Note:** The Tokens/ASTs shown above are not the exact tokens/ASTs generated by the `ruff_python_parser`. //! Refer to the [playground](https://play.ruff.rs) for the correct representation. //! //! ## Source code layout //! //! The functionality of this crate is split into several modules: //! //! - [lexer]: This module contains the lexer and is responsible for generating the tokens. //! - parser: This module contains an interface to the [Parsed] and is responsible for generating the AST. //! - mode: This module contains the definition of the different modes that the `ruff_python_parser` can be in. //! //! [lexical analysis]: https://en.wikipedia.org/wiki/Lexical_analysis //! [parsing]: https://en.wikipedia.org/wiki/Parsing //! [lexer]: crate::lexer pub use crate::error::{ InterpolatedStringErrorType, LexicalErrorType, ParseError, ParseErrorType, UnsupportedSyntaxError, UnsupportedSyntaxErrorKind, }; pub use crate::parser::ParseOptions; use crate::parser::Parser; use ruff_python_ast::token::{Token, TokenFlags, TokenKind, Tokens}; use ruff_python_ast::{ AtomicNodeIndex, Expr, Mod, ModExpression, ModModule, PySourceType, StringFlags, StringLiteral, Suite, }; use ruff_text_size::{Ranged, TextRange}; mod error; pub mod lexer; mod parser; pub mod semantic_errors; mod string; mod token_set; mod token_source; pub mod typing; /// Parse a full Python module usually consisting of multiple lines. /// /// This is a convenience function that can be used to parse a full Python program without having to /// specify the [`Mode`] or the location. It is probably what you want to use most of the time. /// /// # Example /// /// For example, parsing a simple function definition and a call to that function: /// /// ``` /// use ruff_python_parser::parse_module; /// /// let source = r#" /// def foo(): /// return 42 /// /// print(foo()) /// "#; /// /// let module = parse_module(source); /// assert!(module.is_ok()); /// ``` pub fn parse_module(source: &str) -> Result, ParseError> { Parser::new(source, ParseOptions::from(Mode::Module)) .parse() .try_into_module() .unwrap() .into_result() } /// Parses a single Python expression. /// /// This convenience function can be used to parse a single expression without having to /// specify the Mode or the location. /// /// # Example /// /// For example, parsing a single expression denoting the addition of two numbers: /// /// ``` /// use ruff_python_parser::parse_expression; /// /// let expr = parse_expression("1 + 2"); /// assert!(expr.is_ok()); /// ``` pub fn parse_expression(source: &str) -> Result, ParseError> { Parser::new(source, ParseOptions::from(Mode::Expression)) .parse() .try_into_expression() .unwrap() .into_result() } /// Parses a Python expression for the given range in the source. /// /// This function allows to specify the range of the expression in the source code, other than /// that, it behaves exactly like [`parse_expression`]. /// /// # Example /// /// Parsing one of the numeric literal which is part of an addition expression: /// /// ``` /// use ruff_python_parser::parse_expression_range; /// # use ruff_text_size::{TextRange, TextSize}; /// /// let parsed = parse_expression_range("11 + 22 + 33", TextRange::new(TextSize::new(5), TextSize::new(7))); /// assert!(parsed.is_ok()); /// ``` pub fn parse_expression_range( source: &str, range: TextRange, ) -> Result, ParseError> { let source = &source[..range.end().to_usize()]; Parser::new_starts_at(source, range.start(), ParseOptions::from(Mode::Expression)) .parse() .try_into_expression() .unwrap() .into_result() } /// Parses a Python expression as if it is parenthesized. /// /// It behaves similarly to [`parse_expression_range`] but allows what would be valid within parenthesis /// /// # Example /// /// Parsing an expression that would be valid within parenthesis: /// /// ``` /// use ruff_python_parser::parse_parenthesized_expression_range; /// # use ruff_text_size::{TextRange, TextSize}; /// /// let parsed = parse_parenthesized_expression_range("'''\n int | str'''", TextRange::new(TextSize::new(3), TextSize::new(14))); /// assert!(parsed.is_ok()); pub fn parse_parenthesized_expression_range( source: &str, range: TextRange, ) -> Result, ParseError> { let source = &source[..range.end().to_usize()]; let parsed = Parser::new_starts_at( source, range.start(), ParseOptions::from(Mode::ParenthesizedExpression), ) .parse(); parsed.try_into_expression().unwrap().into_result() } /// Parses a Python expression from a string annotation. /// /// # Example /// /// Parsing a string annotation: /// /// ``` /// use ruff_python_parser::parse_string_annotation; /// use ruff_python_ast::{StringLiteral, StringLiteralFlags, AtomicNodeIndex}; /// use ruff_text_size::{TextRange, TextSize}; /// /// let string = StringLiteral { /// value: "'''\n int | str'''".to_string().into_boxed_str(), /// flags: StringLiteralFlags::empty(), /// range: TextRange::new(TextSize::new(0), TextSize::new(16)), /// node_index: AtomicNodeIndex::NONE /// }; /// let parsed = parse_string_annotation("'''\n int | str'''", &string); /// assert!(!parsed.is_ok()); /// ``` pub fn parse_string_annotation( source: &str, string: &StringLiteral, ) -> Result, ParseError> { let range = string .range() .add_start(string.flags.opener_len()) .sub_end(string.flags.closer_len()); let source = &source[..range.end().to_usize()]; if string.flags.is_triple_quoted() { parse_parenthesized_expression_range(source, range) } else { parse_expression_range(source, range) } } /// Parse the given Python source code using the specified [`ParseOptions`]. /// /// This function is the most general function to parse Python code. Based on the [`Mode`] supplied /// via the [`ParseOptions`], it can be used to parse a single expression, a full Python program, /// an interactive expression or a Python program containing IPython escape commands. /// /// # Example /// /// If we want to parse a simple expression, we can use the [`Mode::Expression`] mode during /// parsing: /// /// ``` /// use ruff_python_parser::{parse, Mode, ParseOptions}; /// /// let parsed = parse("1 + 2", ParseOptions::from(Mode::Expression)); /// assert!(parsed.is_ok()); /// ``` /// /// Alternatively, we can parse a full Python program consisting of multiple lines: /// /// ``` /// use ruff_python_parser::{parse, Mode, ParseOptions}; /// /// let source = r#" /// class Greeter: /// /// def greet(self): /// print("Hello, world!") /// "#; /// let parsed = parse(source, ParseOptions::from(Mode::Module)); /// assert!(parsed.is_ok()); /// ``` /// /// Additionally, we can parse a Python program containing IPython escapes: /// /// ``` /// use ruff_python_parser::{parse, Mode, ParseOptions}; /// /// let source = r#" /// %timeit 1 + 2 /// ?str.replace /// !ls /// "#; /// let parsed = parse(source, ParseOptions::from(Mode::Ipython)); /// assert!(parsed.is_ok()); /// ``` pub fn parse(source: &str, options: ParseOptions) -> Result, ParseError> { parse_unchecked(source, options).into_result() } /// Parse the given Python source code using the specified [`ParseOptions`]. /// /// This is same as the [`parse`] function except that it doesn't check for any [`ParseError`] /// and returns the [`Parsed`] as is. pub fn parse_unchecked(source: &str, options: ParseOptions) -> Parsed { Parser::new(source, options).parse() } /// Parse the given Python source code using the specified [`PySourceType`]. pub fn parse_unchecked_source(source: &str, source_type: PySourceType) -> Parsed { // SAFETY: Safe because `PySourceType` always parses to a `ModModule` Parser::new(source, ParseOptions::from(source_type)) .parse() .try_into_module() .unwrap() } /// Parses each `range` of `source` as an independent module and concatenates the results into a /// single [`Parsed`] whose nodes keep their offsets into `source`. /// /// This validates sources such as Jupyter notebooks, where each cell must be syntactically valid on /// its own while later cells can still reference earlier definitions. /// The `ranges` must be ordered and non-overlapping. /// /// Consecutive ranges must be separated by a single-byte `\n`: each range ends just before the /// separator and the next range starts just after it, as Ruff's notebook cells are. A syntax error /// anchored at a cell's trailing offset then lands on that separator, the cell's own last line, so /// it is attributed to that cell rather than to the following one. pub fn parse_cells_unchecked( source: &str, ranges: impl IntoIterator, options: &ParseOptions, ) -> Parsed { let mut ranges = ranges.into_iter().peekable(); let mut body = Suite::new(); let mut tokens = Vec::new(); let mut errors = Vec::new(); let mut unsupported_syntax_errors = Vec::new(); let mut module_range: Option = None; while let Some(range) = ranges.next() { if let Some(previous) = module_range { assert!(previous.end() <= range.start()); } // The cell is lexed from `range.start()`, so the slice must keep the leading text to // preserve absolute offsets into the concatenated source. let cell_source = &source[TextRange::up_to(range.end())]; let Parsed { syntax, tokens: cell_tokens, errors: cell_errors, unsupported_syntax_errors: cell_unsupported_syntax_errors, } = Parser::new_starts_at(cell_source, range.start(), options.clone()) .parse() .try_into_module() .expect("module options should parse into a module"); body.extend(syntax.body); tokens.extend(cell_tokens); errors.extend(cell_errors); unsupported_syntax_errors.extend(cell_unsupported_syntax_errors); // Each range excludes its trailing `\n` separator (see the doc comment above), leaving a // one-byte gap in the token stream. Cover it with a `NonLogicalNewline` so token-based // checks don't treat the separator as another logical line terminator. The final cell's // separator is the file-final newline and is deliberately left uncovered. if let Some(next) = ranges.peek() { let separator = TextRange::new(range.end(), next.start()); assert_eq!(&source[separator], "\n"); tokens.push(Token::new( TokenKind::NonLogicalNewline, separator, TokenFlags::empty(), )); } module_range = Some(match module_range { Some(previous) => TextRange::new(previous.start(), range.end()), None => range, }); } body.shrink_to_fit(); tokens.shrink_to_fit(); errors.shrink_to_fit(); unsupported_syntax_errors.shrink_to_fit(); Parsed { syntax: ModModule { node_index: AtomicNodeIndex::NONE, range: module_range.unwrap_or_default(), body, }, tokens: Tokens::new(tokens), errors, unsupported_syntax_errors, } } /// Represents the parsed source code. #[derive(Debug, PartialEq, Clone, get_size2::GetSize)] pub struct Parsed { syntax: T, tokens: Tokens, errors: Vec, unsupported_syntax_errors: Vec, } impl Parsed { /// Returns the syntax node represented by this parsed output. pub fn syntax(&self) -> &T { &self.syntax } /// Returns all the tokens for the parsed output. pub fn tokens(&self) -> &Tokens { &self.tokens } /// Returns a list of syntax errors found during parsing. pub fn errors(&self) -> &[ParseError] { &self.errors } /// Returns a list of version-related syntax errors found during parsing. pub fn unsupported_syntax_errors(&self) -> &[UnsupportedSyntaxError] { &self.unsupported_syntax_errors } /// Consumes the [`Parsed`] output and returns the contained syntax node. pub fn into_syntax(self) -> T { self.syntax } /// Consumes the [`Parsed`] output and returns a list of syntax errors found during parsing. fn into_errors(self) -> Vec { self.errors } /// Returns `true` if the parsed source code is valid i.e., it has no [`ParseError`]s. /// /// Note that this does not include version-related [`UnsupportedSyntaxError`]s. /// /// See [`Parsed::has_no_syntax_errors`] for a version that takes these into account. pub fn has_valid_syntax(&self) -> bool { self.errors.is_empty() } /// Returns `true` if the parsed source code is invalid i.e., it has [`ParseError`]s. /// /// Note that this does not include version-related [`UnsupportedSyntaxError`]s. /// /// See [`Parsed::has_no_syntax_errors`] for a version that takes these into account. pub fn has_invalid_syntax(&self) -> bool { !self.has_valid_syntax() } /// Returns `true` if the parsed source code does not contain any [`ParseError`]s *or* /// [`UnsupportedSyntaxError`]s. /// /// See [`Parsed::has_valid_syntax`] for a version specific to [`ParseError`]s. pub fn has_no_syntax_errors(&self) -> bool { self.has_valid_syntax() && self.unsupported_syntax_errors.is_empty() } /// Returns `true` if the parsed source code contains any [`ParseError`]s *or* /// [`UnsupportedSyntaxError`]s. /// /// See [`Parsed::has_invalid_syntax`] for a version specific to [`ParseError`]s. pub fn has_syntax_errors(&self) -> bool { !self.has_no_syntax_errors() } /// Returns the [`Parsed`] output as a [`Result`], returning [`Ok`] if it has no syntax errors, /// or [`Err`] containing the first [`ParseError`] encountered. /// /// Note that any [`unsupported_syntax_errors`](Parsed::unsupported_syntax_errors) will not /// cause [`Err`] to be returned. pub fn as_result(&self) -> Result<&Parsed, &[ParseError]> { if self.has_valid_syntax() { Ok(self) } else { Err(&self.errors) } } /// Consumes the [`Parsed`] output and returns a [`Result`] which is [`Ok`] if it has no syntax /// errors, or [`Err`] containing the first [`ParseError`] encountered. /// /// Note that any [`unsupported_syntax_errors`](Parsed::unsupported_syntax_errors) will not /// cause [`Err`] to be returned. fn into_result(self) -> Result, ParseError> { if self.has_valid_syntax() { Ok(self) } else { Err(self.into_errors().into_iter().next().unwrap()) } } } impl Parsed { /// Attempts to convert the [`Parsed`] into a [`Parsed`]. /// /// This method checks if the `syntax` field of the output is a [`Mod::Module`]. If it is, the /// method returns [`Some(Parsed)`] with the contained module. Otherwise, it /// returns [`None`]. /// /// [`Some(Parsed)`]: Some pub fn try_into_module(self) -> Option> { match self.syntax { Mod::Module(module) => Some(Parsed { syntax: module, tokens: self.tokens, errors: self.errors, unsupported_syntax_errors: self.unsupported_syntax_errors, }), Mod::Expression(_) => None, } } /// Attempts to convert the [`Parsed`] into a [`Parsed`]. /// /// This method checks if the `syntax` field of the output is a [`Mod::Expression`]. If it is, /// the method returns [`Some(Parsed)`] with the contained expression. /// Otherwise, it returns [`None`]. /// /// [`Some(Parsed)`]: Some fn try_into_expression(self) -> Option> { match self.syntax { Mod::Module(_) => None, Mod::Expression(expression) => Some(Parsed { syntax: expression, tokens: self.tokens, errors: self.errors, unsupported_syntax_errors: self.unsupported_syntax_errors, }), } } } impl Parsed { /// Returns the module body contained in this parsed output as a [`Suite`]. pub fn suite(&self) -> &Suite { &self.syntax.body } /// Consumes the [`Parsed`] output and returns the module body as a [`Suite`]. pub fn into_suite(self) -> Suite { self.syntax.body } } impl Parsed { /// Returns the expression contained in this parsed output. pub fn expr(&self) -> &Expr { &self.syntax.body } /// Returns a mutable reference to the expression contained in this parsed output. fn expr_mut(&mut self) -> &mut Expr { &mut self.syntax.body } /// Consumes the [`Parsed`] output and returns the contained [`Expr`]. pub fn into_expr(self) -> Expr { *self.syntax.body } } /// Control in the different modes by which a source file can be parsed. /// /// The mode argument specifies in what way code must be parsed. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Mode { /// The code consists of a sequence of statements. Module, /// The code consists of a single expression. Expression, /// The code consists of a single expression and is parsed as if it is parenthesized. The parentheses themselves aren't required. /// This allows for having valid multiline expression without the need of parentheses /// and is specifically useful for parsing string annotations. ParenthesizedExpression, /// The code consists of a sequence of statements which can include the /// escape commands that are part of IPython syntax. /// /// ## Supported escape commands: /// /// - [Magic command system] which is limited to [line magics] and can start /// with `?` or `??`. /// - [Dynamic object information] which can start with `?` or `??`. /// - [System shell access] which can start with `!` or `!!`. /// - [Automatic parentheses and quotes] which can start with `/`, `;`, or `,`. /// /// [Magic command system]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#magic-command-system /// [line magics]: https://ipython.readthedocs.io/en/stable/interactive/magics.html#line-magics /// [Dynamic object information]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#dynamic-object-information /// [System shell access]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#system-shell-access /// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes Ipython, } impl std::str::FromStr for Mode { type Err = ModeParseError; fn from_str(s: &str) -> Result { match s { "exec" | "single" => Ok(Mode::Module), "eval" => Ok(Mode::Expression), "ipython" => Ok(Mode::Ipython), _ => Err(ModeParseError), } } } /// A type that can be represented as [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::Ipython, } } } /// Returned when a given mode is not valid. #[derive(Debug)] pub struct ModeParseError; impl std::fmt::Display for ModeParseError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, r#"mode must be "exec", "eval", "ipython", or "single""#) } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/expression.rs000064400000000000000000003650011046102023000234010ustar00use std::ops::Deref; use bitflags::bitflags; use rustc_hash::{FxBuildHasher, FxHashSet}; use thin_vec::ThinVec; use ruff_python_ast::name::Name; use ruff_python_ast::token::TokenKind; use ruff_python_ast::{ self as ast, AnyStringFlags, AtomicNodeIndex, BoolOp, CmpOp, ConversionFlag, Expr, ExprContext, FString, InterpolatedStringElement, InterpolatedStringElements, IpyEscapeKind, Number, Operator, OperatorPrecedence, StringFlags, TString, UnaryOp, }; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use crate::error::{ ComprehensionUnpackingKind, FStringKind, StarTupleKind, UnparenthesizedNamedExprKind, }; use crate::parser::progress::ParserProgress; use crate::parser::{FunctionKind, IpyEscapeContext, Parser, helpers}; use crate::string::{ InterpolatedStringKind, StringType, parse_interpolated_string_literal_element, parse_string_literal, }; use crate::token_set::TokenSet; use crate::{ InterpolatedStringErrorType, Mode, ParseErrorType, UnsupportedSyntaxError, UnsupportedSyntaxErrorKind, }; use super::{InterpolatedStringElementsKind, Parenthesized, RecoveryContextKind}; /// A token set consisting of a newline or end of file. const NEWLINE_EOF_SET: TokenSet = TokenSet::new([TokenKind::Newline, TokenKind::EndOfFile]); /// Tokens that represents a literal expression. const LITERAL_SET: TokenSet = TokenSet::new([ TokenKind::Int, TokenKind::Float, TokenKind::Complex, TokenKind::String, TokenKind::Ellipsis, TokenKind::True, TokenKind::False, TokenKind::None, ]); /// Tokens that represents either an expression or the start of one. pub(super) const EXPR_SET: TokenSet = TokenSet::new([ TokenKind::Name, TokenKind::Minus, TokenKind::Plus, TokenKind::Tilde, TokenKind::Star, TokenKind::DoubleStar, TokenKind::Lpar, TokenKind::Lbrace, TokenKind::Lsqb, TokenKind::Lambda, TokenKind::Await, TokenKind::Not, TokenKind::Yield, TokenKind::FStringStart, TokenKind::TStringStart, TokenKind::IpyEscapeCommand, ]) .union(LITERAL_SET); /// Tokens that can appear after an expression. const END_EXPR_SET: TokenSet = TokenSet::new([ // Ex) `expr` (without a newline) TokenKind::EndOfFile, // Ex) `expr` TokenKind::Newline, // Ex) `expr;` TokenKind::Semi, // Ex) `data[expr:]` // Ex) `def foo() -> expr:` // Ex) `{expr: expr}` TokenKind::Colon, // Ex) `{expr}` TokenKind::Rbrace, // Ex) `[expr]` TokenKind::Rsqb, // Ex) `(expr)` TokenKind::Rpar, // Ex) `expr,` TokenKind::Comma, // Ex) // // if True: // expr // # <- Dedent // x TokenKind::Dedent, // Ex) `expr if expr else expr` TokenKind::If, TokenKind::Else, // Ex) `with expr as target:` // Ex) `except expr as NAME:` TokenKind::As, // Ex) `raise expr from expr` TokenKind::From, // Ex) `[expr for expr in iter]` TokenKind::For, // Ex) `[expr async for expr in iter]` TokenKind::Async, // Ex) `expr in expr` TokenKind::In, // Ex) `name: expr = expr` // Ex) `f"{expr=}"` TokenKind::Equal, // Ex) `f"{expr!s}"` TokenKind::Exclamation, ]); /// Tokens that can appear at the end of a sequence. const END_SEQUENCE_SET: TokenSet = END_EXPR_SET.remove(TokenKind::Comma); impl<'src> Parser<'src> { /// Returns `true` if the parser is at a name or keyword (including soft keyword) token. pub(super) fn at_name_or_keyword(&self) -> bool { self.at(TokenKind::Name) || self.current_token_kind().is_keyword() } /// Returns `true` if the parser is at a name or soft keyword token. pub(super) fn at_name_or_soft_keyword(&self) -> bool { self.at(TokenKind::Name) || self.at_soft_keyword() } /// Returns `true` if the parser is at a soft keyword token. pub(super) fn at_soft_keyword(&self) -> bool { self.current_token_kind().is_soft_keyword() } /// Returns `true` if the current token is the start of an expression. pub(super) fn at_expr(&self) -> bool { self.at_ts(EXPR_SET) || self.at_soft_keyword() } /// Returns `true` if the current token ends a sequence. pub(super) fn at_sequence_end(&self) -> bool { self.at_ts(END_SEQUENCE_SET) } /// Parses every Python expression. /// /// Matches the `expressions` rule in the [Python grammar]. The [`ExpressionContext`] can be /// used to match the `star_expressions` rule. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html pub(super) fn parse_expression_list(&mut self, context: ExpressionContext) -> ParsedExpr { let start = self.node_start(); let parsed_expr = self.parse_conditional_expression_or_higher_impl(context); if self.at(TokenKind::Comma) { let subsequent_context = context.disallow_yield_expressions(); Expr::Tuple(self.parse_tuple_expression( parsed_expr.expr, start, Parenthesized::No, |p| p.parse_conditional_expression_or_higher_impl(subsequent_context), )) .into() } else { parsed_expr } } /// Parses every Python expression except unparenthesized tuple. /// /// Matches the `named_expression` rule in the [Python grammar]. The [`ExpressionContext`] can /// be used to match the `star_named_expression` rule. /// /// NOTE: If you have expressions separated by commas and want to parse them individually /// instead of as a tuple, as done by [`Parser::parse_expression_list`], use this function. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html pub(super) fn parse_named_expression_or_higher( &mut self, context: ExpressionContext, ) -> ParsedExpr { let start = self.node_start(); let parsed_expr = self.parse_conditional_expression_or_higher_impl(context); if self.at(TokenKind::ColonEqual) { Expr::Named(self.parse_named_expression(parsed_expr.expr, start)).into() } else { parsed_expr } } /// Parses every Python expression except unparenthesized tuple and named expressions. /// /// Matches the `expression` rule in the [Python grammar]. /// /// This uses the default [`ExpressionContext`]. Use /// [`Parser::parse_conditional_expression_or_higher_impl`] if you prefer to pass in the /// context. /// /// NOTE: If you have expressions separated by commas and want to parse them individually /// instead of as a tuple, as done by [`Parser::parse_expression_list`] use this function. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html pub(super) fn parse_conditional_expression_or_higher(&mut self) -> ParsedExpr { self.parse_conditional_expression_or_higher_impl(ExpressionContext::default()) } pub(super) fn parse_conditional_expression_or_higher_impl( &mut self, context: ExpressionContext, ) -> ParsedExpr { if self.at(TokenKind::Lambda) { Expr::Lambda(self.parse_lambda_expr()).into() } else { let start = self.node_start(); let parsed_expr = self.parse_simple_expression(context); if self.at(TokenKind::If) { Expr::If(self.parse_if_expression(parsed_expr.expr, start)).into() } else { parsed_expr } } } /// Parses every Python expression except unparenthesized tuples, named expressions, /// and `if` expression. /// /// This is a combination of the `disjunction`, `starred_expression`, `yield_expr` /// and `lambdef` rules of the [Python grammar]. /// /// Note that this function parses lambda expression but reports an error as they're not /// allowed in this context. This is done for better error recovery. /// Use [`Parser::parse_conditional_expression_or_higher`] or any methods which calls into the /// specified method to allow parsing lambda expression. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_simple_expression(&mut self, context: ExpressionContext) -> ParsedExpr { self.parse_binary_expression_or_higher(OperatorPrecedence::None, context) } /// Parses a binary expression using the [Pratt parsing algorithm]. /// /// [Pratt parsing algorithm]: https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html fn parse_binary_expression_or_higher( &mut self, left_precedence: OperatorPrecedence, context: ExpressionContext, ) -> ParsedExpr { let start = self.node_start(); let lhs = self.parse_lhs_expression(left_precedence, context); self.parse_binary_expression_or_higher_recursive(lhs, left_precedence, context, start) } fn parse_binary_expression_or_higher_recursive( &mut self, mut left: ParsedExpr, left_precedence: OperatorPrecedence, context: ExpressionContext, start: TextSize, ) -> ParsedExpr { let mut progress = ParserProgress::default(); loop { progress.assert_progressing(self); let current_token = self.current_token_kind(); if matches!(current_token, TokenKind::In) && context.is_in_excluded() { // Omit the `in` keyword when parsing the target expression in a comprehension or // a `for` statement. break; } let next_token = matches!(current_token, TokenKind::Is | TokenKind::Not).then(|| self.peek()); let Some(operator) = BinaryLikeOperator::try_from_tokens(current_token, next_token) else { // Not an operator. break; }; let new_precedence = operator.precedence(); let stop_at_current_operator = if new_precedence.is_right_associative() { new_precedence < left_precedence } else { new_precedence <= left_precedence }; if stop_at_current_operator { break; } left.expr = match operator { BinaryLikeOperator::Boolean(bool_op) => { Expr::BoolOp(self.parse_boolean_expression(left.expr, start, bool_op, context)) } BinaryLikeOperator::Comparison(cmp_op) => Expr::Compare( self.parse_comparison_expression(left.expr, start, cmp_op, context), ), BinaryLikeOperator::Binary(bin_op) => { self.bump(TokenKind::from(bin_op)); let right = if new_precedence.is_right_associative() { // For right-associative operators (`**`), the right // operand recursion is unbounded in `a**a**a**...`, // and it bypasses the guard in `parse_lhs_expression` // (that scope is exited once the atom is parsed). if let Some(right) = self.with_recursion(|parser| { parser.parse_binary_expression_or_higher(new_precedence, context) }) { right } else { self.report_recursion_limit_exceeded(self.current_token_range()); self.recursion_recovery_expr() } } else { self.parse_binary_expression_or_higher(new_precedence, context) }; Expr::BinOp(ast::ExprBinOp { left: Box::new(left.expr), op: bin_op, right: Box::new(right.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } }; } left } /// Parses the left-hand side of an expression. /// /// This includes prefix expressions such as unary operators, boolean `not`, /// `await`, `lambda`. It also parses atoms and postfix expressions. /// /// The given [`OperatorPrecedence`] is used to determine if the parsed expression /// is valid in that context. For example, a unary operator is not valid /// in an `await` expression in which case the `left_precedence` would /// be [`OperatorPrecedence::Await`]. fn parse_lhs_expression( &mut self, left_precedence: OperatorPrecedence, context: ExpressionContext, ) -> ParsedExpr { let token = self.current_token_kind(); if !Self::token_starts_recursive_lhs(token) { return self.parse_lhs_expression_inner(left_precedence, context, token); } if let Some(result) = self.with_recursion(|parser| { parser.parse_lhs_expression_inner(left_precedence, context, token) }) { result } else { self.report_recursion_limit_exceeded(self.current_token_range()); self.recursion_recovery_expr() } } /// Returns whether parsing an expression that starts with `token` can /// immediately recurse through another expression parse. #[inline] fn token_starts_recursive_lhs(token: TokenKind) -> bool { token.as_unary_operator().is_some() || matches!( token, TokenKind::Star | TokenKind::Await | TokenKind::Lambda | TokenKind::Yield | TokenKind::FStringStart | TokenKind::TStringStart | TokenKind::Lpar | TokenKind::Lsqb | TokenKind::Lbrace ) } /// The standard expression-recovery node returned when the recursion /// limit is exceeded: an empty `Name` with the `Invalid` context. fn recursion_recovery_expr(&mut self) -> ParsedExpr { ParsedExpr { expr: Expr::Name(ast::ExprName { range: self.missing_node_range(), id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, }), is_parenthesized: false, } } fn parse_lhs_expression_inner( &mut self, left_precedence: OperatorPrecedence, context: ExpressionContext, token: TokenKind, ) -> ParsedExpr { let start = self.node_start(); if let Some(unary_op) = token.as_unary_operator() { let expr = self.parse_unary_expression(unary_op, context); if matches!(unary_op, UnaryOp::Not) { if left_precedence > OperatorPrecedence::Not { self.add_error( ParseErrorType::OtherError( "Boolean 'not' expression cannot be used here".to_string(), ), &expr, ); } } else { // > The power operator `**` binds less tightly than an arithmetic // > or bitwise unary operator on its right, that is, 2**-1 is 0.5. // // Reference: https://docs.python.org/3/reference/expressions.html#id21 if left_precedence > OperatorPrecedence::PosNegBitNot && left_precedence != OperatorPrecedence::Exponent { self.add_error( ParseErrorType::OtherError(format!( "Unary '{unary_op}' expression cannot be used here", )), &expr, ); } } return Expr::UnaryOp(expr).into(); } match token { TokenKind::Star => { let starred_expr = self.parse_starred_expression(context); if left_precedence > OperatorPrecedence::None || !context.is_starred_expression_allowed() { self.add_error(ParseErrorType::InvalidStarredExpressionUsage, &starred_expr); } return Expr::Starred(starred_expr).into(); } TokenKind::Await => { let await_expr = self.parse_await_expression(); // `await` expressions cannot be nested if left_precedence >= OperatorPrecedence::Await { self.add_error( ParseErrorType::OtherError( "Await expression cannot be used here".to_string(), ), &await_expr, ); } return Expr::Await(await_expr).into(); } TokenKind::Lambda => { // Lambda expression isn't allowed in this context but we'll still parse it and // report an error for better recovery. let lambda_expr = self.parse_lambda_expr(); self.add_error(ParseErrorType::InvalidLambdaExpressionUsage, &lambda_expr); return Expr::Lambda(lambda_expr).into(); } TokenKind::Yield => { let expr = self.parse_yield_expression(); if left_precedence > OperatorPrecedence::None || !context.is_yield_expression_allowed() { self.add_error(ParseErrorType::InvalidYieldExpressionUsage, &expr); } return expr.into(); } _ => {} } let lhs = self.parse_atom(context); ParsedExpr { expr: self.parse_postfix_expression(lhs.expr, start, context), is_parenthesized: lhs.is_parenthesized, } } /// Parses an expression with a minimum precedence of bitwise `or`. /// /// This methods actually parses the expression using the `expression` rule /// of the [Python grammar] and then validates the parsed expression. In a /// sense, it matches the `bitwise_or` rule of the [Python grammar]. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_expression_with_bitwise_or_precedence(&mut self) -> ParsedExpr { let parsed_expr = self.parse_conditional_expression_or_higher(); if parsed_expr.is_parenthesized { // Parentheses resets the precedence, so we don't need to validate it. return parsed_expr; } let expr_name = match parsed_expr.expr { Expr::Compare(_) => "Comparison", Expr::BoolOp(_) | Expr::UnaryOp(ast::ExprUnaryOp { op: ast::UnaryOp::Not, .. }) => "Boolean", Expr::If(_) => "Conditional", Expr::Lambda(_) => "Lambda", _ => return parsed_expr, }; self.add_error( ParseErrorType::OtherError(format!("{expr_name} expression cannot be used here")), &parsed_expr, ); parsed_expr } /// Parses a name. /// /// For an invalid name, the `id` field will be an empty string and the `ctx` /// field will be [`ExprContext::Invalid`]. /// /// See: pub(super) fn parse_name(&mut self, context: ExpressionContext) -> ast::ExprName { let identifier = self.parse_identifier_with_context(context); let ctx = if identifier.is_valid() { ExprContext::Load } else { ExprContext::Invalid }; ast::ExprName { range: identifier.range, id: identifier.id, ctx, node_index: AtomicNodeIndex::NONE, } } pub(super) fn parse_missing_name(&mut self) -> ast::ExprName { let identifier = self.parse_missing_identifier(); ast::ExprName { range: identifier.range, id: identifier.id, ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, } } /// Parses an identifier. /// /// For an invalid identifier, the `id` field will be an empty string. /// /// See: pub(super) fn parse_identifier(&mut self) -> ast::Identifier { self.parse_identifier_with_context(ExpressionContext::default()) } fn parse_identifier_with_context(&mut self, context: ExpressionContext) -> ast::Identifier { let range = self.current_token_range(); if self.at(TokenKind::Name) { let name = self.bump_name(); return ast::Identifier { id: name, range, node_index: AtomicNodeIndex::NONE, }; } if self.current_token_kind().is_soft_keyword() { let text = self.src_text(range); let id = self.intern_name(text); self.bump_soft_keyword_as_name(); return ast::Identifier { id, range, node_index: AtomicNodeIndex::NONE, }; } // test_err incomplete_attribute_before_for_in_delimiter // [item. for item in xs] // [item. async for item in xs] // {item. for item in xs} // (item. for item in xs) // [item for item. in xs] // for item. in xs: ... if (context.is_for_excluded()) && (self.at(TokenKind::For) || (self.at(TokenKind::Async) && self.peek() == TokenKind::For)) || (context.is_in_excluded() && self.at(TokenKind::In)) { return self.parse_missing_identifier(); } if self.current_token_kind().is_keyword() { // Non-soft keyword self.add_error( ParseErrorType::OtherError(format!( "Expected an identifier, but found a keyword {} that cannot be used here", self.current_token_kind() )), range, ); let text = self.src_text(range); let id = self.intern_name(text); self.bump_any(); ast::Identifier { id, range, node_index: AtomicNodeIndex::NONE, } } else { self.parse_missing_identifier() } } fn parse_missing_identifier(&mut self) -> ast::Identifier { self.add_error( ParseErrorType::OtherError("Expected an identifier".into()), self.current_token_range(), ); ast::Identifier { id: Name::empty(), range: self.missing_node_range(), node_index: AtomicNodeIndex::NONE, } } /// Parses an atom. /// /// See: fn parse_atom(&mut self, context: ExpressionContext) -> ParsedExpr { let start = self.node_start(); let lhs = match self.current_token_kind() { TokenKind::Float => { let value = self.bump_float(); Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Float(value), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Complex => { let (real, imag) = self.bump_complex(); Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Complex { real, imag }, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Int => { let value = self.bump_int(); Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Int(value), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::True => { self.bump(TokenKind::True); Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: true, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::False => { self.bump(TokenKind::False); Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: false, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::None => { self.bump(TokenKind::None); Expr::NoneLiteral(ast::ExprNoneLiteral { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Ellipsis => { self.bump(TokenKind::Ellipsis); Expr::EllipsisLiteral(ast::ExprEllipsisLiteral { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Name => Expr::Name(self.parse_name(context)), TokenKind::IpyEscapeCommand => { Expr::IpyEscapeCommand(self.parse_ipython_escape_command_expression()) } TokenKind::String | TokenKind::FStringStart | TokenKind::TStringStart => { self.parse_strings() } TokenKind::Lpar => { return self.parse_parenthesized_expression(); } TokenKind::Lsqb => self.parse_list_like_expression(), TokenKind::Lbrace => self.parse_set_or_dict_like_expression(), kind => { if kind.is_keyword() { Expr::Name(self.parse_name(context)) } else { self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); Expr::Name(ast::ExprName { range: self.missing_node_range(), id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, }) } } }; lhs.into() } /// Parses a postfix expression in a loop until there are no postfix expressions left to parse. /// /// For a given left-hand side, a postfix expression can begin with either `(` for a call /// expression, `[` for a subscript expression, or `.` for an attribute expression. /// /// This method does nothing if the current token is not a candidate for a postfix expression. fn parse_postfix_expression( &mut self, mut lhs: Expr, start: TextSize, context: ExpressionContext, ) -> Expr { loop { lhs = match self.current_token_kind() { TokenKind::Lpar => { if self.tokens.nesting() > self.max_nesting_depth { self.report_recursion_limit_exceeded(self.current_token_range()); break lhs; } Expr::Call(self.parse_call_expression(lhs, start)) } TokenKind::Lsqb => { if self.tokens.nesting() > self.max_nesting_depth { self.report_recursion_limit_exceeded(self.current_token_range()); break lhs; } Expr::Subscript(self.parse_subscript_expression(lhs, start)) } TokenKind::Dot => { Expr::Attribute(self.parse_attribute_expression(lhs, start, context)) } _ => break lhs, }; } } /// Parse a call expression. /// /// The function name is parsed by the caller and passed as `func` along with /// the `start` position of the call expression. /// /// # Panics /// /// If the parser isn't position at a `(` token. /// /// See: fn parse_call_expression(&mut self, func: Expr, start: TextSize) -> ast::ExprCall { let arguments = self.parse_arguments(ArgumentsContext::Call); debug_assert_eq!(self.node_range(start).end(), arguments.end()); ast::ExprCall { func: Box::new(func), arguments, range_start: start, node_index: AtomicNodeIndex::NONE, } } /// Parses an argument list. /// /// # Panics /// /// If the parser isn't positioned at a `(` token. /// /// See: pub(super) fn parse_arguments(&mut self, context: ArgumentsContext) -> ast::Arguments { let start = self.node_start(); self.bump(TokenKind::Lpar); if self.eat(TokenKind::Rpar) { return ast::Arguments { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, args: Box::default(), keywords: ThinVec::default(), }; } let args_snapshot = self.expr_scratch.snapshot(); let keywords_snapshot = self.keyword_scratch.snapshot(); let mut seen_keyword_argument = false; // foo = 1 let mut seen_keyword_unpacking = false; // **foo let has_trailing_comma = self.parse_comma_separated_list(RecoveryContextKind::Arguments, |parser| { let argument_start = parser.node_start(); if parser.eat(TokenKind::DoubleStar) { let value = parser.parse_conditional_expression_or_higher(); parser.keyword_scratch.push(ast::Keyword { arg: None, value: value.expr, range: parser.node_range(argument_start), node_index: AtomicNodeIndex::NONE, }); seen_keyword_unpacking = true; } else { let start = parser.node_start(); let mut parsed_expr = parser .parse_named_expression_or_higher(ExpressionContext::starred_conditional()); match parser.current_token_kind() { TokenKind::Async | TokenKind::For => { if parsed_expr.is_unparenthesized_starred_expr() { parser.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInGenerator, ), parsed_expr.range(), ); } parsed_expr = Expr::Generator(parser.parse_generator_expression( parsed_expr.expr, start, Parenthesized::No, )) .into(); } _ => { if seen_keyword_unpacking && parsed_expr.is_unparenthesized_starred_expr() { parser.add_error( ParseErrorType::InvalidArgumentUnpackingOrder, &parsed_expr, ); } } } let arg_range = parser.node_range(start); if parser.eat(TokenKind::Equal) { seen_keyword_argument = true; let arg = if let ParsedExpr { expr: Expr::Name(ident_expr), is_parenthesized, } = parsed_expr { // test_ok parenthesized_kwarg_py37 // # parse_options: {"target-version": "3.7"} // f((a)=1) // test_err parenthesized_kwarg_py38 // # parse_options: {"target-version": "3.8"} // f((a)=1) // f((a) = 1) // f( ( a ) = 1) if is_parenthesized { parser.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::ParenthesizedKeywordArgumentName, arg_range, ); } ast::Identifier { id: ident_expr.id, range: ident_expr.range, node_index: AtomicNodeIndex::NONE, } } else { // TODO(dhruvmanila): Parser shouldn't drop the `parsed_expr` if it's // not a name expression. We could add the expression into `args` but // that means the error is a missing comma instead. parser.add_error( ParseErrorType::OtherError("Expected a parameter name".to_string()), &parsed_expr, ); ast::Identifier { id: Name::empty(), range: parsed_expr.range(), node_index: AtomicNodeIndex::NONE, } }; let value = parser.parse_conditional_expression_or_higher(); parser.keyword_scratch.push(ast::Keyword { arg: Some(arg), value: value.expr, range: parser.node_range(argument_start), node_index: AtomicNodeIndex::NONE, }); } else { if !parsed_expr.is_unparenthesized_starred_expr() { if seen_keyword_unpacking { parser.add_error( ParseErrorType::PositionalAfterKeywordUnpacking, &parsed_expr, ); } else if seen_keyword_argument { parser.add_error( ParseErrorType::PositionalAfterKeywordArgument, &parsed_expr, ); } } parser.expr_scratch.push(parsed_expr.expr); } } }); self.expect(TokenKind::Rpar); let keywords = self.keyword_scratch.take_thin_vec(keywords_snapshot); let arguments = ast::Arguments { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, args: self.expr_scratch.take(args_snapshot), keywords, }; self.validate_arguments(&arguments, has_trailing_comma, context); arguments } /// Parses a subscript expression. /// /// # Panics /// /// If the parser isn't positioned at a `[` token. /// /// See: fn parse_subscript_expression( &mut self, mut value: Expr, start: TextSize, ) -> ast::ExprSubscript { self.bump(TokenKind::Lsqb); // To prevent the `value` context from being `Del` within a `del` statement, // we set the context as `Load` here. helpers::set_expr_ctx(&mut value, ExprContext::Load); // Slice range doesn't include the `[` token. let slice_start = self.node_start(); // Create an error when receiving an empty slice to parse, e.g. `x[]` if self.eat(TokenKind::Rsqb) { let slice_range = self.node_range(slice_start); self.add_error(ParseErrorType::EmptySlice, slice_range); return ast::ExprSubscript { value: Box::new(value), slice: Box::new(Expr::Name(ast::ExprName { range: slice_range, id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, })), ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }; } let mut slice = self.parse_slice(); // If there are more than one element in the slice, we need to create a tuple // expression to represent it. if self.eat(TokenKind::Comma) { let slices_snapshot = self.expr_scratch.snapshot(); self.expr_scratch.push(slice); self.parse_comma_separated_list(RecoveryContextKind::Slices, |parser| { let slice = parser.parse_slice(); parser.expr_scratch.push(slice); }); slice = Expr::Tuple(ast::ExprTuple { elts: self.expr_scratch.take(slices_snapshot), ctx: ExprContext::Load, range: self.node_range(slice_start), parenthesized: false, node_index: AtomicNodeIndex::NONE, }); } else if slice.is_starred_expr() { // If the only slice element is a starred expression, that is represented // using a tuple expression with a single element. This is the second case // in the `slices` rule in the Python grammar. slice = Expr::Tuple(ast::ExprTuple { elts: vec![slice], ctx: ExprContext::Load, range: self.node_range(slice_start), parenthesized: false, node_index: AtomicNodeIndex::NONE, }); } self.expect(TokenKind::Rsqb); // test_ok star_index_py311 // # parse_options: {"target-version": "3.11"} // lst[*index] # simple index // class Array(Generic[DType, *Shape]): ... # motivating example from the PEP // lst[a, *b, c] # different positions // lst[a, b, *c] # different positions // lst[*a, *b] # multiple unpacks // array[3:5, *idxs] # mixed with slices // test_err star_index_py310 // # parse_options: {"target-version": "3.10"} // lst[*index] # simple index // class Array(Generic[DType, *Shape]): ... # motivating example from the PEP // lst[a, *b, c] # different positions // lst[a, b, *c] # different positions // lst[*a, *b] # multiple unpacks // array[3:5, *idxs] # mixed with slices // test_err star_slices // array[*start:*end] // test_ok parenthesized_star_index_py310 // # parse_options: {"target-version": "3.10"} // out[(*(slice(None) for _ in range(2)), *ind)] = 1 if let Expr::Tuple(ast::ExprTuple { elts, parenthesized: false, .. }) = &slice { for elt in elts.iter().filter(|elt| elt.is_starred_expr()) { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::StarExpressionInIndex, elt.range(), ); } } ast::ExprSubscript { value: Box::new(value), slice: Box::new(slice), ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a slice expression. /// /// See: fn parse_slice(&mut self) -> Expr { const UPPER_END_SET: TokenSet = TokenSet::new([TokenKind::Comma, TokenKind::Colon, TokenKind::Rsqb]) .union(NEWLINE_EOF_SET); const STEP_END_SET: TokenSet = TokenSet::new([TokenKind::Comma, TokenKind::Rsqb]).union(NEWLINE_EOF_SET); // test_err named_expr_slice // # even after 3.9, an unparenthesized named expression is not allowed in a slice // lst[x:=1:-1] // lst[1:x:=1] // lst[1:3:x:=1] // test_err named_expr_slice_parse_error // # parse_options: {"target-version": "3.8"} // # before 3.9, only emit the parse error, not the unsupported syntax error // lst[x:=1:-1] let start = self.node_start(); let lower = if self.at_expr() { let lower = self.parse_named_expression_or_higher(ExpressionContext::starred_conditional()); // This means we're in a subscript. if self.at_ts(NEWLINE_EOF_SET.union([TokenKind::Rsqb, TokenKind::Comma].into())) { // test_ok parenthesized_named_expr_index_py38 // # parse_options: {"target-version": "3.8"} // lst[(x:=1)] // test_ok unparenthesized_named_expr_index_py39 // # parse_options: {"target-version": "3.9"} // lst[x:=1] // test_err unparenthesized_named_expr_index_py38 // # parse_options: {"target-version": "3.8"} // lst[x:=1] if lower.is_unparenthesized_named_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SequenceIndex, ), lower.range(), ); } return lower.expr; } // Now we know we're in a slice. if !lower.is_parenthesized { match lower.expr { Expr::Starred(_) => { self.add_error(ParseErrorType::InvalidStarredExpressionUsage, &lower); } Expr::Named(_) => { self.add_error(ParseErrorType::UnparenthesizedNamedExpression, &lower); } _ => {} } } Some(lower.expr) } else { None }; self.expect(TokenKind::Colon); let lower = lower.map(Box::new); let upper = if self.at_ts(UPPER_END_SET) { None } else { Some(Box::new(self.parse_conditional_expression_or_higher().expr)) }; let step = if self.eat(TokenKind::Colon) { if self.at_ts(STEP_END_SET) { None } else { Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } } else { None }; Expr::Slice(ast::ExprSlice { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, lower, upper, step, }) } /// Parses a unary expression. /// /// This includes the unary arithmetic `+` and `-`, bitwise `~`, and the /// boolean `not` operators. /// /// # Panics /// /// If the parser isn't positioned at any of the unary operators. /// /// See: pub(super) fn parse_unary_expression( &mut self, op: UnaryOp, context: ExpressionContext, ) -> ast::ExprUnaryOp { let start = self.node_start(); self.bump(TokenKind::from(op)); let operand = self.parse_binary_expression_or_higher(OperatorPrecedence::from(op), context); ast::ExprUnaryOp { op, operand: Box::new(operand.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an attribute expression. /// /// # Panics /// /// If the parser isn't positioned at a `.` token. /// /// See: pub(super) fn parse_attribute_expression( &mut self, value: Expr, start: TextSize, context: ExpressionContext, ) -> ast::ExprAttribute { self.bump(TokenKind::Dot); let attr = self.parse_identifier_with_context(context); ast::ExprAttribute { value: Box::new(value), attr, ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a boolean operation expression. /// /// Note that the boolean `not` operator is parsed as a unary expression and /// not as a boolean expression. /// /// # Panics /// /// If the parser isn't positioned at a `or` or `and` token. /// /// See: fn parse_boolean_expression( &mut self, lhs: Expr, start: TextSize, op: BoolOp, context: ExpressionContext, ) -> ast::ExprBoolOp { self.bump(TokenKind::from(op)); let values_snapshot = self.expr_scratch.snapshot(); self.expr_scratch.push(lhs); let mut progress = ParserProgress::default(); // Keep adding the expression to `values` until we see a different // token than `operator_token`. loop { progress.assert_progressing(self); let parsed_expr = self.parse_binary_expression_or_higher(OperatorPrecedence::from(op), context); self.expr_scratch.push(parsed_expr.expr); if !self.eat(TokenKind::from(op)) { break; } } ast::ExprBoolOp { values: self.expr_scratch.take(values_snapshot), op, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Bump the appropriate token(s) for the given comparison operator. fn bump_cmp_op(&mut self, op: CmpOp) { let (first, second) = match op { CmpOp::Eq => (TokenKind::EqEqual, None), CmpOp::NotEq => (TokenKind::NotEqual, None), CmpOp::Lt => (TokenKind::Less, None), CmpOp::LtE => (TokenKind::LessEqual, None), CmpOp::Gt => (TokenKind::Greater, None), CmpOp::GtE => (TokenKind::GreaterEqual, None), CmpOp::Is => (TokenKind::Is, None), CmpOp::IsNot => (TokenKind::Is, Some(TokenKind::Not)), CmpOp::In => (TokenKind::In, None), CmpOp::NotIn => (TokenKind::Not, Some(TokenKind::In)), }; self.bump(first); if let Some(second) = second { self.bump(second); } } /// Parse a comparison expression. /// /// This includes the following operators: /// - Value comparisons: `==`, `!=`, `<`, `<=`, `>`, and `>=`. /// - Membership tests: `in` and `not in`. /// - Identity tests: `is` and `is not`. /// /// # Panics /// /// If the parser isn't positioned at any of the comparison operators. /// /// See: fn parse_comparison_expression( &mut self, lhs: Expr, start: TextSize, op: CmpOp, context: ExpressionContext, ) -> ast::ExprCompare { self.bump_cmp_op(op); let comparators_snapshot = self.expr_scratch.snapshot(); let mut operators = vec![op]; let mut progress = ParserProgress::default(); loop { progress.assert_progressing(self); let comparator = self .parse_binary_expression_or_higher( OperatorPrecedence::ComparisonsMembershipIdentity, context, ) .expr; self.expr_scratch.push(comparator); let next_token = self.current_token_kind(); if matches!(next_token, TokenKind::In) && context.is_in_excluded() { break; } let next_next_token = matches!(next_token, TokenKind::Is | TokenKind::Not).then(|| self.peek()); let Some(next_op) = helpers::token_kind_to_cmp_op(next_token, next_next_token) else { break; }; self.bump_cmp_op(next_op); operators.push(next_op); } ast::ExprCompare { left: Box::new(lhs), ops: operators.into_boxed_slice(), comparators: self.expr_scratch.take(comparators_snapshot), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses all kinds of strings and implicitly concatenated strings. /// /// # Panics /// /// If the parser isn't positioned at a `String`, `FStringStart`, or `TStringStart` token. /// /// See: (Search "strings:") pub(super) fn parse_strings(&mut self) -> Expr { const STRING_START_SET: TokenSet = TokenSet::new([ TokenKind::String, TokenKind::FStringStart, TokenKind::TStringStart, ]); let start = self.node_start(); let first = self.parse_string(); if !self.at_ts(STRING_START_SET) { return first.into(); } let mut strings = Vec::with_capacity(2); strings.push(first); let mut progress = ParserProgress::default(); while self.at_ts(STRING_START_SET) { progress.assert_progressing(self); strings.push(self.parse_string()); } let range = self.node_range(start); self.handle_implicitly_concatenated_strings(strings, range) } /// Parses a single string, byte literal, f-string, or t-string. fn parse_string(&mut self) -> StringType { if self.at(TokenKind::String) { self.parse_string_or_byte_literal() } else if self.at(TokenKind::FStringStart) { StringType::FString( self.parse_interpolated_string(InterpolatedStringKind::FString) .into(), ) } else if self.at(TokenKind::TStringStart) { // test_ok template_strings_py314 // # parse_options: {"target-version": "3.14"} // t"{hey}" // t'{there}' // t"""what's // happening?""" // test_err template_strings_py313 // # parse_options: {"target-version": "3.13"} // t"{hey}" // t'{there}' // t"""what's // happening?""" let string_type = StringType::TString( self.parse_interpolated_string(InterpolatedStringKind::TString) .into(), ); self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::TemplateStrings, string_type.range(), ); string_type } else { unreachable!("Expected to parse a string") } } /// Handles implicitly concatenated strings. /// /// # Panics /// /// If the length of `strings` is less than 2. fn handle_implicitly_concatenated_strings( &mut self, strings: Vec, range: TextRange, ) -> Expr { assert!(strings.len() > 1); let mut has_fstring = false; let mut byte_literal_count = 0; let mut tstring_count = 0; for string in &strings { match string { StringType::FString(_) => has_fstring = true, StringType::TString(_) => tstring_count += 1, StringType::Bytes(_) => byte_literal_count += 1, StringType::Str(_) => {} } } let has_bytes = byte_literal_count > 0; let has_tstring = tstring_count > 0; if has_bytes { if byte_literal_count < strings.len() { // TODO(dhruvmanila): This is not an ideal recovery because the parser // replaces the byte literals with an invalid string literal node. Any // downstream tools can extract the raw bytes from the range. // // We could convert the node into a string and mark it as invalid // and would be clever to mark the type which is fewer in quantity. // test_err mixed_bytes_and_non_bytes_literals // 'first' b'second' // f'first' b'second' // 'first' f'second' b'third' self.add_error( ParseErrorType::OtherError( "Bytes literal cannot be mixed with non-bytes literals".to_string(), ), range, ); } // Only construct a byte expression if all the literals are bytes // otherwise, we'll try either string, t-string, or f-string. This is to retain // as much information as possible. else { let mut values = Vec::with_capacity(strings.len()); for string in strings { values.push(match string { StringType::Bytes(value) => value, _ => unreachable!("Expected `StringType::Bytes`"), }); } return Expr::from(ast::ExprBytesLiteral { value: ast::BytesLiteralValue::concatenated(values), range, node_index: AtomicNodeIndex::NONE, }); } } if has_tstring { if tstring_count < strings.len() { self.add_error( ParseErrorType::OtherError( "Cannot mix t-string literals with string or bytes literals".to_string(), ), range, ); } // Only construct a t-string expression if all the literals are t-strings // otherwise, we'll try either string or f-string. This is to retain // as much information as possible. else { let mut values = Vec::with_capacity(strings.len()); for string in strings { values.push(match string { StringType::TString(value) => value, _ => unreachable!("Expected `StringType::TString`"), }); } return Expr::from(ast::ExprTString { value: ast::TStringValue::concatenated(values), range, node_index: AtomicNodeIndex::NONE, }); } } // TODO(dhruvmanila): Parser drops unterminated strings here as well // because the lexer doesn't emit them. // test_err implicitly_concatenated_unterminated_string // 'hello' 'world // 1 + 1 // 'hello' f'world {x} // 2 + 2 // test_err implicitly_concatenated_unterminated_string_multiline // ( // 'hello' // f'world {x} // ) // 1 + 1 // ( // 'first' // 'second // f'third' // ) // 2 + 2 if !has_fstring && !has_tstring { let mut values = Vec::with_capacity(strings.len()); for string in strings { values.push(match string { StringType::Str(value) => value, _ => ast::StringLiteral::invalid(string.range()), }); } return Expr::from(ast::ExprStringLiteral { value: ast::StringLiteralValue::concatenated(values), range, node_index: AtomicNodeIndex::NONE, }); } let mut parts = Vec::with_capacity(strings.len()); for string in strings { match string { StringType::FString(fstring) => parts.push(ast::FStringPart::FString(fstring)), StringType::Str(string) => parts.push(ast::FStringPart::Literal(string)), // Bytes and Template strings are invalid at this point // and stored as invalid string literal parts in the // f-string StringType::TString(tstring) => parts.push(ast::FStringPart::Literal( ast::StringLiteral::invalid(tstring.range()), )), StringType::Bytes(bytes) => parts.push(ast::FStringPart::Literal( ast::StringLiteral::invalid(bytes.range()), )), } } Expr::from(ast::ExprFString { value: ast::FStringValue::concatenated(parts), range, node_index: AtomicNodeIndex::NONE, }) } /// Parses a single string or byte literal. /// /// This does not handle implicitly concatenated strings. /// /// # Panics /// /// If the parser isn't positioned at a `String` token. /// /// See: fn parse_string_or_byte_literal(&mut self) -> StringType { let range = self.current_token_range(); let flags = self.tokens.current_flags().as_any_string_flags(); let value = self.bump_string_value(); match parse_string_literal(value, flags, range) { Ok(string) => string, Err(error) => { let location = error.location(); self.add_error(ParseErrorType::Lexical(error.into_error()), location); if flags.is_byte_string() { // test_err invalid_byte_literal // b'123a𝐁c' // rb"a𝐁c123" // b"""123a𝐁c""" StringType::Bytes(ast::BytesLiteral { value: Box::new([]), range, flags: ast::BytesLiteralFlags::from(flags).with_invalid(), node_index: AtomicNodeIndex::NONE, }) } else { // test_err invalid_string_literal // 'hello \N{INVALID} world' // """hello \N{INVALID} world""" StringType::Str(ast::StringLiteral { value: "".into(), range, flags: ast::StringLiteralFlags::from(flags).with_invalid(), node_index: AtomicNodeIndex::NONE, }) } } } } /// Parses an f/t-string. /// /// This does not handle implicitly concatenated strings. /// /// # Panics /// /// If the parser isn't positioned at an `FStringStart` or /// `TStringStart` token. /// /// See: (Search "fstring:" or "tstring:") /// See: fn parse_interpolated_string( &mut self, kind: InterpolatedStringKind, ) -> InterpolatedStringData { let start = self.node_start(); let mut flags = self.tokens.current_flags().as_any_string_flags(); self.bump(kind.start_token()); let elements = self.parse_interpolated_string_elements( flags, InterpolatedStringElementsKind::Regular(kind), kind, ); if !self.expect(kind.end_token()) { flags = flags.with_unclosed(true); } InterpolatedStringData { elements, range: self.node_range(start), flags, } } /// Check `range` for comment tokens, report an `UnsupportedSyntaxError` for each one found, /// and return whether any comments were found. fn check_fstring_comments(&mut self, range: TextRange) -> bool { let mut has_comments = false; self.unsupported_syntax_errors.extend( self.tokens .in_range(range) .iter() .filter(|token| token.kind().is_comment()) .map(|token| { has_comments = true; UnsupportedSyntaxError { kind: UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::Comment), range: token.range(), target_version: self.options.target_version, } }), ); has_comments } /// Parses a list of f/t-string elements. /// /// # Panics /// /// If the parser isn't positioned at a `{`, `FStringMiddle`, /// or `TStringMiddle` token. fn parse_interpolated_string_elements( &mut self, flags: ast::AnyStringFlags, elements_kind: InterpolatedStringElementsKind, string_kind: InterpolatedStringKind, ) -> ast::InterpolatedStringElements { let mut elements = vec![]; let middle_token_kind = string_kind.middle_token(); self.parse_list( RecoveryContextKind::InterpolatedStringElements(elements_kind), |parser| { let element = match parser.current_token_kind() { TokenKind::Lbrace => ast::InterpolatedStringElement::from( parser.parse_interpolated_element(flags, string_kind), ), tok if tok == middle_token_kind => { let range = parser.current_token_range(); let value = parser.current_token_text(); parser.bump(middle_token_kind); InterpolatedStringElement::Literal( parse_interpolated_string_literal_element(value, flags, range) .unwrap_or_else(|lex_error| { // test_err invalid_fstring_literal_element // f'hello \N{INVALID} world' // f"""hello \N{INVALID} world""" let location = lex_error.location(); parser.add_error( ParseErrorType::Lexical(lex_error.into_error()), location, ); ast::InterpolatedStringLiteralElement { value: "".into(), range, node_index: AtomicNodeIndex::NONE, } }), ) } // `Invalid` tokens are created when there's a lexical error, so // we ignore it here to avoid creating unexpected token errors TokenKind::Unknown => { parser.bump_any(); return; } tok => { // This should never happen because the list parsing will only // call this closure for the above token kinds which are the same // as in the FIRST set. unreachable!( "{}: unexpected token `{tok:?}` at {:?}", string_kind, parser.current_token_range() ); } }; elements.push(element); }, ); ast::InterpolatedStringElements::from(elements) } /// Parses an f/t-string expression element. /// /// # Panics /// /// If the parser isn't positioned at a `{` token. fn parse_interpolated_element( &mut self, flags: ast::AnyStringFlags, string_kind: InterpolatedStringKind, ) -> ast::InterpolatedElement { let start = self.node_start(); self.bump(TokenKind::Lbrace); self.tokens .re_lex_string_token_in_interpolation_element(string_kind); // test_err f_string_empty_expression // f"{}" // f"{ }" // test_err t_string_empty_expression // # parse_options: {"target-version": "3.14"} // t"{}" // t"{ }" // test_err f_string_invalid_starred_expr // # Starred expression inside f-string has a minimum precedence of bitwise or. // f"{*}" // f"{*x and y}" // f"{*yield x}" // test_err t_string_invalid_starred_expr // # parse_options: {"target-version": "3.14"} // # Starred expression inside t-string has a minimum precedence of bitwise or. // t"{*}" // t"{*x and y}" // t"{*yield x}" let value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); if !value.is_parenthesized && value.expr.is_lambda_expr() { // TODO(dhruvmanila): This requires making some changes in lambda expression // parsing logic to handle the emitted `FStringMiddle` token in case the // lambda expression is not parenthesized. // test_err f_string_lambda_without_parentheses // f"{lambda x: x}" // test_err t_string_lambda_without_parentheses // # parse_options: {"target-version": "3.14"} // t"{lambda x: x}" self.add_error( ParseErrorType::from_interpolated_string_error( InterpolatedStringErrorType::LambdaWithoutParentheses, string_kind, ), value.range(), ); } let debug_text = if self.eat(TokenKind::Equal) { let leading_range = TextRange::new(start + "{".text_len(), value.start()); let trailing_range = TextRange::new(value.end(), self.current_token_range().start()); Some(ast::DebugText::new( self.src_text(leading_range), self.src_text(value.range()), self.src_text(trailing_range), )) } else { None }; let conversion = if self.eat(TokenKind::Exclamation) { // Ensure that the `r` is lexed as a `r` name token instead of a raw string // in `f{abc!r"` (note the missing `}`). self.tokens.re_lex_raw_string_in_format_spec(); let conversion_flag_range = self.current_token_range(); if self.at(TokenKind::Name) { // test_err f_string_conversion_follows_exclamation // f"{x! s}" // t"{x! s}" // f"{x! z}" if self.prev_token_end != conversion_flag_range.start() { self.add_error( ParseErrorType::from_interpolated_string_error( InterpolatedStringErrorType::ConversionFlagNotImmediatelyAfterExclamation, string_kind, ), TextRange::new(self.prev_token_end, conversion_flag_range.start()), ); } let name = self.bump_name(); match &*name { "s" => ConversionFlag::Str, "r" => ConversionFlag::Repr, "a" => ConversionFlag::Ascii, _ => { // test_err f_string_invalid_conversion_flag_name_tok // f"{x!z}" // test_err t_string_invalid_conversion_flag_name_tok // # parse_options: {"target-version": "3.14"} // t"{x!z}" self.add_error( ParseErrorType::from_interpolated_string_error( InterpolatedStringErrorType::InvalidConversionFlag, string_kind, ), conversion_flag_range, ); ConversionFlag::None } } } else { // test_err f_string_invalid_conversion_flag_other_tok // f"{x!123}" // f"{x!'a'}" // test_err t_string_invalid_conversion_flag_other_tok // # parse_options: {"target-version": "3.14"} // t"{x!123}" // t"{x!'a'}" self.add_error( ParseErrorType::from_interpolated_string_error( InterpolatedStringErrorType::InvalidConversionFlag, string_kind, ), conversion_flag_range, ); // TODO(dhruvmanila): Avoid dropping this token self.bump_any(); ConversionFlag::None } } else { ConversionFlag::None }; let format_spec = if self.eat(TokenKind::Colon) { let spec_start = self.node_start(); let elements = if let Some(elements) = self.with_recursion(|parser| { parser.parse_interpolated_string_elements( flags, InterpolatedStringElementsKind::FormatSpec(string_kind), string_kind, ) }) { elements } else { self.report_recursion_limit_exceeded(self.current_token_range()); ast::InterpolatedStringElements::from(vec![]) }; Some(Box::new(ast::InterpolatedStringFormatSpec { range: self.node_range(spec_start), elements, node_index: AtomicNodeIndex::NONE, })) } else { None }; self.tokens .re_lex_string_token_in_interpolation_element(string_kind); // We're using `eat` here instead of `expect` to use the f-string specific error type. if !self.eat(TokenKind::Rbrace) { // TODO(dhruvmanila): This requires some changes in the lexer. One of them // would be to emit `FStringEnd`. Currently, the following test cases doesn't // really work as expected. Refer https://github.com/astral-sh/ruff/pull/10372 // test_err f_string_unclosed_lbrace // f"{" // f"{foo!r" // f"{foo=" // f"{" // f"""{""" // test_err t_string_unclosed_lbrace // # parse_options: {"target-version": "3.14"} // t"{" // t"{foo!r" // t"{foo=" // t"{" // t"""{""" // The lexer does emit `FStringEnd` for the following test cases: // test_err f_string_unclosed_lbrace_in_format_spec // f"hello {x:" // f"hello {x:.3f" // test_err t_string_unclosed_lbrace_in_format_spec // # parse_options: {"target-version": "3.14"} // t"hello {x:" // t"hello {x:.3f" self.add_error( ParseErrorType::from_interpolated_string_error( InterpolatedStringErrorType::UnclosedLbrace, string_kind, ), self.current_token_range(), ); } // test_ok pep701_f_string_py312 // # parse_options: {"target-version": "3.12"} // f'Magic wand: { bag['wand'] }' # nested quotes // f"{'\n'.join(a)}" # escape sequence // f'''A complex trick: { // bag['bag'] # comment // }''' // f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting // f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes // f"{ // 1 // }" // f"test {a \ // } more" # line continuation // test_ok pep750_t_string_py314 // # parse_options: {"target-version": "3.14"} // t'Magic wand: { bag['wand'] }' # nested quotes // t"{'\n'.join(a)}" # escape sequence // t'''A complex trick: { // bag['bag'] # comment // }''' // t"{t"{t"{t"{t"{t"{1+1}"}"}"}"}"}" # arbitrary nesting // t"{t'''{"nested"} inner'''} outer" # nested (triple) quotes // t"test {a \ // } more" # line continuation // test_ok pep701_f_string_py311 // # parse_options: {"target-version": "3.11"} // f"outer {'# not a comment'}" // f'outer {x:{"# not a comment"} }' // f"""{f'''{f'{"# not a comment"}'}'''}""" // f"""{f'''# before expression {f'# aro{f"#{1+1}#"}und #'}'''} # after expression""" // f"""{ // 1 // }""" // f"escape outside of \t {expr}\n" // f"test\"abcd" // f"{1:\x64}" # escapes are valid in the format spec // f"{1:\"d\"}" # this also means that escaped outer quotes are valid // test_err pep701_f_string_py311 // # parse_options: {"target-version": "3.11"} // f'Magic wand: { bag['wand'] }' # nested quotes // f"{'\n'.join(a)}" # escape sequence // f'''A complex trick: { // bag['bag'] # comment // }''' // f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting // f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes // f"{ // 1 // }" // f"test {a \ // } more" # line continuation // f"""{f"""{x}"""}""" # mark the whole triple quote // f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors // test_err pep701_nested_interpolation_py311 // # parse_options: {"target-version": "3.11"} // # nested interpolations also need to be checked // f'{1: abcd "{'aa'}" }' // f'{1: abcd "{"\n"}" }' // test_err nested_quote_in_format_spec_py312 // # parse_options: {"target-version": "3.12"} // f"{1:""}" # this is a ParseError on all versions // test_ok non_nested_quote_in_format_spec_py311 // # parse_options: {"target-version": "3.11"} // f"{1:''}" # but this is okay on all versions let range = self.node_range(start); if !self.options.target_version.supports_pep_701() && matches!(string_kind, InterpolatedStringKind::FString) { // We need to check the whole expression range, including any leading or trailing // debug text, but exclude the format spec, where escapes and escaped, reused quotes // are allowed. let range = format_spec .as_ref() .map(|format_spec| TextRange::new(range.start(), format_spec.start())) .unwrap_or(range); let quote_bytes = flags.quote_str().as_bytes(); let quote_len = flags.quote_len(); let mut has_backslash_or_comment = false; for slash_position in memchr::memchr_iter(b'\\', self.source[range].as_bytes()) { has_backslash_or_comment = true; let slash_position = TextSize::try_from(slash_position).unwrap(); self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::Backslash), TextRange::at(range.start() + slash_position, '\\'.text_len()), ); } if let Some(quote_position) = memchr::memmem::find(self.source[range].as_bytes(), quote_bytes) { let quote_position = TextSize::try_from(quote_position).unwrap(); self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::NestedQuote), TextRange::at(range.start() + quote_position, quote_len), ); } has_backslash_or_comment |= self.check_fstring_comments(range); // Before Python 3.12, replacement fields could only span physical lines when the // outer f-string was triple-quoted. if !flags.is_triple_quoted() && !has_backslash_or_comment && memchr::memchr2(b'\n', b'\r', self.source[range].as_bytes()).is_some() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::LineBreak), TextRange::at(range.start(), '{'.text_len()), ); } } ast::InterpolatedElement { expression: Box::new(value.expr), debug_text, conversion, format_spec, range, node_index: AtomicNodeIndex::NONE, } } /// Parses a list or a list comprehension expression. /// /// # Panics /// /// If the parser isn't positioned at a `[` token. /// /// See: fn parse_list_like_expression(&mut self) -> Expr { let start = self.node_start(); self.bump(TokenKind::Lsqb); // Nice error message when having a unclosed open bracket `[` if self.at_ts(NEWLINE_EOF_SET) { self.add_error( ParseErrorType::OtherError("Missing closing bracket `]`".to_string()), self.current_token_range(), ); } // Return an empty `ListExpr` when finding a `]` right after the `[` if self.eat(TokenKind::Rsqb) { return Expr::List(ast::ExprList { elts: vec![], ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }); } // Parse the first element with a more general rule and limit it later. let first_element = self.parse_named_expression_or_higher( ExpressionContext::starred_bitwise_or().with_for_excluded(), ); match self.current_token_kind() { TokenKind::Async | TokenKind::For => { // Parenthesized starred expression isn't allowed either but that is // handled by the `parse_parenthesized_expression` method. // test_ok starred_list_comp_py315 // # parse_options: {"target-version": "3.15"} // [*x for x in y] // [*factor.dims for factor in bases] // test_err starred_list_comp_py314 // # parse_options: {"target-version": "3.14"} // [*x for x in y] if first_element.is_unparenthesized_starred_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInList, ), first_element.range(), ); } Expr::ListComp(self.parse_list_comprehension_expression(first_element.expr, start)) } _ => Expr::List(self.parse_list_expression(first_element.expr, start)), } } /// Parses a set, dict, set comprehension, or dict comprehension. /// /// # Panics /// /// If the parser isn't positioned at a `{` token. /// /// See: /// - /// - /// - fn parse_set_or_dict_like_expression(&mut self) -> Expr { // test_ok pep_798_unpacking_comprehensions_py315 // # parse_options: {"target-version": "3.15"} // [*x for x in y] // {*x for x in y} // {**x for x in y} // (*x for x in y) // f(*x for x in y) // [*x async for x in y] // {*x async for x in y} // {**x async for x in y} // (*x async for x in y) // test_err pep_798_unpacking_comprehensions_py314 // # parse_options: {"target-version": "3.14"} // [*x for x in y] // {*x for x in y} // {**x for x in y} // (*x for x in y) // f(*x for x in y) // test_err pep_798_invalid_dict_unpacking_comprehensions_py315 // # parse_options: {"target-version": "3.15"} // {*k: v for k, v in items} // {k: *v for k, v in items} // {**k: v for k, v in items} // {k: **v for k, v in items} let start = self.node_start(); self.bump(TokenKind::Lbrace); // Nice error message when having a unclosed open brace `{` if self.at_ts(NEWLINE_EOF_SET) { self.add_error( ParseErrorType::OtherError("Missing closing brace `}`".to_string()), self.current_token_range(), ); } // Return an empty `DictExpr` when finding a `}` right after the `{` if self.eat(TokenKind::Rbrace) { return Expr::Dict(ast::ExprDict { items: vec![], range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }); } let after_brace = self.node_start(); if self.eat(TokenKind::DoubleStar) { // Handle dictionary unpacking. Here, the grammar is `'**' bitwise_or` // which requires limiting the expression. let value = self.parse_expression_with_bitwise_or_precedence(); let unpack_range = TextRange::new(after_brace, value.range().end()); if matches!(self.current_token_kind(), TokenKind::Async | TokenKind::For) { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::DictInDict, ), unpack_range, ); return Expr::DictComp( self.parse_dictionary_comprehension_expression(None, value.expr, start), ); } if self.at(TokenKind::Colon) { self.add_error(ParseErrorType::InvalidStarredExpressionUsage, unpack_range); self.bump(TokenKind::Colon); let dict_value = self.parse_conditional_expression_or_higher(); if matches!(self.current_token_kind(), TokenKind::Async | TokenKind::For) { return Expr::DictComp(self.parse_dictionary_comprehension_expression( Some(value.expr), dict_value.expr, start, )); } return Expr::Dict(self.parse_dictionary_expression( Some(value.expr), dict_value.expr, start, )); } return Expr::Dict(self.parse_dictionary_expression(None, value.expr, start)); } // For dictionary expressions, the key uses the `expression` rule while for // set expressions, the element uses the `star_expression` rule. So, use the // one that is more general and limit it later. let key_or_element = self.parse_named_expression_or_higher( ExpressionContext::starred_bitwise_or().with_for_excluded(), ); match self.current_token_kind() { TokenKind::Async | TokenKind::For => { if key_or_element.is_unparenthesized_starred_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInSet, ), key_or_element.range(), ); } else if key_or_element.is_unparenthesized_named_expr() { // test_ok parenthesized_named_expr_py38 // # parse_options: {"target-version": "3.8"} // {(x := 1), 2, 3} // {(last := x) for x in range(3)} // test_ok unparenthesized_named_expr_py39 // # parse_options: {"target-version": "3.9"} // {x := 1, 2, 3} // {last := x for x in range(3)} // test_err unparenthesized_named_expr_set_comp_py38 // # parse_options: {"target-version": "3.8"} // {last := x for x in range(3)} self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SetComprehension, ), key_or_element.range(), ); } Expr::SetComp(self.parse_set_comprehension_expression(key_or_element.expr, start)) } TokenKind::Colon => { // Now, we know that it's either a dictionary expression or a dictionary comprehension. // In either case, the key is limited to an `expression`. if !key_or_element.is_parenthesized { match key_or_element.expr { Expr::Starred(_) => self.add_error( ParseErrorType::InvalidStarredExpressionUsage, &key_or_element.expr, ), Expr::Named(_) => self.add_error( ParseErrorType::UnparenthesizedNamedExpression, &key_or_element, ), _ => {} } } self.bump(TokenKind::Colon); let value = if self.at(TokenKind::DoubleStar) { let unpack_start = self.node_start(); self.bump(TokenKind::DoubleStar); let value = self.parse_expression_with_bitwise_or_precedence(); self.add_error( ParseErrorType::InvalidStarredExpressionUsage, TextRange::new(unpack_start, value.range().end()), ); value } else { self.parse_conditional_expression_or_higher() }; if matches!(self.current_token_kind(), TokenKind::Async | TokenKind::For) { Expr::DictComp(self.parse_dictionary_comprehension_expression( Some(key_or_element.expr), value.expr, start, )) } else { Expr::Dict(self.parse_dictionary_expression( Some(key_or_element.expr), value.expr, start, )) } } _ => Expr::Set(self.parse_set_expression(key_or_element, start)), } } /// Parses an expression in parentheses, a tuple expression, or a generator expression. /// /// Matches the `(tuple | group | genexp)` rule in the [Python grammar]. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_parenthesized_expression(&mut self) -> ParsedExpr { let start = self.node_start(); self.bump(TokenKind::Lpar); // Nice error message when having a unclosed open parenthesis `(` if self.at_ts(NEWLINE_EOF_SET) { let range = self.current_token_range(); self.add_error( ParseErrorType::OtherError("Missing closing parenthesis `)`".to_string()), range, ); } // Return an empty `TupleExpr` when finding a `)` right after the `(` if self.eat(TokenKind::Rpar) { return Expr::Tuple(ast::ExprTuple { elts: vec![], ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, parenthesized: true, }) .into(); } // Use the more general rule of the three to parse the first element // and limit it later. let mut parsed_expr = self.parse_named_expression_or_higher( ExpressionContext::yield_or_starred_bitwise_or().with_for_excluded(), ); match self.current_token_kind() { TokenKind::Comma => { // grammar: `tuple` let tuple = self.parse_tuple_expression(parsed_expr.expr, start, Parenthesized::Yes, |p| { p.parse_named_expression_or_higher(ExpressionContext::starred_bitwise_or()) }); ParsedExpr { expr: tuple.into(), is_parenthesized: false, } } TokenKind::Async | TokenKind::For => { // grammar: `genexp` if parsed_expr.is_unparenthesized_starred_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnpackingInComprehension( ComprehensionUnpackingKind::IterableInGenerator, ), parsed_expr.range(), ); } let generator = Expr::Generator(self.parse_generator_expression( parsed_expr.expr, start, Parenthesized::Yes, )); ParsedExpr { expr: generator, is_parenthesized: false, } } _ => { // grammar: `group` if parsed_expr.expr.is_starred_expr() { self.add_error(ParseErrorType::InvalidStarredExpressionUsage, &parsed_expr); } self.expect(TokenKind::Rpar); parsed_expr.is_parenthesized = true; parsed_expr } } } /// Parses multiple items separated by a comma into a tuple expression. /// /// Uses the `parse_func` to parse each item in the tuple. pub(super) fn parse_tuple_expression( &mut self, first_element: Expr, start: TextSize, parenthesized: Parenthesized, mut parse_func: impl FnMut(&mut Parser<'src>) -> ParsedExpr, ) -> ast::ExprTuple { // TODO(dhruvmanila): Can we remove `parse_func` and use `parenthesized` to // determine the parsing function? if !self.at_sequence_end() { self.expect(TokenKind::Comma); } let elts_snapshot = self.expr_scratch.snapshot(); self.expr_scratch.push(first_element); self.parse_comma_separated_list(RecoveryContextKind::TupleElements(parenthesized), |p| { let element = parse_func(p).expr; p.expr_scratch.push(element); }); if parenthesized.is_yes() { self.expect(TokenKind::Rpar); } ast::ExprTuple { elts: self.expr_scratch.take(elts_snapshot), ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, parenthesized: parenthesized.is_yes(), } } /// Parses a list expression. /// /// See: fn parse_list_expression(&mut self, first_element: Expr, start: TextSize) -> ast::ExprList { if !self.at_sequence_end() { self.expect(TokenKind::Comma); } let elts_snapshot = self.expr_scratch.snapshot(); self.expr_scratch.push(first_element); self.parse_comma_separated_list(RecoveryContextKind::ListElements, |parser| { let element = parser .parse_named_expression_or_higher(ExpressionContext::starred_bitwise_or()) .expr; parser.expr_scratch.push(element); }); self.expect(TokenKind::Rsqb); ast::ExprList { elts: self.expr_scratch.take(elts_snapshot), ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a set expression. /// /// See: fn parse_set_expression(&mut self, first_element: ParsedExpr, start: TextSize) -> ast::ExprSet { if !self.at_sequence_end() { self.expect(TokenKind::Comma); } // test_err unparenthesized_named_expr_set_literal_py38 // # parse_options: {"target-version": "3.8"} // {x := 1, 2, 3} // {1, x := 2, 3} // {1, 2, x := 3} if first_element.is_unparenthesized_named_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SetLiteral, ), first_element.range(), ); } let elts_snapshot = self.expr_scratch.snapshot(); self.expr_scratch.push(first_element.expr); self.parse_comma_separated_list(RecoveryContextKind::SetElements, |parser| { let parsed_expr = parser.parse_named_expression_or_higher(ExpressionContext::starred_bitwise_or()); if parsed_expr.is_unparenthesized_named_expr() { parser.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnparenthesizedNamedExpr( UnparenthesizedNamedExprKind::SetLiteral, ), parsed_expr.range(), ); } parser.expr_scratch.push(parsed_expr.expr); }); self.expect(TokenKind::Rbrace); ast::ExprSet { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, elts: self.expr_scratch.take(elts_snapshot), } } /// Parses a dictionary expression. /// /// See: fn parse_dictionary_expression( &mut self, key: Option, value: Expr, start: TextSize, ) -> ast::ExprDict { if !self.at_sequence_end() { self.expect(TokenKind::Comma); } let mut items = vec![ast::DictItem { key, value }]; self.parse_comma_separated_list(RecoveryContextKind::DictElements, |parser| { if parser.eat(TokenKind::DoubleStar) { // Handle dictionary unpacking. Here, the grammar is `'**' bitwise_or` // which requires limiting the expression. items.push(ast::DictItem { key: None, value: parser.parse_expression_with_bitwise_or_precedence().expr, }); } else { let key = parser.parse_conditional_expression_or_higher().expr; parser.expect(TokenKind::Colon); items.push(ast::DictItem { key: Some(key), value: parser.parse_conditional_expression_or_higher().expr, }); } }); self.expect(TokenKind::Rbrace); items.shrink_to_fit(); ast::ExprDict { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, items, } } /// Parses a list of comprehension generators. /// /// These are the `for` and `async for` clauses in a comprehension, optionally /// followed by `if` clauses. /// /// See: fn parse_generators(&mut self) -> Vec { const GENERATOR_SET: TokenSet = TokenSet::new([TokenKind::For, TokenKind::Async]); let mut generators = Vec::with_capacity(1); let mut progress = ParserProgress::default(); while self.at_ts(GENERATOR_SET) { progress.assert_progressing(self); generators.push(self.parse_comprehension()); } generators.shrink_to_fit(); generators } /// Parses a comprehension. /// /// # Panics /// /// If the parser isn't positioned at an `async` or `for` token. /// /// See: fn parse_comprehension(&mut self) -> ast::Comprehension { let start = self.node_start(); let is_async = self.eat(TokenKind::Async); if is_async { // test_err comprehension_missing_for_after_async // (async) // (x async x in iter) self.expect(TokenKind::For); } else { self.bump(TokenKind::For); } let mut target = self.parse_expression_list(ExpressionContext::starred_conditional().with_in_excluded()); helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); self.validate_assignment_target(&target.expr); self.expect(TokenKind::In); let iter = self.parse_simple_expression(ExpressionContext::default()); let ifs_snapshot = self.expr_scratch.snapshot(); let mut progress = ParserProgress::default(); while self.eat(TokenKind::If) { progress.assert_progressing(self); let parsed_expr = self.parse_simple_expression(ExpressionContext::default()); self.expr_scratch.push(parsed_expr.expr); } ast::Comprehension { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, target: target.expr, iter: iter.expr, ifs: self.expr_scratch.take(ifs_snapshot), is_async, } } /// Parses a generator expression. /// /// The given `start` offset is the start of either the opening parenthesis if the generator is /// parenthesized or the first token of the expression. /// /// See: fn parse_generator_expression( &mut self, element: Expr, start: TextSize, parenthesized: Parenthesized, ) -> ast::ExprGenerator { let generators = self.parse_generators(); if parenthesized.is_yes() { self.expect(TokenKind::Rpar); } ast::ExprGenerator { elt: Box::new(element), generators, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, parenthesized: parenthesized.is_yes(), } } /// Parses a list comprehension expression. /// /// See: fn parse_list_comprehension_expression( &mut self, element: Expr, start: TextSize, ) -> ast::ExprListComp { let generators = self.parse_generators(); self.expect(TokenKind::Rsqb); ast::ExprListComp { elt: Box::new(element), generators, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a dictionary comprehension expression. /// /// See: fn parse_dictionary_comprehension_expression( &mut self, key: Option, value: Expr, start: TextSize, ) -> ast::ExprDictComp { let generators = self.parse_generators(); self.expect(TokenKind::Rbrace); ast::ExprDictComp { key: key.map(Box::new), value: Box::new(value), generators, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a set comprehension expression. /// /// See: fn parse_set_comprehension_expression( &mut self, element: Expr, start: TextSize, ) -> ast::ExprSetComp { let generators = self.parse_generators(); self.expect(TokenKind::Rbrace); ast::ExprSetComp { elt: Box::new(element), generators, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a starred expression with the given precedence. /// /// The expression is parsed with the highest precedence. If the precedence /// of the parsed expression is lower than the given precedence, an error /// is reported. /// /// For example, if the given precedence is [`StarredExpressionPrecedence::BitOr`], /// the comparison expression is not allowed. /// /// Refer to the [Python grammar] for more information. /// /// # Panics /// /// If the parser isn't positioned at a `*` token. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_starred_expression(&mut self, context: ExpressionContext) -> ast::ExprStarred { let start = self.node_start(); self.bump(TokenKind::Star); let parsed_expr = match context.starred_expression_precedence() { StarredExpressionPrecedence::Conditional => self .parse_conditional_expression_or_higher_impl( // test_err starred_starred_expression // print(* // *[]) // print(* *[]) context.disallow_starred_expressions(), ), StarredExpressionPrecedence::BitwiseOr => { self.parse_expression_with_bitwise_or_precedence() } }; ast::ExprStarred { value: Box::new(parsed_expr.expr), ctx: ExprContext::Load, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `await` expression. /// /// # Panics /// /// If the parser isn't positioned at an `await` token. /// /// See: fn parse_await_expression(&mut self) -> ast::ExprAwait { let start = self.node_start(); self.bump(TokenKind::Await); let parsed_expr = self.parse_binary_expression_or_higher( OperatorPrecedence::Await, ExpressionContext::default(), ); ast::ExprAwait { value: Box::new(parsed_expr.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `yield` expression. /// /// # Panics /// /// If the parser isn't positioned at a `yield` token. /// /// See: fn parse_yield_expression(&mut self) -> Expr { let start = self.node_start(); self.bump(TokenKind::Yield); if self.eat(TokenKind::From) { return self.parse_yield_from_expression(start); } let value = self.at_expr().then(|| { let parsed_expr = self.parse_expression_list(ExpressionContext::starred_bitwise_or()); // test_ok iter_unpack_yield_py37 // # parse_options: {"target-version": "3.7"} // rest = (4, 5, 6) // def g(): yield (1, 2, 3, *rest) // test_ok iter_unpack_yield_py38 // # parse_options: {"target-version": "3.8"} // rest = (4, 5, 6) // def g(): yield 1, 2, 3, *rest // def h(): yield 1, (yield 2, *rest), 3 // test_err iter_unpack_yield_py37 // # parse_options: {"target-version": "3.7"} // rest = (4, 5, 6) // def g(): yield 1, 2, 3, *rest // def h(): yield 1, (yield 2, *rest), 3 self.check_tuple_unpacking( &parsed_expr, UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Yield), ); Box::new(parsed_expr.expr) }); Expr::Yield(ast::ExprYield { value, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } /// Parses a `yield from` expression. /// /// This method should not be used directly. Use [`Parser::parse_yield_expression`] /// even when parsing a `yield from` expression. /// /// See: fn parse_yield_from_expression(&mut self, start: TextSize) -> Expr { // Grammar: // 'yield' 'from' expression // // Here, a tuple expression isn't allowed without the parentheses. But, we // allow it here to report better error message. // // Now, this also solves another problem. Take the following example: // // ```python // yield from x, y // ``` // // If we didn't use the `parse_expression_list` method here, the parser // would have stopped at the comma. Then, the outer expression would // have been a tuple expression with two elements: `yield from x` and `y`. let expr = self .parse_expression_list(ExpressionContext::default()) .expr; match &expr { Expr::Tuple(tuple) if !tuple.parenthesized => { self.add_error(ParseErrorType::UnparenthesizedTupleExpression, &expr); } _ => {} } Expr::YieldFrom(ast::ExprYieldFrom { value: Box::new(expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } /// Parses a named expression (`:=`). /// /// # Panics /// /// If the parser isn't positioned at a `:=` token. /// /// See: fn parse_named_expression(&mut self, mut target: Expr, start: TextSize) -> ast::ExprNamed { self.bump(TokenKind::ColonEqual); if !target.is_name_expr() { self.add_error(ParseErrorType::InvalidNamedAssignmentTarget, target.range()); } helpers::set_expr_ctx(&mut target, ExprContext::Store); let value = self.parse_conditional_expression_or_higher(); let range = self.node_range(start); // test_err walrus_py37 // # parse_options: { "target-version": "3.7" } // (x := 1) // test_ok walrus_py38 // # parse_options: { "target-version": "3.8" } // (x := 1) self.add_unsupported_syntax_error(UnsupportedSyntaxErrorKind::Walrus, range); ast::ExprNamed { target: Box::new(target), value: Box::new(value.expr), range, node_index: AtomicNodeIndex::NONE, } } /// Parses a lambda expression. /// /// # Panics /// /// If the parser isn't positioned at a `lambda` token. /// /// See: fn parse_lambda_expr(&mut self) -> ast::ExprLambda { let start = self.node_start(); self.bump(TokenKind::Lambda); let parameters = if self.at(TokenKind::Colon) { // test_ok lambda_with_no_parameters // lambda: 1 None } else { Some(Box::new(self.parse_parameters(FunctionKind::Lambda))) }; self.expect(TokenKind::Colon); // test_ok lambda_with_valid_body // lambda x: x // lambda x: x if True else y // lambda x: await x // lambda x: lambda y: x + y // lambda x: (yield x) # Parenthesized `yield` is fine // lambda x: x, *y // test_err lambda_body_with_starred_expr // lambda x: *y // lambda x: *y, // lambda x: *y, z // lambda x: *y and z // test_err lambda_body_with_yield_expr // lambda x: yield y // lambda x: yield from y // `lambda: lambda: lambda: ...` recurses through the lambda body at // the conditional layer, bypassing the `parse_lhs_expression` guard. let body = if let Some(body) = self.with_recursion(Self::parse_conditional_expression_or_higher) { body } else { self.report_recursion_limit_exceeded(self.current_token_range()); self.recursion_recovery_expr() }; ast::ExprLambda { body: Box::new(body.expr), parameters, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `if` expression. /// /// # Panics /// /// If the parser isn't positioned at an `if` token. /// /// See: fn parse_if_expression(&mut self, body: Expr, start: TextSize) -> ast::ExprIf { self.bump(TokenKind::If); let test = self.parse_simple_expression(ExpressionContext::default()); self.expect(TokenKind::Else); // `a if b else a if b else ...` recurses through `orelse` at the // conditional layer, which is not covered by the `parse_lhs_expression` // guard (that scope is released once each atom is parsed). Guard here. let orelse = if let Some(orelse) = self.with_recursion(Self::parse_conditional_expression_or_higher) { orelse } else { self.report_recursion_limit_exceeded(self.current_token_range()); self.recursion_recovery_expr() }; ast::ExprIf { body: Box::new(body), test: Box::new(test.expr), orelse: Box::new(orelse.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an IPython escape command at the expression level. /// /// # Panics /// /// If the parser isn't positioned at a `IpyEscapeCommand` token. /// If the escape command kind is not `%` or `!`. fn parse_ipython_escape_command_expression(&mut self) -> ast::ExprIpyEscapeCommand { let start = self.node_start(); let (value, kind) = self.bump_ipython_escape_command(IpyEscapeContext::Assignment); if !matches!(kind, IpyEscapeKind::Magic | IpyEscapeKind::Shell) { // This should never occur as the lexer won't allow it. unreachable!("IPython escape command expression is only allowed for % and !"); } let command = ast::ExprIpyEscapeCommand { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, kind, value, }; if self.options.mode != Mode::Ipython { self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, &command); } command } /// Performs the following validations on the arguments: /// 1. There aren't any duplicate keyword argument /// 2. Generator expressions are parenthesized when required by the argument context. fn validate_arguments( &mut self, arguments: &ast::Arguments, has_trailing_comma: bool, context: ArgumentsContext, ) { let mut all_arg_names = FxHashSet::with_capacity_and_hasher(arguments.keywords.len(), FxBuildHasher); for (name, range) in arguments .keywords .iter() .filter_map(|argument| argument.arg.as_ref().map(|arg| (arg, argument.range))) { let arg_name = name.as_str(); if !all_arg_names.insert(arg_name) { self.add_error( ParseErrorType::DuplicateKeywordArgumentError(arg_name.to_string()), range, ); } } let generator_must_be_parenthesized = match context { ArgumentsContext::Call => has_trailing_comma || arguments.len() > 1, // CPython rejects an unparenthesized generator expression as a class base even though // this restriction isn't specified in the class definition grammar. ArgumentsContext::ClassDefinition => true, }; if generator_must_be_parenthesized { for arg in &*arguments.args { if let Some(ast::ExprGenerator { range, parenthesized: false, .. }) = arg.as_generator_expr() { // test_ok args_unparenthesized_generator // zip((x for x in range(10)), (y for y in range(10))) // sum(x for x in range(10)) // sum((x for x in range(10)),) // test_err args_unparenthesized_generator // sum(x for x in range(10), 5) // total(1, 2, x for x in range(5), 6) // sum(x for x in range(10),) self.add_error(ParseErrorType::UnparenthesizedGeneratorExpression, range); } } } } } /// Identifies the syntactic context for an argument list. /// /// Unlike calls, class definitions require a sole generator expression to be parenthesized: /// /// ```python /// f(x for x in xs) /// class C((x for x in xs)): ... /// ``` #[derive(Debug, Copy, Clone)] pub(super) enum ArgumentsContext { Call, ClassDefinition, } #[derive(Debug)] pub(super) struct ParsedExpr { pub(super) expr: Expr, pub(super) is_parenthesized: bool, } impl ParsedExpr { #[inline] pub(super) const fn is_unparenthesized_starred_expr(&self) -> bool { !self.is_parenthesized && self.expr.is_starred_expr() } #[inline] const fn is_unparenthesized_named_expr(&self) -> bool { !self.is_parenthesized && self.expr.is_named_expr() } } impl From for ParsedExpr { #[inline] fn from(expr: Expr) -> Self { ParsedExpr { expr, is_parenthesized: false, } } } impl Deref for ParsedExpr { type Target = Expr; fn deref(&self) -> &Self::Target { &self.expr } } impl Ranged for ParsedExpr { #[inline] fn range(&self) -> TextRange { self.expr.range() } } #[derive(Debug)] enum BinaryLikeOperator { Boolean(BoolOp), Comparison(CmpOp), Binary(Operator), } impl BinaryLikeOperator { /// Attempts to convert the token into the corresponding binary-like operator. `next` is /// required to distinguish `is not` and `not in` from their one-token alternatives. /// Returns [None] if it's not a binary-like operator. fn try_from_tokens(current: TokenKind, next: Option) -> Option { if let Some(bool_op) = current.as_bool_operator() { Some(BinaryLikeOperator::Boolean(bool_op)) } else if let Some(bin_op) = current.as_binary_operator() { Some(BinaryLikeOperator::Binary(bin_op)) } else { helpers::token_kind_to_cmp_op(current, next).map(BinaryLikeOperator::Comparison) } } /// Returns the [`OperatorPrecedence`] for the given operator token or [None] if the token /// isn't an operator token. fn precedence(&self) -> OperatorPrecedence { match self { BinaryLikeOperator::Boolean(bool_op) => OperatorPrecedence::from(*bool_op), BinaryLikeOperator::Comparison(_) => OperatorPrecedence::ComparisonsMembershipIdentity, BinaryLikeOperator::Binary(bin_op) => OperatorPrecedence::from(*bin_op), } } } /// Represents the precedence used for parsing the value part of a starred expression. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(super) enum StarredExpressionPrecedence { /// Matches `'*' bitwise_or` which is part of the `star_expression` rule in the /// [Python grammar](https://docs.python.org/3/reference/grammar.html). BitwiseOr, /// Matches `'*' expression` which is part of the `starred_expression` rule in the /// [Python grammar](https://docs.python.org/3/reference/grammar.html). Conditional, } /// Represents the expression parsing context. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub(super) struct ExpressionContext(ExpressionContextFlags); bitflags! { #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] struct ExpressionContextFlags: u8 { /// This flag is set when the `in` keyword should be excluded from a comparison expression. /// It is to avoid ambiguity in `for ... in ...` statements. const EXCLUDE_IN = 1 << 0; /// This flag is set when a starred expression should be allowed. This doesn't affect the /// parsing of a starred expression as it will be parsed nevertheless. But, if it is not /// allowed, an error is reported. const ALLOW_STARRED_EXPRESSION = 1 << 1; /// This flag is set when the value of a starred expression should be limited to bitwise OR /// precedence. Matches the `* bitwise_or` grammar rule if set. const STARRED_BITWISE_OR_PRECEDENCE = 1 << 2; /// This flag is set when a yield expression should be allowed. This doesn't affect the /// parsing of a yield expression as it will be parsed nevertheless. But, if it is not /// allowed, an error is reported. const ALLOW_YIELD_EXPRESSION = 1 << 3; /// This flag is set when the `for` keyword, or `async` starting `async for`, should be /// excluded from an expression. const EXCLUDE_FOR = 1 << 4; } } impl ExpressionContext { /// Create a new context allowing starred expression at conditional precedence. pub(super) fn starred_conditional() -> Self { ExpressionContext::default() .with_starred_expression_allowed(StarredExpressionPrecedence::Conditional) } /// Create a new context allowing starred expression at bitwise OR precedence. pub(super) fn starred_bitwise_or() -> Self { ExpressionContext::default() .with_starred_expression_allowed(StarredExpressionPrecedence::BitwiseOr) } /// Create a new context allowing starred expression at bitwise OR precedence or yield /// expression. pub(super) fn yield_or_starred_bitwise_or() -> Self { ExpressionContext::starred_bitwise_or().with_yield_expression_allowed() } fn disallow_starred_expressions(self) -> Self { let flags = self.0 & !ExpressionContextFlags::ALLOW_STARRED_EXPRESSION; ExpressionContext(flags) } fn disallow_yield_expressions(self) -> Self { ExpressionContext(self.0 & !ExpressionContextFlags::ALLOW_YIELD_EXPRESSION) } /// Returns a new [`ExpressionContext`] which allows starred expression with the given /// precedence. fn with_starred_expression_allowed(self, precedence: StarredExpressionPrecedence) -> Self { let mut flags = self.0 | ExpressionContextFlags::ALLOW_STARRED_EXPRESSION; match precedence { StarredExpressionPrecedence::BitwiseOr => { flags |= ExpressionContextFlags::STARRED_BITWISE_OR_PRECEDENCE; } StarredExpressionPrecedence::Conditional => { flags -= ExpressionContextFlags::STARRED_BITWISE_OR_PRECEDENCE; } } ExpressionContext(flags) } /// Returns a new [`ExpressionContext`] which allows yield expression. fn with_yield_expression_allowed(self) -> Self { ExpressionContext(self.0 | ExpressionContextFlags::ALLOW_YIELD_EXPRESSION) } /// Returns a new [`ExpressionContext`] which excludes `in` as part of a comparison expression. pub(super) fn with_in_excluded(self) -> Self { ExpressionContext(self.0 | ExpressionContextFlags::EXCLUDE_IN) } /// Returns a new [`ExpressionContext`] which excludes `for` from an expression. fn with_for_excluded(self) -> Self { ExpressionContext(self.0 | ExpressionContextFlags::EXCLUDE_FOR) } /// Returns `true` if the `in` keyword should be excluded from a comparison expression. const fn is_in_excluded(self) -> bool { self.0.contains(ExpressionContextFlags::EXCLUDE_IN) } /// Returns `true` if starred expressions are allowed. const fn is_starred_expression_allowed(self) -> bool { self.0 .contains(ExpressionContextFlags::ALLOW_STARRED_EXPRESSION) } /// Returns `true` if yield expressions are allowed. const fn is_yield_expression_allowed(self) -> bool { self.0 .contains(ExpressionContextFlags::ALLOW_YIELD_EXPRESSION) } /// Returns `true` if `for` should be excluded from the expression. const fn is_for_excluded(self) -> bool { self.0.contains(ExpressionContextFlags::EXCLUDE_FOR) } /// Returns the [`StarredExpressionPrecedence`] for the context, regardless of whether starred /// expressions are allowed or not. const fn starred_expression_precedence(self) -> StarredExpressionPrecedence { if self .0 .contains(ExpressionContextFlags::STARRED_BITWISE_OR_PRECEDENCE) { StarredExpressionPrecedence::BitwiseOr } else { StarredExpressionPrecedence::Conditional } } } #[derive(Debug)] struct InterpolatedStringData { elements: InterpolatedStringElements, range: TextRange, flags: AnyStringFlags, } impl From for FString { fn from(value: InterpolatedStringData) -> Self { Self { elements: value.elements, range: value.range, flags: value.flags.into(), node_index: AtomicNodeIndex::NONE, } } } impl From for TString { fn from(value: InterpolatedStringData) -> Self { Self { elements: value.elements, range: value.range, flags: value.flags.into(), node_index: AtomicNodeIndex::NONE, } } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/helpers.rs000064400000000000000000000107411046102023000226420ustar00use ruff_python_ast::token::TokenKind; use ruff_python_ast::{self as ast, CmpOp, Expr, ExprContext, Number}; use ruff_text_size::{Ranged, TextRange}; use crate::error::RelaxedDecoratorError; /// Set the `ctx` for `Expr::Id`, `Expr::Attribute`, `Expr::Subscript`, `Expr::Starred`, /// `Expr::Tuple` and `Expr::List`. If `expr` is either `Expr::Tuple` or `Expr::List`, /// recursively sets the `ctx` for their elements. pub(super) fn set_expr_ctx(expr: &mut Expr, new_ctx: ExprContext) { match expr { Expr::Name(ast::ExprName { ctx, .. }) | Expr::Attribute(ast::ExprAttribute { ctx, .. }) | Expr::Subscript(ast::ExprSubscript { ctx, .. }) => *ctx = new_ctx, Expr::Starred(ast::ExprStarred { value, ctx, .. }) => { *ctx = new_ctx; set_expr_ctx(value, new_ctx); } Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => { set_expr_ctx(operand, new_ctx); } Expr::List(ast::ExprList { elts, ctx, .. }) | Expr::Tuple(ast::ExprTuple { elts, ctx, .. }) => { *ctx = new_ctx; for element in elts.iter_mut() { set_expr_ctx(element, new_ctx); } } _ => {} } } /// Converts a [`TokenKind`] into its corresponding [`CmpOp`]. /// /// `next` is only needed to distinguish `is not` and `not in`. pub(super) const fn token_kind_to_cmp_op( current: TokenKind, next: Option, ) -> Option { Some(match (current, next) { (TokenKind::Is, Some(TokenKind::Not)) => CmpOp::IsNot, (TokenKind::Is, _) => CmpOp::Is, (TokenKind::Not, Some(TokenKind::In)) => CmpOp::NotIn, (TokenKind::In, _) => CmpOp::In, (TokenKind::EqEqual, _) => CmpOp::Eq, (TokenKind::NotEqual, _) => CmpOp::NotEq, (TokenKind::Less, _) => CmpOp::Lt, (TokenKind::LessEqual, _) => CmpOp::LtE, (TokenKind::Greater, _) => CmpOp::Gt, (TokenKind::GreaterEqual, _) => CmpOp::GtE, _ => return None, }) } /// Helper for `parse_decorators` to determine if `expr` is a [`dotted_name`] from the decorator /// grammar before Python 3.9. /// /// Returns `Some((error, range))` if `expr` is not a `dotted_name`, or `None` if it is a `dotted_name`. /// /// [`dotted_name`]: https://docs.python.org/3.8/reference/compound_stmts.html#grammar-token-dotted-name pub(super) fn detect_invalid_pre_py39_decorator_node( expr: &Expr, ) -> Option<(RelaxedDecoratorError, TextRange)> { let description = match expr { Expr::Name(_) => return None, Expr::Attribute(attribute) => { return detect_invalid_pre_py39_decorator_node(&attribute.value); } Expr::Call(_) => return Some((RelaxedDecoratorError::CallExpression, expr.range())), Expr::NumberLiteral(number) => match &number.value { Number::Int(_) => "an int literal", Number::Float(_) => "a float literal", Number::Complex { .. } => "a complex literal", }, Expr::BoolOp(_) => "boolean expression", Expr::BinOp(_) => "binary-operation expression", Expr::UnaryOp(_) => "unary-operation expression", Expr::Await(_) => "`await` expression", Expr::Lambda(_) => "lambda expression", Expr::If(_) => "conditional expression", Expr::Dict(_) => "a dict literal", Expr::Set(_) => "a set literal", Expr::List(_) => "a list literal", Expr::Tuple(_) => "a tuple literal", Expr::Starred(_) => "starred expression", Expr::Slice(_) => "slice expression", Expr::BytesLiteral(_) => "a bytes literal", Expr::StringLiteral(_) => "a string literal", Expr::EllipsisLiteral(_) => "an ellipsis literal", Expr::NoneLiteral(_) => "a `None` literal", Expr::BooleanLiteral(_) => "a boolean literal", Expr::ListComp(_) => "a list comprehension", Expr::SetComp(_) => "a set comprehension", Expr::DictComp(_) => "a dict comprehension", Expr::Generator(_) => "generator expression", Expr::Yield(_) => "`yield` expression", Expr::YieldFrom(_) => "`yield from` expression", Expr::Compare(_) => "comparison expression", Expr::FString(_) => "f-string", Expr::TString(_) => "t-string", Expr::Named(_) => "assignment expression", Expr::Subscript(_) => "subscript expression", Expr::IpyEscapeCommand(_) => "IPython escape command", }; Some((RelaxedDecoratorError::Other(description), expr.range())) } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/mod.rs000064400000000000000000002122531046102023000217610ustar00use std::borrow::Cow; use std::cmp::Ordering; use std::str::FromStr; use bitflags::bitflags; use ruff_python_ast::name::Name; use ruff_python_ast::token::TokenKind; use ruff_python_ast::{ Alias, AtomicNodeIndex, ElifElseClause, Expr, Int, IpyEscapeKind, Keyword, Mod, ModExpression, ModModule, ParameterWithDefault, Stmt, StringFlags, }; use ruff_python_trivia::is_python_whitespace; use ruff_text_size::{Ranged, TextRange, TextSize}; use rustc_hash::FxHashSet; use thin_vec::ThinVec; use unicode_normalization::UnicodeNormalization; use crate::error::UnsupportedSyntaxError; use crate::parser::expression::ExpressionContext; use crate::parser::progress::{ParserProgress, TokenId}; use crate::parser::scratch_buffer::ScratchBuffer; use crate::string::InterpolatedStringKind; use crate::token_set::TokenSet; use crate::token_source::{TokenSource, TokenSourceCheckpoint}; use crate::{Mode, ParseError, ParseErrorType, UnsupportedSyntaxErrorKind}; use crate::{Parsed, Tokens}; pub use crate::parser::options::ParseOptions; mod expression; mod helpers; mod options; mod pattern; mod progress; mod recovery; mod scratch_buffer; mod statement; #[cfg(test)] mod tests; #[derive(Debug, Default)] struct NameInterner { names: FxHashSet, } impl NameInterner { /// Returns an inline name directly, or a shared clone of a heap-allocated name. fn intern(&mut self, text: &str) -> Name { if let Some(name) = Name::new_inline(text) { return name; } if let Some(name) = self.names.get(text) { return name.clone(); } let name = Name::new_heap(text); self.names.insert(name.clone()); name } } #[derive(Debug)] pub(crate) struct Parser<'src> { source: &'src str, /// Token source for the parser that skips over any non-trivia token. tokens: TokenSource<'src>, /// Deduplicates the backing allocations for repeated names that do not fit inline. name_interner: NameInterner, /// Reusable storage for names that need to be constructed by the parser. name_buffer: String, /// Stores all the syntax errors found during the parsing. errors: Vec, /// Stores non-fatal syntax errors found during parsing, such as version-related errors. unsupported_syntax_errors: Vec, /// Options for how the code will be parsed. options: ParseOptions, /// The ID of the current token. This is used to track the progress of the parser /// to avoid infinite loops when the parser is stuck. current_token_id: TokenId, /// The end of the previous token processed. This is used to determine a node's end. prev_token_end: TextSize, /// The recovery context in which the parser is currently in. recovery_context: RecoveryContext, /// The start offset in the source code from which to start parsing at. start_offset: TextSize, /// Current parser recursion depth remaining before the depth limit is exceeded. depth_remaining: u16, /// Maximum lexer nesting depth before postfix calls and subscripts should stop recursing. max_nesting_depth: u32, /// Reusable, nesting-safe scratch storage for expression lists. expr_scratch: ScratchBuffer, /// Reusable, nesting-safe scratch storage for call keywords. keyword_scratch: ScratchBuffer, /// Reusable, nesting-safe scratch storage for function and lambda parameters. parameter_scratch: ScratchBuffer, /// Reusable, nesting-safe scratch storage for statement lists. stmt_scratch: ScratchBuffer, /// Reusable scratch storage for import aliases. alias_scratch: ScratchBuffer, /// Reusable, nesting-safe scratch storage for `elif` and `else` clauses. elif_else_scratch: ScratchBuffer, } impl<'src> Parser<'src> { /// Create a new parser for the given source code. pub(crate) fn new(source: &'src str, options: ParseOptions) -> Self { Parser::new_starts_at(source, TextSize::new(0), options) } /// Create a new parser for the given source code which starts parsing at the given offset. pub(crate) fn new_starts_at( source: &'src str, start_offset: TextSize, options: ParseOptions, ) -> Self { let tokens = TokenSource::from_source(source, options.mode, start_offset); let depth_remaining = options.max_recursion_depth; let max_nesting_depth = u32::from(options.max_recursion_depth.saturating_sub(2)); Parser { options, source, errors: Vec::new(), unsupported_syntax_errors: Vec::new(), tokens, name_interner: NameInterner::default(), name_buffer: String::new(), recovery_context: RecoveryContext::empty(), prev_token_end: TextSize::new(0), start_offset, current_token_id: TokenId::default(), depth_remaining, max_nesting_depth, expr_scratch: ScratchBuffer::with_capacity(16), keyword_scratch: ScratchBuffer::new(), parameter_scratch: ScratchBuffer::new(), stmt_scratch: ScratchBuffer::with_capacity(32), alias_scratch: ScratchBuffer::new(), elif_else_scratch: ScratchBuffer::new(), } } /// Runs `f` if the recursive parser depth limit has not been hit. /// /// # Note /// /// This recursion guard is a temporary fix for #22930. #[must_use] #[inline] fn with_recursion(&mut self, f: impl FnOnce(&mut Self) -> T) -> Option { if self.depth_remaining == 0 { return None; } self.depth_remaining -= 1; let result = f(self); self.depth_remaining += 1; Some(result) } #[cold] #[inline(never)] fn report_recursion_limit_exceeded(&mut self, ranged: R) { self.add_error(ParseErrorType::RecursionLimitExceeded, ranged); // Skip to end-of-file so outer parser frames unwind quickly and our // `ParserProgress` infinite-loop guards don't fire when they see the // same `(` / `[` etc. that this frame failed to consume. while self.current_token_kind() != TokenKind::EndOfFile { self.bump_any(); } } /// Consumes the [`Parser`] and returns the parsed [`Parsed`]. pub(crate) fn parse(mut self) -> Parsed { let syntax = match self.options.mode { Mode::Expression | Mode::ParenthesizedExpression => { Mod::Expression(self.parse_single_expression()) } Mode::Module | Mode::Ipython => Mod::Module(self.parse_module()), }; self.finish(syntax) } /// Parses a single expression. /// /// This is to be used for [`Mode::Expression`]. /// /// ## Recovery /// /// After parsing a single expression, an error is reported and all remaining tokens are /// dropped by the parser. fn parse_single_expression(&mut self) -> ModExpression { let start = self.node_start(); let parsed_expr = self.parse_expression_list(ExpressionContext::default()); // All remaining newlines are actually going to be non-logical newlines. self.eat(TokenKind::Newline); if !self.at(TokenKind::EndOfFile) { self.add_error( ParseErrorType::UnexpectedExpressionToken, self.current_token_range(), ); // TODO(dhruvmanila): How should error recovery work here? Just truncate after the expression? let mut progress = ParserProgress::default(); loop { progress.assert_progressing(self); if self.at(TokenKind::EndOfFile) { break; } self.bump_any(); } } self.bump(TokenKind::EndOfFile); ModExpression { body: Box::new(parsed_expr.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a Python module. /// /// This is to be used for [`Mode::Module`] and [`Mode::Ipython`]. fn parse_module(&mut self) -> ModModule { let body = self.parse_list_into_thin_vec(RecoveryContextKind::ModuleStatements, |p| { p.parse_statement() }); self.bump(TokenKind::EndOfFile); ModModule { body, range: TextRange::new(self.start_offset, self.current_token_range().end()), node_index: AtomicNodeIndex::NONE, } } fn finish(self, syntax: Mod) -> Parsed { assert_eq!( self.current_token_kind(), TokenKind::EndOfFile, "Parser should be at the end of the file." ); // TODO consider re-integrating lexical error handling into the parser? let parse_errors = self.errors; let (tokens, lex_errors) = self.tokens.finish(); // Fast path for when there are no lex errors. // There's no fast path for when there are no parse errors because a lex error // always results in a parse error. if lex_errors.is_empty() { return Parsed { syntax, tokens: Tokens::new(tokens), errors: parse_errors, unsupported_syntax_errors: self.unsupported_syntax_errors, }; } let mut merged = Vec::with_capacity(parse_errors.len().saturating_add(lex_errors.len())); let mut parse_errors = parse_errors.into_iter().peekable(); let mut lex_errors = lex_errors.into_iter().peekable(); while let (Some(parse_error), Some(lex_error)) = (parse_errors.peek(), lex_errors.peek()) { match parse_error .location .start() .cmp(&lex_error.location().start()) { Ordering::Less => merged.push(parse_errors.next().unwrap()), Ordering::Equal => { // Skip the parse error if we already have a lex error at the same location.. parse_errors.next().unwrap(); merged.push(lex_errors.next().unwrap().into()); } Ordering::Greater => merged.push(lex_errors.next().unwrap().into()), } } merged.extend(parse_errors); merged.extend(lex_errors.map(ParseError::from)); Parsed { syntax, tokens: Tokens::new(tokens), errors: merged, unsupported_syntax_errors: self.unsupported_syntax_errors, } } /// Returns the start position for a node that starts at the current token. fn node_start(&self) -> TextSize { self.current_token_range().start() } fn node_range(&self, start: TextSize) -> TextRange { // It's possible during error recovery that the parsing didn't consume any tokens. In that // case, `last_token_end` still points to the end of the previous token but `start` is the // start of the current token. Calling `TextRange::new(start, self.last_token_end)` would // panic in that case because `start > end`. This path "detects" this case and creates an // empty range instead. // // The reason it's `<=` instead of just `==` is because there could be whitespaces between // the two tokens. For example: // // ```python // # last token end // # | current token (newline) start // # v v // def foo \n // # ^ // # assume there's trailing whitespace here // ``` // // Or, there could tokens that are considered "trivia" and thus aren't emitted by the token // source. These are comments and non-logical newlines. For example: // // ```python // # last token end // # v // def foo # comment\n // # ^ current token (newline) start // ``` // // In either of the above cases, there's a "gap" between the end of the last token and start // of the current token. if self.prev_token_end <= start { // We need to create an empty range at the last token end instead of the start because // otherwise this node range will fall outside the range of it's parent node. Taking // the above example: // // ```python // if True: // # function start // # | function end // # v v // def foo # comment // # ^ current token start // ``` // // Here, the current token start is the start of parameter range but the function ends // at `foo`. Even if there's a function body, the range of parameters would still be // before the comment. // test_err node_range_with_gaps // def foo # comment // def bar(): ... // def baz TextRange::empty(self.prev_token_end) } else { TextRange::new(start, self.prev_token_end) } } fn missing_node_range(&self) -> TextRange { // TODO(dhruvmanila): This range depends on whether the missing node is // on the leftmost or the rightmost of the expression. It's incorrect for // the leftmost missing node because the range is outside the expression // range. For example, // // ```python // value = ** y // # ^^^^ expression range // # ^ last token end // ``` TextRange::empty(self.prev_token_end) } /// Moves the parser to the next token. fn do_bump(&mut self, kind: TokenKind) { if match self.current_token_kind() { // TODO explore including everything up to the dedent as part of the body. TokenKind::Dedent => false, // Don't include newlines in the body TokenKind::Newline => false, // TODO(micha): Including the semi feels more correct but it isn't compatible with lalrpop and breaks the // formatters semicolon detection. Exclude it for now TokenKind::Semi => false, _ => true, } { self.prev_token_end = self.current_token_range().end(); } self.tokens.bump(kind); self.current_token_id.increment(); } /// Returns the next token kind without consuming it. fn peek(&mut self) -> TokenKind { self.tokens.peek() } /// Returns the next two token kinds without consuming it. fn peek2(&mut self) -> (TokenKind, TokenKind) { self.tokens.peek2() } /// Returns the current token kind. #[inline] fn current_token_kind(&self) -> TokenKind { self.tokens.current_kind() } /// Returns the range of the current token. #[inline] fn current_token_range(&self) -> TextRange { self.tokens.current_range() } /// Returns the current token ID. #[inline] fn current_token_id(&self) -> TokenId { self.current_token_id } /// Bumps the current token assuming it is of the given kind. /// /// # Panics /// /// If the current token is not of the given kind. fn bump(&mut self, kind: TokenKind) { assert_eq!(self.current_token_kind(), kind); self.do_bump(kind); } fn bump_name(&mut self) -> Name { let text = self.current_token_text(); let name = if !self.tokens.current_flags().is_non_ascii_name() { self.intern_name(text) } else { self.intern_normalized_name(text) }; self.bump(TokenKind::Name); name } fn intern_name(&mut self, text: &str) -> Name { self.name_interner.intern(text) } fn intern_normalized_name(&mut self, text: &str) -> Name { let snapshot = self.name_buffer.len(); self.name_buffer.extend(text.nfkc()); let name = self.name_interner.intern(&self.name_buffer[snapshot..]); self.name_buffer.truncate(snapshot); name } fn bump_int(&mut self) -> Int { let text = self.current_token_text(); let value = if let Some(digits) = text.strip_prefix("0x").or_else(|| text.strip_prefix("0X")) { Int::from_str_radix(&strip_underscores(digits), 16, text) } else if let Some(digits) = text.strip_prefix("0o").or_else(|| text.strip_prefix("0O")) { Int::from_str_radix(&strip_underscores(digits), 8, text) } else if let Some(digits) = text.strip_prefix("0b").or_else(|| text.strip_prefix("0B")) { Int::from_str_radix(&strip_underscores(digits), 2, text) } else { Int::from_str(&strip_underscores(text)) } .expect("lexer validated integer literal"); self.bump(TokenKind::Int); value } fn bump_float(&mut self) -> f64 { let value = f64::from_str(&strip_underscores(self.current_token_text())) .expect("lexer validated float literal"); self.bump(TokenKind::Float); value } fn bump_complex(&mut self) -> (f64, f64) { let text = self.current_token_text(); let value = f64::from_str(&strip_underscores(&text[..text.len() - 1])) .expect("lexer validated complex literal"); self.bump(TokenKind::Complex); (0.0, value) } fn bump_string_value(&mut self) -> &'src str { let range = self.current_token_range(); let flags = self.tokens.current_flags().as_any_string_flags(); let value_range = TextRange::new( range.start() + flags.opener_len(), range.end() - flags.closer_len(), ); let value = &self.source[value_range]; self.bump(TokenKind::String); value } fn bump_ipython_escape_command( &mut self, context: IpyEscapeContext, ) -> (Box, IpyEscapeKind) { let (value, kind) = self.parse_ipython_escape_command_value(context); self.bump(TokenKind::IpyEscapeCommand); (value, kind) } fn current_token_text(&self) -> &'src str { self.src_text(self.current_token_range()) } fn parse_ipython_escape_command_value( &self, context: IpyEscapeContext, ) -> (Box, IpyEscapeKind) { let raw = self.current_token_text(); let initial_kind = if context.is_logical_line_start() && let Ok(kind) = IpyEscapeKind::try_from([ raw.as_bytes()[0] as char, raw[1..].chars().next().unwrap_or('\0'), ]) { kind } else { IpyEscapeKind::try_from(raw.as_bytes()[0] as char).expect("IPython escape token") }; let mut value = String::new(); let mut chars = raw[initial_kind.as_str().len()..].chars().peekable(); while let Some(c) = chars.next() { match c { '\\' if matches!(chars.peek(), Some('\r' | '\n')) => { if chars.next() == Some('\r') && matches!(chars.peek(), Some('\n')) { chars.next(); } } '?' => { let mut question_count = 1; while matches!(chars.peek(), Some('?')) { chars.next(); question_count += 1; } // At logical-line start, IPython treats one or two terminal `?` after a // nonempty help or magic command as the command kind. Strict `foo?` syntax // is parsed separately. // https://github.com/ipython/ipython/blob/292e3a23459ca965b8c1bfe2c3707044c510209a/IPython/core/inputtransformer2.py#L454-L462 if !context.is_logical_line_start() || !(initial_kind.is_magic() || initial_kind.is_help()) || question_count > 2 || value.chars().last().is_none_or(is_python_whitespace) || !matches!(chars.peek(), None | Some('\n' | '\r')) { value.extend(std::iter::repeat_n('?', question_count)); continue; } let kind = if question_count == 1 { IpyEscapeKind::Help } else { IpyEscapeKind::Help2 }; // A help suffix replaces a leading help prefix, but takes precedence over a // magic prefix, which remains part of the value (`%foo?` becomes help for // `%foo`). if initial_kind.is_help() { value = value.trim_start_matches([' ', '?']).to_string(); } else { value.insert_str(0, initial_kind.as_str()); } return (value.into_boxed_str(), kind); } '\n' | '\r' => break, c => value.push(c), } } (value.into_boxed_str(), initial_kind) } /// Bumps the current token assuming it is found in the given token set. /// /// # Panics /// /// If the current token is not found in the given token set. fn bump_ts(&mut self, ts: TokenSet) { let kind = self.current_token_kind(); assert!(ts.contains(kind)); self.do_bump(kind); } /// Bumps the current token regardless of its kind and advances to the next token. /// /// # Panics /// /// If the parser is at end of file. fn bump_any(&mut self) { let kind = self.current_token_kind(); assert_ne!(kind, TokenKind::EndOfFile); self.do_bump(kind); } /// Bumps the soft keyword token as a `Name` token. /// /// # Panics /// /// If the current token is not a soft keyword. fn bump_soft_keyword_as_name(&mut self) { assert!(self.at_soft_keyword()); self.do_bump(TokenKind::Name); } /// Consume the current token if it is of the given kind. Returns `true` if it matches, `false` /// otherwise. fn eat(&mut self, kind: TokenKind) -> bool { if self.at(kind) { self.do_bump(kind); true } else { false } } /// Eat the current token if its of the expected kind, otherwise adds an appropriate error. fn expect(&mut self, expected: TokenKind) -> bool { if self.eat(expected) { return true; } self.add_error( ParseErrorType::ExpectedToken { found: self.current_token_kind(), expected, }, self.current_token_range(), ); false } fn add_error(&mut self, error: ParseErrorType, ranged: T) where T: Ranged, { fn inner(errors: &mut Vec, error: ParseErrorType, range: TextRange) { // Avoid flagging multiple errors at the same location let is_same_location = errors .last() .is_some_and(|last| last.location.start() == range.start()); if !is_same_location { errors.push(ParseError { error, location: range, }); } } inner(&mut self.errors, error, ranged.range()); } /// Add an [`UnsupportedSyntaxError`] with the given [`UnsupportedSyntaxErrorKind`] and /// [`TextRange`] if its minimum version is less than [`Parser::target_version`]. fn add_unsupported_syntax_error(&mut self, kind: UnsupportedSyntaxErrorKind, range: TextRange) { if kind.is_unsupported(self.options.target_version) { self.unsupported_syntax_errors.push(UnsupportedSyntaxError { kind, range, target_version: self.options.target_version, }); } } /// Returns `true` if the current token is of the given kind. fn at(&self, kind: TokenKind) -> bool { self.current_token_kind() == kind } /// Returns `true` if the current token is found in the given token set. fn at_ts(&self, ts: TokenSet) -> bool { ts.contains(self.current_token_kind()) } fn src_text(&self, ranged: T) -> &'src str where T: Ranged, { &self.source[ranged.range()] } /// Parses a list of elements into a thin vector where each element is parsed using /// the given `parse_element` function. fn parse_list_into_thin_vec( &mut self, recovery_context_kind: RecoveryContextKind, parse_element: impl Fn(&mut Parser<'src>) -> T, ) -> ThinVec { let mut elements = ThinVec::new(); self.parse_list(recovery_context_kind, |p| elements.push(parse_element(p))); elements.shrink_to_fit(); elements } /// Parses a list of elements where each element is parsed using the given /// `parse_element` function. fn parse_list( &mut self, recovery_context_kind: RecoveryContextKind, mut parse_element: impl FnMut(&mut Parser<'src>), ) { let mut progress = ParserProgress::default(); let mut unexpected_indents = 0; let saved_context = self.recovery_context; self.recovery_context = self .recovery_context .union(RecoveryContext::from_kind(recovery_context_kind)); loop { progress.assert_progressing(self); if 0 < unexpected_indents && self.at(TokenKind::Dedent) { // Ignore this `Dedent` like we ignored the `Indent`, avoiding extra errors from // being imbalanced unexpected_indents -= 1; self.bump(TokenKind::Dedent); } else if recovery_context_kind.is_list_element(self) { parse_element(self); } else if recovery_context_kind.is_regular_list_terminator(self) { break; } else { // Run the error recovery: If the token is recognised as an element or terminator // of an enclosing list, then we try to re-lex in the context of a logical line and // break out of list parsing. if self.is_enclosing_list_element_or_terminator() { self.tokens.re_lex_logical_token(); break; } self.add_error( recovery_context_kind.create_error(self), self.current_token_range(), ); if matches!( recovery_context_kind, RecoveryContextKind::ModuleStatements | RecoveryContextKind::BlockStatements ) && self.at(TokenKind::Indent) { // For this invalid `Indent`, ensure the matching `Dedent` gets consumed as well unexpected_indents += 1; } self.bump_any(); } } self.recovery_context = saved_context; } /// Parses a comma separated list of elements into a vector where each element /// is parsed using the given `parse_element` function. fn parse_comma_separated_list_into_vec( &mut self, recovery_context_kind: RecoveryContextKind, parse_element: impl Fn(&mut Parser<'src>) -> T, ) -> Vec { self.parse_comma_separated_list_into_vec_with_capacity( recovery_context_kind, parse_element, 0, ) } /// Parses a comma separated list of elements into a vector with an initial capacity. fn parse_comma_separated_list_into_vec_with_capacity( &mut self, recovery_context_kind: RecoveryContextKind, parse_element: impl Fn(&mut Parser<'src>) -> T, capacity: usize, ) -> Vec { let mut elements = Vec::with_capacity(capacity); self.parse_comma_separated_list(recovery_context_kind, |p| elements.push(parse_element(p))); elements } /// Parses a comma separated list of elements where each element is parsed /// using the given `parse_element` function. /// /// The difference between this function and `parse_comma_separated_list_into_vec` /// is that this function does not return the parsed elements. Instead, it is the /// caller's responsibility to handle the parsed elements. This is the reason /// that the `parse_element` parameter is bound to [`FnMut`] instead of [`Fn`]. /// /// Returns `true` if there is a trailing comma present. fn parse_comma_separated_list( &mut self, recovery_context_kind: RecoveryContextKind, mut parse_element: impl FnMut(&mut Parser<'src>), ) -> bool { let mut progress = ParserProgress::default(); let saved_context = self.recovery_context; self.recovery_context = self .recovery_context .union(RecoveryContext::from_kind(recovery_context_kind)); let mut first_element = true; let mut trailing_comma_range: Option = None; loop { progress.assert_progressing(self); if recovery_context_kind.is_list_element(self) { parse_element(self); // Only unset this when we've completely parsed a single element. This is mainly to // raise the correct error in case the first element isn't valid and the current // token isn't a comma. Without this knowledge, the parser would later expect a // comma instead of raising the context error. first_element = false; let maybe_comma_range = self.current_token_range(); if self.eat(TokenKind::Comma) { trailing_comma_range = Some(maybe_comma_range); continue; } trailing_comma_range = None; } // test_ok comma_separated_regular_list_terminator // # The first element is parsed by `parse_list_like_expression` and the comma after // # the first element is expected by `parse_list_expression` // [0] // [0, 1] // [0, 1,] // [0, 1, 2] // [0, 1, 2,] if recovery_context_kind.is_regular_list_terminator(self) { break; } // test_err comma_separated_missing_comma_between_elements // # The comma between the first two elements is expected in `parse_list_expression`. // [0, 1 2] if recovery_context_kind.is_list_element(self) { // This is a special case to expect a comma between two elements and should be // checked before running the error recovery. This is because the error recovery // will always run as the parser is currently at a list element. self.expect(TokenKind::Comma); continue; } // Run the error recovery: If the token is recognised as an element or terminator of an // enclosing list, then we try to re-lex in the context of a logical line and break out // of list parsing. if self.is_enclosing_list_element_or_terminator() { self.tokens.re_lex_logical_token(); break; } if first_element || self.at(TokenKind::Comma) { // There are two conditions when we need to add the recovery context error: // // 1. If the parser is at a comma which means that there's a missing element // otherwise the comma would've been consumed by the first `eat` call above. // And, the parser doesn't take the re-lexing route on a comma token. // 2. If it's the first element and the current token is not a comma which means // that it's an invalid element. // test_err comma_separated_missing_element_between_commas // [0, 1, , 2] // test_err comma_separated_missing_first_element // call(= 1) self.add_error( recovery_context_kind.create_error(self), self.current_token_range(), ); trailing_comma_range = if self.at(TokenKind::Comma) { Some(self.current_token_range()) } else { None }; } else { // Otherwise, there should've been a comma at this position. This could be because // the element isn't consumed completely by `parse_element`. // test_err comma_separated_missing_comma // call(**x := 1) self.expect(TokenKind::Comma); trailing_comma_range = None; } self.bump_any(); } if let Some(trailing_comma_range) = trailing_comma_range { if !recovery_context_kind.allow_trailing_comma() { self.add_error( ParseErrorType::OtherError("Trailing comma not allowed".to_string()), trailing_comma_range, ); } } self.recovery_context = saved_context; trailing_comma_range.is_some() } #[cold] fn is_enclosing_list_element_or_terminator(&self) -> bool { for context in self.recovery_context.kind_iter() { if context.is_list_terminator(self) || context.is_list_element(self) { return true; } } false } /// Creates a checkpoint to which the parser can later return to using [`Self::rewind`]. fn checkpoint(&self) -> ParserCheckpoint { ParserCheckpoint { tokens: self.tokens.checkpoint(), errors_position: self.errors.len(), unsupported_syntax_errors_position: self.unsupported_syntax_errors.len(), current_token_id: self.current_token_id, prev_token_end: self.prev_token_end, recovery_context: self.recovery_context, } } /// Restore the parser to the given checkpoint. fn rewind(&mut self, checkpoint: ParserCheckpoint) { let ParserCheckpoint { tokens, errors_position, unsupported_syntax_errors_position, current_token_id, prev_token_end, recovery_context, } = checkpoint; self.tokens.rewind(tokens); self.errors.truncate(errors_position); self.unsupported_syntax_errors .truncate(unsupported_syntax_errors_position); self.current_token_id = current_token_id; self.prev_token_end = prev_token_end; self.recovery_context = recovery_context; } } fn strip_underscores(text: &str) -> Cow<'_, str> { if text.as_bytes().contains(&b'_') { Cow::Owned(text.chars().filter(|&c| c != '_').collect()) } else { Cow::Borrowed(text) } } #[derive(Copy, Clone)] enum IpyEscapeContext { Assignment, LogicalLineStart, } impl IpyEscapeContext { const fn is_logical_line_start(self) -> bool { matches!(self, Self::LogicalLineStart) } } struct ParserCheckpoint { tokens: TokenSourceCheckpoint, errors_position: usize, unsupported_syntax_errors_position: usize, current_token_id: TokenId, prev_token_end: TextSize, recovery_context: RecoveryContext, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum SequenceMatchPatternParentheses { Tuple, List, } impl SequenceMatchPatternParentheses { /// Returns the token kind that closes the parentheses. const fn closing_kind(self) -> TokenKind { match self { SequenceMatchPatternParentheses::Tuple => TokenKind::Rpar, SequenceMatchPatternParentheses::List => TokenKind::Rsqb, } } /// Returns `true` if the parentheses are for a list pattern e.g., `case [a, b]: ...`. const fn is_list(self) -> bool { matches!(self, SequenceMatchPatternParentheses::List) } } #[derive(Debug, PartialEq, Copy, Clone)] enum FunctionKind { /// A lambda expression, e.g., `lambda x: x` Lambda, /// A function definition, e.g., `def f(x): ...` FunctionDef, } impl FunctionKind { /// Returns the token that terminates a list of parameters. const fn list_terminator(self) -> TokenKind { match self { FunctionKind::Lambda => TokenKind::Colon, FunctionKind::FunctionDef => TokenKind::Rpar, } } } #[derive(Debug, PartialEq, Copy, Clone)] enum WithItemKind { /// A list of `with` items that are surrounded by parentheses. /// /// ```python /// with (item1, item2): ... /// with (item1, item2 as foo): ... /// ``` /// /// The parentheses belongs to the `with` statement. Parenthesized, /// The `with` item has a parenthesized expression. /// /// ```python /// with (item) as foo: ... /// ``` /// /// The parentheses belongs to the context expression. ParenthesizedExpression, /// The `with` items aren't parenthesized in any way. /// /// ```python /// with item: ... /// with item as foo: ... /// with item1, item2: ... /// ``` /// /// There are no parentheses around the items. Unparenthesized, } impl WithItemKind { /// Returns `true` if the with items are parenthesized. const fn is_parenthesized(self) -> bool { matches!(self, WithItemKind::Parenthesized) } } #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum InterpolatedStringElementsKind { /// The regular f-string elements. /// /// For example, the `"hello "`, `x`, and `" world"` elements in: /// ```py /// f"hello {x:.2f} world" /// ``` Regular(InterpolatedStringKind), /// The f-string elements are part of the format specifier. /// /// For example, the `.2f` in: /// ```py /// f"hello {x:.2f} world" /// ``` FormatSpec(InterpolatedStringKind), } impl InterpolatedStringElementsKind { const fn list_terminator(self) -> TokenKind { match self { InterpolatedStringElementsKind::Regular(string_kind) => string_kind.end_token(), // test_ok fstring_format_spec_terminator // f"hello {x:} world" // f"hello {x:.3f} world" InterpolatedStringElementsKind::FormatSpec(_) => TokenKind::Rbrace, } } } #[derive(Debug, PartialEq, Copy, Clone)] enum Parenthesized { /// The elements are parenthesized, e.g., `(a, b)`. Yes, /// The elements are not parenthesized, e.g., `a, b`. No, } impl From for Parenthesized { fn from(value: bool) -> Self { if value { Parenthesized::Yes } else { Parenthesized::No } } } impl Parenthesized { /// Returns `true` if the parenthesized value is `Yes`. const fn is_yes(self) -> bool { matches!(self, Parenthesized::Yes) } } #[derive(Copy, Clone, Debug)] enum ListTerminatorKind { /// The current token terminates the list. Regular, /// The current token doesn't terminate the list, but is useful for better error recovery. ErrorRecovery, } #[derive(Copy, Clone, Debug)] enum RecoveryContextKind { /// When parsing a list of statements at the module level i.e., at the top level of a file. ModuleStatements, /// When parsing a list of statements in a block e.g., the body of a function or a class. BlockStatements, /// The `elif` clauses of an `if` statement Elif, /// The `except` clauses of a `try` statement Except, /// When parsing a list of assignment targets AssignmentTargets, /// When parsing a list of type parameters TypeParams, /// When parsing a list of names in a `from ... import ...` statement ImportFromAsNames(Parenthesized), /// When parsing a list of names in an `import` statement ImportNames, /// When parsing a list of slice elements e.g., `data[1, 2]`. /// /// This is different from `ListElements` as the surrounding context is /// different in that the list is part of a subscript expression. Slices, /// When parsing a list of elements in a list expression e.g., `[1, 2]` ListElements, /// When parsing a list of elements in a set expression e.g., `{1, 2}` SetElements, /// When parsing a list of elements in a dictionary expression e.g., `{1: "a", **data}` DictElements, /// When parsing a list of elements in a tuple expression e.g., `(1, 2)` TupleElements(Parenthesized), /// When parsing a list of patterns in a match statement with an optional /// parentheses, e.g., `case a, b: ...`, `case (a, b): ...`, `case [a, b]: ...` SequenceMatchPattern(Option), /// When parsing a mapping pattern in a match statement MatchPatternMapping, /// When parsing a list of arguments in a class pattern for the match statement MatchPatternClassArguments, /// When parsing a list of arguments in a function call or a class definition Arguments, /// When parsing a `del` statement DeleteTargets, /// When parsing a list of identifiers Identifiers, /// When parsing a list of parameters in a function definition which can be /// either a function definition or a lambda expression. Parameters(FunctionKind), /// When parsing a list of items in a `with` statement WithItems(WithItemKind), /// When parsing a list of f-string or t-string elements which are either literal elements, expressions, or interpolations. InterpolatedStringElements(InterpolatedStringElementsKind), } impl RecoveryContextKind { /// Returns `true` if a trailing comma is allowed in the current context. const fn allow_trailing_comma(self) -> bool { match self { RecoveryContextKind::Slices | RecoveryContextKind::TupleElements(_) | RecoveryContextKind::SetElements | RecoveryContextKind::ListElements | RecoveryContextKind::DictElements | RecoveryContextKind::Arguments | RecoveryContextKind::MatchPatternMapping | RecoveryContextKind::SequenceMatchPattern(_) | RecoveryContextKind::MatchPatternClassArguments | RecoveryContextKind::Parameters(_) | RecoveryContextKind::TypeParams | RecoveryContextKind::DeleteTargets | RecoveryContextKind::ImportFromAsNames(Parenthesized::Yes) => true, // Only allow a trailing comma if the with item itself is parenthesized RecoveryContextKind::WithItems(WithItemKind::Parenthesized) => true, _ => false, } } /// Returns `true` if the parser is at a token that terminates the list as per the context. /// /// This token could either end the list or is only present for better error recovery. Refer to /// [`is_regular_list_terminator`] to only check against the former. /// /// [`is_regular_list_terminator`]: RecoveryContextKind::is_regular_list_terminator fn is_list_terminator(self, p: &Parser) -> bool { self.list_terminator_kind(p).is_some() } /// Returns `true` if the parser is at a token that terminates the list as per the context but /// the token isn't part of the error recovery set. #[expect(clippy::inline_always, reason = "reduces list-parser branch misses")] #[inline(always)] fn is_regular_list_terminator(self, p: &Parser) -> bool { matches!( self.list_terminator_kind(p), Some(ListTerminatorKind::Regular) ) } /// Checks the current token the parser is at and returns the list terminator kind if the token /// terminates the list as per the context. #[expect(clippy::inline_always, reason = "reduces list-parser branch misses")] #[inline(always)] fn list_terminator_kind(self, p: &Parser) -> Option { // The end of file marker ends all lists. if p.at(TokenKind::EndOfFile) { return Some(ListTerminatorKind::Regular); } match self { // The parser must consume all tokens until the end RecoveryContextKind::ModuleStatements => None, RecoveryContextKind::BlockStatements => p .at(TokenKind::Dedent) .then_some(ListTerminatorKind::Regular), RecoveryContextKind::Elif => { p.at(TokenKind::Else).then_some(ListTerminatorKind::Regular) } RecoveryContextKind::Except => { matches!(p.current_token_kind(), TokenKind::Finally | TokenKind::Else) .then_some(ListTerminatorKind::Regular) } RecoveryContextKind::AssignmentTargets => { // test_ok assign_targets_terminator // x = y = z = 1; a, b // x = y = z = 1 // a, b matches!(p.current_token_kind(), TokenKind::Newline | TokenKind::Semi) .then_some(ListTerminatorKind::Regular) } // Tokens other than `]` are for better error recovery. For example, recover when we // find the `:` of a clause header or the equal of a type assignment. RecoveryContextKind::TypeParams => { if p.at(TokenKind::Rsqb) { Some(ListTerminatorKind::Regular) } else { matches!( p.current_token_kind(), TokenKind::Newline | TokenKind::Colon | TokenKind::Equal | TokenKind::Lpar ) .then_some(ListTerminatorKind::ErrorRecovery) } } // The names of an import statement cannot be parenthesized, so `)` is not a // terminator. RecoveryContextKind::ImportNames => { // test_ok import_stmt_terminator // import a, b; import c, d // import a, b // c, d matches!(p.current_token_kind(), TokenKind::Semi | TokenKind::Newline) .then_some(ListTerminatorKind::Regular) } RecoveryContextKind::ImportFromAsNames(_) => { // test_ok from_import_stmt_terminator // from a import (b, c) // from a import (b, c); x, y // from a import b, c; x, y // from a import b, c // x, y matches!( p.current_token_kind(), TokenKind::Rpar | TokenKind::Semi | TokenKind::Newline ) .then_some(ListTerminatorKind::Regular) } // The elements in a container expression cannot end with a newline // as all of them are actually non-logical newlines. RecoveryContextKind::Slices | RecoveryContextKind::ListElements => { p.at(TokenKind::Rsqb).then_some(ListTerminatorKind::Regular) } RecoveryContextKind::SetElements | RecoveryContextKind::DictElements => p .at(TokenKind::Rbrace) .then_some(ListTerminatorKind::Regular), RecoveryContextKind::TupleElements(parenthesized) => { if parenthesized.is_yes() { p.at(TokenKind::Rpar).then_some(ListTerminatorKind::Regular) } else { p.at_sequence_end().then_some(ListTerminatorKind::Regular) } } RecoveryContextKind::SequenceMatchPattern(parentheses) => match parentheses { None => { // test_ok match_sequence_pattern_terminator // match subject: // case a if x: ... // case a, b: ... // case a, b if x: ... // case a: ... matches!(p.current_token_kind(), TokenKind::Colon | TokenKind::If) .then_some(ListTerminatorKind::Regular) } Some(parentheses) => { // test_ok match_sequence_pattern_parentheses_terminator // match subject: // case [a, b]: ... // case (a, b): ... p.at(parentheses.closing_kind()) .then_some(ListTerminatorKind::Regular) } }, RecoveryContextKind::MatchPatternMapping => p .at(TokenKind::Rbrace) .then_some(ListTerminatorKind::Regular), RecoveryContextKind::MatchPatternClassArguments => { p.at(TokenKind::Rpar).then_some(ListTerminatorKind::Regular) } RecoveryContextKind::Arguments => { p.at(TokenKind::Rpar).then_some(ListTerminatorKind::Regular) } RecoveryContextKind::DeleteTargets | RecoveryContextKind::Identifiers => { // test_ok del_targets_terminator // del a, b; c, d // del a, b // c, d matches!(p.current_token_kind(), TokenKind::Semi | TokenKind::Newline) .then_some(ListTerminatorKind::Regular) } RecoveryContextKind::Parameters(function_kind) => { // `lambda x, y: ...` or `def f(x, y): ...` if p.at(function_kind.list_terminator()) { Some(ListTerminatorKind::Regular) } else { // To recover from missing closing parentheses (p.at(TokenKind::Rarrow) || p.at_compound_stmt()) .then_some(ListTerminatorKind::ErrorRecovery) } } RecoveryContextKind::WithItems(with_item_kind) => match with_item_kind { WithItemKind::Parenthesized => match p.current_token_kind() { TokenKind::Rpar => Some(ListTerminatorKind::Regular), TokenKind::Colon => Some(ListTerminatorKind::ErrorRecovery), _ => None, }, // test_err ipython_help_escape_command_error_recovery_1 // # parse_options: {"mode": "ipython"} // with (a, ?b) // ? // test_err ipython_help_escape_command_error_recovery_2 // # parse_options: {"mode": "ipython"} // with (a, ?b // ? // test_err ipython_help_escape_command_error_recovery_3 // # parse_options: {"mode": "ipython"} // with a, ?b // ? // x = 1 WithItemKind::Unparenthesized => matches!( p.current_token_kind(), TokenKind::Colon | TokenKind::Newline ) .then_some(ListTerminatorKind::Regular), WithItemKind::ParenthesizedExpression => p .at(TokenKind::Colon) .then_some(ListTerminatorKind::Regular), }, RecoveryContextKind::InterpolatedStringElements(kind) => { if p.at(kind.list_terminator()) { Some(ListTerminatorKind::Regular) } else { // test_err unterminated_fstring_newline_recovery // f"hello // 1 + 1 // f"hello {x // 2 + 2 // f"hello {x: // 3 + 3 // f"hello {x} // 4 + 4 p.at(TokenKind::Newline) .then_some(ListTerminatorKind::ErrorRecovery) } } } } #[expect(clippy::inline_always, reason = "reduces list-parser branch misses")] #[inline(always)] fn is_list_element(self, p: &Parser) -> bool { match self { RecoveryContextKind::ModuleStatements => p.at_stmt(), RecoveryContextKind::BlockStatements => p.at_stmt(), RecoveryContextKind::Elif => p.at(TokenKind::Elif), RecoveryContextKind::Except => p.at(TokenKind::Except), RecoveryContextKind::AssignmentTargets => p.at(TokenKind::Equal), RecoveryContextKind::TypeParams => p.at_type_param(), RecoveryContextKind::ImportNames => p.at_name_or_soft_keyword(), RecoveryContextKind::ImportFromAsNames(_) => { p.at(TokenKind::Star) || p.at_name_or_soft_keyword() } RecoveryContextKind::Slices => p.at(TokenKind::Colon) || p.at_expr(), RecoveryContextKind::ListElements | RecoveryContextKind::SetElements | RecoveryContextKind::TupleElements(_) => p.at_expr(), RecoveryContextKind::DictElements => p.at(TokenKind::DoubleStar) || p.at_expr(), RecoveryContextKind::SequenceMatchPattern(_) => { // `+` doesn't start any pattern but is here for better error recovery. p.at(TokenKind::Plus) || p.at_pattern_start() } RecoveryContextKind::MatchPatternMapping => { // A star pattern is invalid as a mapping key and is here only for // better error recovery. p.at(TokenKind::Star) || p.at_mapping_pattern_start() } RecoveryContextKind::MatchPatternClassArguments => p.at_pattern_start(), RecoveryContextKind::Arguments => p.at_expr(), RecoveryContextKind::DeleteTargets => p.at_expr(), RecoveryContextKind::Identifiers => p.at_name_or_soft_keyword(), RecoveryContextKind::Parameters(_) => { matches!( p.current_token_kind(), TokenKind::Star | TokenKind::DoubleStar | TokenKind::Slash ) || p.at_name_or_soft_keyword() } RecoveryContextKind::WithItems(_) => p.at_expr(), RecoveryContextKind::InterpolatedStringElements(elements_kind) => match elements_kind { InterpolatedStringElementsKind::Regular(interpolated_string_kind) | InterpolatedStringElementsKind::FormatSpec(interpolated_string_kind) => { p.current_token_kind() == interpolated_string_kind.middle_token() || p.current_token_kind() == TokenKind::Lbrace } }, } } fn create_error(self, p: &Parser) -> ParseErrorType { match self { RecoveryContextKind::ModuleStatements | RecoveryContextKind::BlockStatements => { if p.at(TokenKind::Indent) { ParseErrorType::UnexpectedIndentation } else { ParseErrorType::OtherError("Expected a statement".to_string()) } } RecoveryContextKind::Elif => ParseErrorType::OtherError( "Expected an `elif` or `else` clause, or the end of the `if` statement." .to_string(), ), RecoveryContextKind::Except => ParseErrorType::OtherError( "Expected an `except` or `finally` clause or the end of the `try` statement." .to_string(), ), RecoveryContextKind::AssignmentTargets => { if p.current_token_kind().is_keyword() { ParseErrorType::OtherError( "The keyword is not allowed as a variable declaration name".to_string(), ) } else { ParseErrorType::OtherError("Expected an assignment target".to_string()) } } RecoveryContextKind::TypeParams => ParseErrorType::OtherError( "Expected a type parameter or the end of the type parameter list".to_string(), ), RecoveryContextKind::ImportFromAsNames(parenthesized) => { if parenthesized.is_yes() { ParseErrorType::OtherError("Expected an import name or a ')'".to_string()) } else { ParseErrorType::OtherError("Expected an import name".to_string()) } } RecoveryContextKind::ImportNames => { ParseErrorType::OtherError("Expected an import name".to_string()) } RecoveryContextKind::Slices => ParseErrorType::OtherError( "Expected an expression or the end of the slice list".to_string(), ), RecoveryContextKind::ListElements => { ParseErrorType::OtherError("Expected an expression or a ']'".to_string()) } RecoveryContextKind::SetElements | RecoveryContextKind::DictElements => { ParseErrorType::OtherError("Expected an expression or a '}'".to_string()) } RecoveryContextKind::TupleElements(parenthesized) => { if parenthesized.is_yes() { ParseErrorType::OtherError("Expected an expression or a ')'".to_string()) } else { ParseErrorType::OtherError("Expected an expression".to_string()) } } RecoveryContextKind::SequenceMatchPattern(_) => ParseErrorType::OtherError( "Expected a pattern or the end of the sequence pattern".to_string(), ), RecoveryContextKind::MatchPatternMapping => ParseErrorType::OtherError( "Expected a mapping pattern or the end of the mapping pattern".to_string(), ), RecoveryContextKind::MatchPatternClassArguments => { ParseErrorType::OtherError("Expected a pattern or a ')'".to_string()) } RecoveryContextKind::Arguments => { ParseErrorType::OtherError("Expected an expression or a ')'".to_string()) } RecoveryContextKind::DeleteTargets => { ParseErrorType::OtherError("Expected a delete target".to_string()) } RecoveryContextKind::Identifiers => { ParseErrorType::OtherError("Expected an identifier".to_string()) } RecoveryContextKind::Parameters(_) => ParseErrorType::OtherError( "Expected a parameter or the end of the parameter list".to_string(), ), RecoveryContextKind::WithItems(with_item_kind) => match with_item_kind { WithItemKind::Parenthesized => { ParseErrorType::OtherError("Expected an expression or a ')'".to_string()) } _ => ParseErrorType::OtherError( "Expected an expression or the end of the with item list".to_string(), ), }, RecoveryContextKind::InterpolatedStringElements(kind) => match kind { InterpolatedStringElementsKind::Regular(string_kind) => ParseErrorType::OtherError( format!("Expected an element of or the end of the {string_kind}"), ), InterpolatedStringElementsKind::FormatSpec(string_kind) => { ParseErrorType::OtherError(format!( "Expected an {string_kind} element or a '}}'" )) } }, } } } #[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] struct RecoveryContext(u32); bitflags! { impl RecoveryContext: u32 { const MODULE_STATEMENTS = 1 << 0; const BLOCK_STATEMENTS = 1 << 1; const ELIF = 1 << 2; const EXCEPT = 1 << 3; const ASSIGNMENT_TARGETS = 1 << 4; const TYPE_PARAMS = 1 << 5; const IMPORT_FROM_AS_NAMES_PARENTHESIZED = 1 << 6; const IMPORT_FROM_AS_NAMES_UNPARENTHESIZED = 1 << 7; const IMPORT_NAMES = 1 << 8; const SLICES = 1 << 9; const LIST_ELEMENTS = 1 << 10; const SET_ELEMENTS = 1 << 11; const DICT_ELEMENTS = 1 << 12; const TUPLE_ELEMENTS_PARENTHESIZED = 1 << 13; const TUPLE_ELEMENTS_UNPARENTHESIZED = 1 << 14; const SEQUENCE_MATCH_PATTERN = 1 << 15; const SEQUENCE_MATCH_PATTERN_LIST = 1 << 16; const SEQUENCE_MATCH_PATTERN_TUPLE = 1 << 17; const MATCH_PATTERN_MAPPING = 1 << 18; const MATCH_PATTERN_CLASS_ARGUMENTS = 1 << 19; const ARGUMENTS = 1 << 20; const DELETE = 1 << 21; const IDENTIFIERS = 1 << 22; const FUNCTION_PARAMETERS = 1 << 23; const LAMBDA_PARAMETERS = 1 << 24; const WITH_ITEMS_PARENTHESIZED = 1 << 25; const WITH_ITEMS_PARENTHESIZED_EXPRESSION = 1 << 26; const WITH_ITEMS_UNPARENTHESIZED = 1 << 27; const F_STRING_ELEMENTS = 1 << 28; const T_STRING_ELEMENTS = 1 << 29; const F_STRING_ELEMENTS_IN_FORMAT_SPEC = 1 << 30; const T_STRING_ELEMENTS_IN_FORMAT_SPEC = 1 << 31; } } impl RecoveryContext { const fn from_kind(kind: RecoveryContextKind) -> Self { match kind { RecoveryContextKind::ModuleStatements => RecoveryContext::MODULE_STATEMENTS, RecoveryContextKind::BlockStatements => RecoveryContext::BLOCK_STATEMENTS, RecoveryContextKind::Elif => RecoveryContext::ELIF, RecoveryContextKind::Except => RecoveryContext::EXCEPT, RecoveryContextKind::AssignmentTargets => RecoveryContext::ASSIGNMENT_TARGETS, RecoveryContextKind::TypeParams => RecoveryContext::TYPE_PARAMS, RecoveryContextKind::ImportFromAsNames(parenthesized) => match parenthesized { Parenthesized::Yes => RecoveryContext::IMPORT_FROM_AS_NAMES_PARENTHESIZED, Parenthesized::No => RecoveryContext::IMPORT_FROM_AS_NAMES_UNPARENTHESIZED, }, RecoveryContextKind::ImportNames => RecoveryContext::IMPORT_NAMES, RecoveryContextKind::Slices => RecoveryContext::SLICES, RecoveryContextKind::ListElements => RecoveryContext::LIST_ELEMENTS, RecoveryContextKind::SetElements => RecoveryContext::SET_ELEMENTS, RecoveryContextKind::DictElements => RecoveryContext::DICT_ELEMENTS, RecoveryContextKind::TupleElements(parenthesized) => match parenthesized { Parenthesized::Yes => RecoveryContext::TUPLE_ELEMENTS_PARENTHESIZED, Parenthesized::No => RecoveryContext::TUPLE_ELEMENTS_UNPARENTHESIZED, }, RecoveryContextKind::SequenceMatchPattern(parentheses) => match parentheses { None => RecoveryContext::SEQUENCE_MATCH_PATTERN, Some(SequenceMatchPatternParentheses::List) => { RecoveryContext::SEQUENCE_MATCH_PATTERN_LIST } Some(SequenceMatchPatternParentheses::Tuple) => { RecoveryContext::SEQUENCE_MATCH_PATTERN_TUPLE } }, RecoveryContextKind::MatchPatternMapping => RecoveryContext::MATCH_PATTERN_MAPPING, RecoveryContextKind::MatchPatternClassArguments => { RecoveryContext::MATCH_PATTERN_CLASS_ARGUMENTS } RecoveryContextKind::Arguments => RecoveryContext::ARGUMENTS, RecoveryContextKind::DeleteTargets => RecoveryContext::DELETE, RecoveryContextKind::Identifiers => RecoveryContext::IDENTIFIERS, RecoveryContextKind::Parameters(function_kind) => match function_kind { FunctionKind::Lambda => RecoveryContext::LAMBDA_PARAMETERS, FunctionKind::FunctionDef => RecoveryContext::FUNCTION_PARAMETERS, }, RecoveryContextKind::WithItems(with_item_kind) => match with_item_kind { WithItemKind::Parenthesized => RecoveryContext::WITH_ITEMS_PARENTHESIZED, WithItemKind::ParenthesizedExpression => { RecoveryContext::WITH_ITEMS_PARENTHESIZED_EXPRESSION } WithItemKind::Unparenthesized => RecoveryContext::WITH_ITEMS_UNPARENTHESIZED, }, RecoveryContextKind::InterpolatedStringElements(kind) => match kind { InterpolatedStringElementsKind::Regular(InterpolatedStringKind::FString) => { RecoveryContext::F_STRING_ELEMENTS } InterpolatedStringElementsKind::Regular(InterpolatedStringKind::TString) => { RecoveryContext::T_STRING_ELEMENTS } InterpolatedStringElementsKind::FormatSpec(InterpolatedStringKind::FString) => { RecoveryContext::F_STRING_ELEMENTS_IN_FORMAT_SPEC } InterpolatedStringElementsKind::FormatSpec(InterpolatedStringKind::TString) => { RecoveryContext::T_STRING_ELEMENTS_IN_FORMAT_SPEC } }, } } /// Safe conversion to the corresponding [`RecoveryContextKind`] (inverse of [`Self::from_kind`]). /// /// Returns `None` if the `RecoveryContext` is empty or has multiple flags set. const fn to_kind(self) -> Option { Some(match self { RecoveryContext::MODULE_STATEMENTS => RecoveryContextKind::ModuleStatements, RecoveryContext::BLOCK_STATEMENTS => RecoveryContextKind::BlockStatements, RecoveryContext::ELIF => RecoveryContextKind::Elif, RecoveryContext::EXCEPT => RecoveryContextKind::Except, RecoveryContext::ASSIGNMENT_TARGETS => RecoveryContextKind::AssignmentTargets, RecoveryContext::TYPE_PARAMS => RecoveryContextKind::TypeParams, RecoveryContext::IMPORT_FROM_AS_NAMES_PARENTHESIZED => { RecoveryContextKind::ImportFromAsNames(Parenthesized::Yes) } RecoveryContext::IMPORT_FROM_AS_NAMES_UNPARENTHESIZED => { RecoveryContextKind::ImportFromAsNames(Parenthesized::No) } RecoveryContext::IMPORT_NAMES => RecoveryContextKind::ImportNames, RecoveryContext::SLICES => RecoveryContextKind::Slices, RecoveryContext::LIST_ELEMENTS => RecoveryContextKind::ListElements, RecoveryContext::SET_ELEMENTS => RecoveryContextKind::SetElements, RecoveryContext::DICT_ELEMENTS => RecoveryContextKind::DictElements, RecoveryContext::TUPLE_ELEMENTS_PARENTHESIZED => { RecoveryContextKind::TupleElements(Parenthesized::Yes) } RecoveryContext::TUPLE_ELEMENTS_UNPARENTHESIZED => { RecoveryContextKind::TupleElements(Parenthesized::No) } RecoveryContext::SEQUENCE_MATCH_PATTERN => { RecoveryContextKind::SequenceMatchPattern(None) } RecoveryContext::SEQUENCE_MATCH_PATTERN_LIST => { RecoveryContextKind::SequenceMatchPattern(Some( SequenceMatchPatternParentheses::List, )) } RecoveryContext::SEQUENCE_MATCH_PATTERN_TUPLE => { RecoveryContextKind::SequenceMatchPattern(Some( SequenceMatchPatternParentheses::Tuple, )) } RecoveryContext::MATCH_PATTERN_MAPPING => RecoveryContextKind::MatchPatternMapping, RecoveryContext::MATCH_PATTERN_CLASS_ARGUMENTS => { RecoveryContextKind::MatchPatternClassArguments } RecoveryContext::ARGUMENTS => RecoveryContextKind::Arguments, RecoveryContext::DELETE => RecoveryContextKind::DeleteTargets, RecoveryContext::IDENTIFIERS => RecoveryContextKind::Identifiers, RecoveryContext::FUNCTION_PARAMETERS => { RecoveryContextKind::Parameters(FunctionKind::FunctionDef) } RecoveryContext::LAMBDA_PARAMETERS => { RecoveryContextKind::Parameters(FunctionKind::Lambda) } RecoveryContext::WITH_ITEMS_PARENTHESIZED => { RecoveryContextKind::WithItems(WithItemKind::Parenthesized) } RecoveryContext::WITH_ITEMS_PARENTHESIZED_EXPRESSION => { RecoveryContextKind::WithItems(WithItemKind::ParenthesizedExpression) } RecoveryContext::WITH_ITEMS_UNPARENTHESIZED => { RecoveryContextKind::WithItems(WithItemKind::Unparenthesized) } RecoveryContext::F_STRING_ELEMENTS => RecoveryContextKind::InterpolatedStringElements( InterpolatedStringElementsKind::Regular(InterpolatedStringKind::FString), ), RecoveryContext::T_STRING_ELEMENTS => RecoveryContextKind::InterpolatedStringElements( InterpolatedStringElementsKind::Regular(InterpolatedStringKind::TString), ), RecoveryContext::F_STRING_ELEMENTS_IN_FORMAT_SPEC => { RecoveryContextKind::InterpolatedStringElements( InterpolatedStringElementsKind::FormatSpec(InterpolatedStringKind::FString), ) } RecoveryContext::T_STRING_ELEMENTS_IN_FORMAT_SPEC => { RecoveryContextKind::InterpolatedStringElements( InterpolatedStringElementsKind::FormatSpec(InterpolatedStringKind::TString), ) } _ => return None, }) } fn kind_iter(self) -> impl Iterator { self.iter().map(|context| { context .to_kind() .expect("Expected context to be of a single kind.") }) } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/options.rs000064400000000000000000000055211046102023000226730ustar00use ruff_python_ast::{PySourceType, PythonVersion}; use crate::{AsMode, Mode}; /// The default maximum recursion depth used by the parser. /// /// Real-world Python rarely nests more than a handful of levels deep; this cap /// exists to keep the parser from overflowing the stack on adversarial or /// machine-generated input. /// /// The default value mirrors CPython's `MAXSTACK` of 200 nested parentheses /// (`Parser/parser.c`): a one-statement module of the form `((((1))))` at /// depth 200 must parse, and one at depth 201 must fail. Each nesting level /// costs one `with_recursion` call, plus two framing calls (one for the /// surrounding statement and one for the innermost atom), so the cap is set /// to `200 + 2`. const DEFAULT_MAX_RECURSION_DEPTH: u16 = 202; /// Options for controlling how a source file is parsed. /// /// You can construct a [`ParseOptions`] directly from a [`Mode`]: /// /// ``` /// use ruff_python_parser::{Mode, ParseOptions}; /// /// let options = ParseOptions::from(Mode::Module); /// ``` /// /// or from a [`PySourceType`] /// /// ``` /// use ruff_python_ast::PySourceType; /// use ruff_python_parser::ParseOptions; /// /// let options = ParseOptions::from(PySourceType::Python); /// ``` #[derive(Clone, Debug)] pub struct ParseOptions { /// Specify the mode in which the code will be parsed. pub(crate) mode: Mode, /// Target version for detecting version-related syntax errors. pub(crate) target_version: PythonVersion, /// Maximum recursion depth for the parser. The parser aborts with a /// [`crate::ParseErrorType::RecursionLimitExceeded`] error once this many /// nested expression / statement / pattern nodes are on the parser's call /// stack. Defaults to [`DEFAULT_MAX_RECURSION_DEPTH`]. pub(crate) max_recursion_depth: u16, } impl ParseOptions { #[must_use] pub fn with_target_version(mut self, target_version: PythonVersion) -> Self { self.target_version = target_version; self } pub fn target_version(&self) -> PythonVersion { self.target_version } /// Set the maximum recursion depth for the parser. #[must_use] pub fn with_max_recursion_depth(mut self, depth: u16) -> Self { self.max_recursion_depth = depth; self } pub fn max_recursion_depth(&self) -> u16 { self.max_recursion_depth } } impl From for ParseOptions { fn from(mode: Mode) -> Self { Self { mode, target_version: PythonVersion::default(), max_recursion_depth: DEFAULT_MAX_RECURSION_DEPTH, } } } impl From for ParseOptions { fn from(source_type: PySourceType) -> Self { Self { mode: source_type.as_mode(), target_version: PythonVersion::default(), max_recursion_depth: DEFAULT_MAX_RECURSION_DEPTH, } } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/pattern.rs000064400000000000000000000740021046102023000226550ustar00use ruff_python_ast::name::Name; use ruff_python_ast::token::TokenKind; use ruff_python_ast::{ self as ast, AtomicNodeIndex, Expr, ExprContext, Number, Operator, Pattern, PatternKeys, Patterns, Singleton, }; use ruff_text_size::{Ranged, TextSize}; use crate::ParseErrorType; use crate::parser::progress::ParserProgress; use crate::parser::{Parser, RecoveryContextKind, SequenceMatchPatternParentheses, recovery}; use crate::token_set::TokenSet; use super::expression::ExpressionContext; /// The set of tokens that can start a literal pattern. const LITERAL_PATTERN_START_SET: TokenSet = TokenSet::new([ TokenKind::None, TokenKind::True, TokenKind::False, TokenKind::String, TokenKind::Int, TokenKind::Float, TokenKind::Complex, TokenKind::Minus, // Unary minus ]); /// The set of tokens that can start a pattern. const PATTERN_START_SET: TokenSet = TokenSet::new([ // Star pattern TokenKind::Star, // Capture pattern // Wildcard pattern ('_' is a name token) // Value pattern (name or attribute) // Class pattern TokenKind::Name, // Group pattern TokenKind::Lpar, // Sequence pattern TokenKind::Lsqb, // Mapping pattern TokenKind::Lbrace, ]) .union(LITERAL_PATTERN_START_SET); /// The set of tokens that can start a mapping pattern. const MAPPING_PATTERN_START_SET: TokenSet = TokenSet::new([ // Double star pattern TokenKind::DoubleStar, // Value pattern TokenKind::Name, ]) .union(LITERAL_PATTERN_START_SET); impl Parser<'_> { /// Returns `true` if the current token is a valid start of a pattern. pub(super) fn at_pattern_start(&self) -> bool { self.at_ts(PATTERN_START_SET) || self.at_soft_keyword() } /// Returns `true` if the current token is a valid start of a mapping pattern. pub(super) fn at_mapping_pattern_start(&self) -> bool { self.at_ts(MAPPING_PATTERN_START_SET) || self.at_soft_keyword() } /// Entry point to start parsing a pattern. /// /// See: pub(super) fn parse_match_patterns(&mut self) -> Pattern { let start = self.node_start(); // We don't yet know if it's a sequence pattern or a single pattern, so // we need to allow star pattern here. let pattern = self.parse_match_pattern(AllowStarPattern::Yes); if self.at(TokenKind::Comma) { Pattern::MatchSequence(self.parse_sequence_match_pattern(pattern, start, None)) } else { // We know it's not a sequence pattern now, so check for star pattern usage. if pattern.is_match_star() { self.add_error(ParseErrorType::InvalidStarPatternUsage, &pattern); } pattern } } /// Parses an `or_pattern` or an `as_pattern`. /// /// See: fn parse_match_pattern(&mut self, allow_star_pattern: AllowStarPattern) -> Pattern { if let Some(result) = self.with_recursion(|parser| parser.parse_match_pattern_inner(allow_star_pattern)) { result } else { let range = self.missing_node_range(); self.report_recursion_limit_exceeded(self.current_token_range()); let invalid_node = Expr::Name(ast::ExprName { range, id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, }); Pattern::MatchValue(ast::PatternMatchValue { range: invalid_node.range(), value: Box::new(invalid_node), node_index: AtomicNodeIndex::NONE, }) } } fn parse_match_pattern_inner(&mut self, allow_star_pattern: AllowStarPattern) -> Pattern { let start = self.node_start(); // We don't yet know if it's an or pattern or an as pattern, so use whatever // was passed in. let mut lhs = self.parse_match_pattern_lhs(allow_star_pattern); // Or pattern if self.at(TokenKind::Vbar) { // We know it's an `or` pattern now, so check for star pattern usage. if lhs.is_match_star() { self.add_error(ParseErrorType::InvalidStarPatternUsage, &lhs); } let mut patterns = vec![lhs]; let mut progress = ParserProgress::default(); while self.eat(TokenKind::Vbar) { progress.assert_progressing(self); let pattern = self.parse_match_pattern_lhs(AllowStarPattern::No); patterns.push(pattern); } lhs = Pattern::MatchOr(ast::PatternMatchOr { range: self.node_range(start), patterns, node_index: AtomicNodeIndex::NONE, }); } // As pattern if self.eat(TokenKind::As) { // We know it's an `as` pattern now, so check for star pattern usage. if lhs.is_match_star() { self.add_error(ParseErrorType::InvalidStarPatternUsage, &lhs); } let ident = self.parse_match_pattern_target(); lhs = Pattern::MatchAs(ast::PatternMatchAs { range: self.node_range(start), name: Some(ident), pattern: Some(Box::new(lhs)), node_index: AtomicNodeIndex::NONE, }); } lhs } /// Parses a pattern. /// /// See: fn parse_match_pattern_lhs(&mut self, allow_star_pattern: AllowStarPattern) -> Pattern { let start = self.node_start(); let mut lhs = match self.current_token_kind() { TokenKind::Lbrace => Pattern::MatchMapping(self.parse_match_pattern_mapping()), TokenKind::Star => { let star_pattern = self.parse_match_pattern_star(); if allow_star_pattern.is_no() { self.add_error(ParseErrorType::InvalidStarPatternUsage, &star_pattern); } Pattern::MatchStar(star_pattern) } TokenKind::Lpar | TokenKind::Lsqb => self.parse_parenthesized_or_sequence_pattern(), _ => self.parse_match_pattern_literal(), }; if self.at(TokenKind::Lpar) { lhs = Pattern::MatchClass(self.parse_match_pattern_class(lhs, start)); } if matches!( self.current_token_kind(), TokenKind::Plus | TokenKind::Minus ) { lhs = Pattern::MatchValue(self.parse_complex_literal_pattern(lhs, start)); } lhs } /// Parses a mapping pattern. /// /// # Panics /// /// If the parser isn't positioned at a `{` token. /// /// See: fn parse_match_pattern_mapping(&mut self) -> ast::PatternMatchMapping { let start = self.node_start(); self.bump(TokenKind::Lbrace); let mut keys = PatternKeys::new(); let mut patterns = Patterns::new(); let mut rest = None; self.parse_comma_separated_list(RecoveryContextKind::MatchPatternMapping, |parser| { let mapping_item_start = parser.node_start(); if parser.eat(TokenKind::DoubleStar) { let identifier = parser.parse_match_pattern_target(); if rest.is_some() { parser.add_error( ParseErrorType::OtherError( "Only one double star pattern is allowed".to_string(), ), parser.node_range(mapping_item_start), ); } // TODO(dhruvmanila): It's not possible to retain multiple double starred // patterns because of the way the mapping node is represented in the grammar. // The last value will always win. Update the AST representation. // See: https://github.com/astral-sh/ruff/pull/10477#discussion_r1535143536 rest = Some(identifier); } else { let key = match parser.parse_match_pattern_lhs(AllowStarPattern::No) { Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => *value, Pattern::MatchSingleton(ast::PatternMatchSingleton { value, range, node_index, }) => match value { Singleton::None => { Expr::NoneLiteral(ast::ExprNoneLiteral { range, node_index }) } Singleton::True => Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: true, range, node_index, }), Singleton::False => Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: false, range, node_index, }), }, pattern => { parser.add_error( ParseErrorType::OtherError("Invalid mapping pattern key".to_string()), &pattern, ); recovery::pattern_to_expr(pattern) } }; keys.push(key); parser.expect(TokenKind::Colon); patterns.push(parser.parse_match_pattern(AllowStarPattern::No)); if rest.is_some() { parser.add_error( ParseErrorType::OtherError( "Pattern cannot follow a double star pattern".to_string(), ), parser.node_range(mapping_item_start), ); } } }); self.expect(TokenKind::Rbrace); ast::PatternMatchMapping { range: self.node_range(start), keys, patterns, rest, node_index: AtomicNodeIndex::NONE, } } /// Parses a star pattern. /// /// # Panics /// /// If the parser isn't positioned at a `*` token. /// /// See: fn parse_match_pattern_star(&mut self) -> ast::PatternMatchStar { let start = self.node_start(); self.bump(TokenKind::Star); let ident = self.parse_identifier(); ast::PatternMatchStar { range: self.node_range(start), name: if ident.is_valid() && ident.id == "_" { None } else { Some(ident) }, node_index: AtomicNodeIndex::NONE, } } /// Parses a binding target in an `as` or mapping pattern. fn parse_match_pattern_target(&mut self) -> ast::Identifier { // test_err invalid_match_pattern_target // match value: // case 1 as _: ... // case {**_}: ... // after = 1 let identifier = self.parse_identifier(); if identifier.is_valid() && identifier.id == "_" { self.add_error(ParseErrorType::InvalidMatchPatternTarget, &identifier); } identifier } /// Parses a parenthesized pattern or a sequence pattern. /// /// # Panics /// /// If the parser isn't positioned at a `(` or `[` token. /// /// See: fn parse_parenthesized_or_sequence_pattern(&mut self) -> Pattern { let start = self.node_start(); let parentheses = if self.eat(TokenKind::Lpar) { SequenceMatchPatternParentheses::Tuple } else { self.bump(TokenKind::Lsqb); SequenceMatchPatternParentheses::List }; if matches!( self.current_token_kind(), TokenKind::Newline | TokenKind::Colon ) { // TODO(dhruvmanila): This recovery isn't possible currently because // of the soft keyword transformer. If there's a missing closing // parenthesis, it'll consider `case` a name token instead. self.add_error( ParseErrorType::OtherError(format!( "Missing '{closing}'", closing = if parentheses.is_list() { "]" } else { ")" } )), self.current_token_range(), ); } if self.eat(parentheses.closing_kind()) { return Pattern::MatchSequence(ast::PatternMatchSequence { patterns: Vec::new(), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }); } let mut pattern = self.parse_match_pattern(AllowStarPattern::Yes); if parentheses.is_list() || self.at(TokenKind::Comma) { pattern = Pattern::MatchSequence(self.parse_sequence_match_pattern( pattern, start, Some(parentheses), )); } else { self.expect(parentheses.closing_kind()); } pattern } /// Parses the rest of a sequence pattern, given the first element. /// /// If the `parentheses` is `None`, it is an [open sequence pattern]. /// /// See: /// /// [open sequence pattern]: https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-open_sequence_pattern fn parse_sequence_match_pattern( &mut self, first_element: Pattern, start: TextSize, parentheses: Option, ) -> ast::PatternMatchSequence { if parentheses.is_some_and(|parentheses| { self.at(parentheses.closing_kind()) || self.peek() == parentheses.closing_kind() }) { // The comma is optional if it is a single-element sequence self.eat(TokenKind::Comma); } else { self.expect(TokenKind::Comma); } let mut patterns = vec![first_element]; self.parse_comma_separated_list( RecoveryContextKind::SequenceMatchPattern(parentheses), |parser| patterns.push(parser.parse_match_pattern(AllowStarPattern::Yes)), ); if let Some(parentheses) = parentheses { self.expect(parentheses.closing_kind()); } ast::PatternMatchSequence { range: self.node_range(start), patterns, node_index: AtomicNodeIndex::NONE, } } /// Parses a literal pattern. /// /// See: fn parse_match_pattern_literal(&mut self) -> Pattern { let start = self.node_start(); match self.current_token_kind() { TokenKind::None => { self.bump(TokenKind::None); Pattern::MatchSingleton(ast::PatternMatchSingleton { value: Singleton::None, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::True => { self.bump(TokenKind::True); Pattern::MatchSingleton(ast::PatternMatchSingleton { value: Singleton::True, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::False => { self.bump(TokenKind::False); Pattern::MatchSingleton(ast::PatternMatchSingleton { value: Singleton::False, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::String | TokenKind::FStringStart | TokenKind::TStringStart => { let str = self.parse_strings(); Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(str), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Complex => { let (real, imag) = self.bump_complex(); let range = self.node_range(start); Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Complex { real, imag }, range, node_index: AtomicNodeIndex::NONE, })), range, node_index: AtomicNodeIndex::NONE, }) } TokenKind::Int => { let value = self.bump_int(); let range = self.node_range(start); Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Int(value), range, node_index: AtomicNodeIndex::NONE, })), range, node_index: AtomicNodeIndex::NONE, }) } TokenKind::Float => { let value = self.bump_float(); let range = self.node_range(start); Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(Expr::NumberLiteral(ast::ExprNumberLiteral { value: Number::Float(value), range, node_index: AtomicNodeIndex::NONE, })), range, node_index: AtomicNodeIndex::NONE, }) } kind => { // The `+` is only for better error recovery. if let Some(unary_arithmetic_op) = kind.as_unary_arithmetic_operator() { if matches!( self.peek(), TokenKind::Int | TokenKind::Float | TokenKind::Complex ) { let unary_expr = self.parse_unary_expression( unary_arithmetic_op, ExpressionContext::default(), ); if unary_expr.op.is_u_add() { self.add_error( ParseErrorType::OtherError( "Unary '+' is not allowed as a literal pattern".to_string(), ), &unary_expr, ); } return Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(Expr::UnaryOp(unary_expr)), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }); } } if self.at_name_or_keyword() { if self.peek() == TokenKind::Dot { // test_ok match_attr_pattern_soft_keyword // match foo: // case match.bar: ... // case case.bar: ... // case type.bar: ... // case match.case.type.bar.type.case.match: ... let id = Expr::Name(self.parse_name(ExpressionContext::default())); let attribute = self.parse_attr_expr_for_match_pattern(id, start); Pattern::MatchValue(ast::PatternMatchValue { value: Box::new(attribute), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } else { // test_ok match_as_pattern_soft_keyword // match foo: // case case: ... // match foo: // case match: ... // match foo: // case type: ... let ident = self.parse_identifier(); // test_ok match_as_pattern // match foo: // case foo_bar: ... // match foo: // case _: ... Pattern::MatchAs(ast::PatternMatchAs { range: ident.range, pattern: None, name: if &ident == "_" { None } else { Some(ident) }, node_index: AtomicNodeIndex::NONE, }) } } else { // Upon encountering an unexpected token, return a `Pattern::MatchValue` containing // an empty `Expr::Name`. self.add_error( ParseErrorType::OtherError("Expected a pattern".to_string()), self.current_token_range(), ); let invalid_node = Expr::Name(ast::ExprName { range: self.missing_node_range(), id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, }); Pattern::MatchValue(ast::PatternMatchValue { range: invalid_node.range(), value: Box::new(invalid_node), node_index: AtomicNodeIndex::NONE, }) } } } } /// Parses a complex literal pattern, given the `lhs` pattern and the `start` /// position of the pattern. /// /// # Panics /// /// If the parser isn't positioned at a `+` or `-` token. /// /// See: fn parse_complex_literal_pattern( &mut self, lhs: Pattern, start: TextSize, ) -> ast::PatternMatchValue { let operator = if self.eat(TokenKind::Plus) { Operator::Add } else { self.bump(TokenKind::Minus); Operator::Sub }; let lhs_value = if let Pattern::MatchValue(lhs) = lhs { if !is_real_number(&lhs.value) { self.add_error(ParseErrorType::ExpectedRealNumber, &lhs); } lhs.value } else { self.add_error(ParseErrorType::ExpectedRealNumber, &lhs); Box::new(recovery::pattern_to_expr(lhs)) }; let rhs_pattern = self.parse_match_pattern_lhs(AllowStarPattern::No); let rhs_value = if let Pattern::MatchValue(rhs) = rhs_pattern { if !is_complex_number(&rhs.value) { self.add_error(ParseErrorType::ExpectedImaginaryNumber, &rhs); } rhs.value } else { self.add_error(ParseErrorType::ExpectedImaginaryNumber, &rhs_pattern); Box::new(recovery::pattern_to_expr(rhs_pattern)) }; let range = self.node_range(start); ast::PatternMatchValue { value: Box::new(Expr::BinOp(ast::ExprBinOp { left: lhs_value, op: operator, right: rhs_value, range, node_index: AtomicNodeIndex::NONE, })), range, node_index: AtomicNodeIndex::NONE, } } /// Parses an attribute expression until the current token is not a `.`. fn parse_attr_expr_for_match_pattern(&mut self, mut lhs: Expr, start: TextSize) -> Expr { while self.current_token_kind() == TokenKind::Dot { lhs = Expr::Attribute(self.parse_attribute_expression( lhs, start, ExpressionContext::default(), )); } lhs } /// Parses the [pattern arguments] in a class pattern. /// /// # Panics /// /// If the parser isn't positioned at a `(` token. /// /// See: /// /// [pattern arguments]: https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-pattern_arguments fn parse_match_pattern_class( &mut self, cls: Pattern, start: TextSize, ) -> ast::PatternMatchClass { let arguments_start = self.node_start(); let cls = match cls { Pattern::MatchAs(ast::PatternMatchAs { pattern: None, name: Some(ident), .. }) => { if ident.is_valid() { Box::new(Expr::Name(ast::ExprName { range: ident.range(), id: ident.id, ctx: ExprContext::Load, node_index: AtomicNodeIndex::NONE, })) } else { Box::new(Expr::Name(ast::ExprName { range: ident.range(), id: Name::empty(), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, })) } } Pattern::MatchValue(ast::PatternMatchValue { value, .. }) if matches!(&*value, Expr::Attribute(_)) => { value } pattern => { self.add_error( ParseErrorType::OtherError("Invalid value for a class pattern".to_string()), &pattern, ); Box::new(recovery::pattern_to_expr(pattern)) } }; self.bump(TokenKind::Lpar); let mut patterns = Patterns::new(); let mut keywords = vec![]; let mut has_seen_pattern = false; let mut has_seen_keyword_pattern = false; self.parse_comma_separated_list( RecoveryContextKind::MatchPatternClassArguments, |parser| { let pattern_start = parser.node_start(); let pattern = parser.parse_match_pattern(AllowStarPattern::No); if parser.eat(TokenKind::Equal) { has_seen_pattern = false; has_seen_keyword_pattern = true; let key = if let Pattern::MatchAs(ast::PatternMatchAs { pattern: None, name: Some(name), .. }) = pattern { name } else { parser.add_error( ParseErrorType::OtherError( "Expected an identifier for the keyword pattern".to_string(), ), &pattern, ); ast::Identifier { id: Name::empty(), range: parser.missing_node_range(), node_index: AtomicNodeIndex::NONE, } }; let value_pattern = parser.parse_match_pattern(AllowStarPattern::No); keywords.push(ast::PatternKeyword { attr: key, pattern: value_pattern, range: parser.node_range(pattern_start), node_index: AtomicNodeIndex::NONE, }); } else { has_seen_pattern = true; patterns.push(pattern); } if has_seen_keyword_pattern && has_seen_pattern { parser.add_error( ParseErrorType::OtherError( "Positional patterns cannot follow keyword patterns".to_string(), ), parser.node_range(pattern_start), ); } }, ); self.expect(TokenKind::Rpar); ast::PatternMatchClass { cls, arguments: ast::PatternArguments { patterns, keywords, range: self.node_range(arguments_start), node_index: AtomicNodeIndex::NONE, }, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } } #[derive(Debug, Clone, Copy)] enum AllowStarPattern { Yes, No, } impl AllowStarPattern { const fn is_no(self) -> bool { matches!(self, AllowStarPattern::No) } } /// Returns `true` if the given expression is a real number literal or a unary /// addition or subtraction of a real number literal. const fn is_real_number(expr: &Expr) -> bool { match expr { Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Int(_) | ast::Number::Float(_), .. }) => true, Expr::UnaryOp(ast::ExprUnaryOp { op: ast::UnaryOp::UAdd | ast::UnaryOp::USub, operand, .. }) => is_real_number(operand), _ => false, } } /// Returns `true` if the given expression is a complex number literal. const fn is_complex_number(expr: &Expr) -> bool { matches!( expr, Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Complex { .. }, .. }) ) } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/progress.rs000064400000000000000000000026561046102023000230520ustar00use crate::parser::Parser; #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub(super) struct TokenId(u32); impl TokenId { /// Increments the value of the token ID. pub(super) fn increment(&mut self) { // It's fine to just wrap around because the main purpose is to check whether // the previous token ID is different from the current token ID. self.0 = self.0.wrapping_add(1); } } /// Captures the progress of the parser and allows to test if the parsing is still making progress #[derive(Debug, Copy, Clone, Default)] pub(super) struct ParserProgress(Option); impl ParserProgress { /// Returns true if the parser has passed this position #[inline] fn has_progressed(self, p: &Parser) -> bool { match self.0 { None => true, Some(prev_token_id) => prev_token_id != p.current_token_id(), } } /// Asserts that the parsing is still making progress. /// /// # Panics /// /// Panics if the parser hasn't progressed since the last call. #[inline] pub(super) fn assert_progressing(&mut self, p: &Parser) { assert!( self.has_progressed(p), "The parser is no longer progressing. Stuck at '{}' {:?}:{:?}", p.src_text(p.current_token_range()), p.current_token_kind(), p.current_token_range(), ); self.0 = Some(p.current_token_id()); } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/recovery.rs000064400000000000000000000174611046102023000230440ustar00use ruff_python_ast::name::Name; use ruff_python_ast::{self as ast, Expr, ExprContext, Pattern}; use ruff_text_size::{Ranged, TextLen, TextRange}; /// Convert the given [`Pattern`] to an [`Expr`]. /// /// This is used to convert an invalid use of pattern to their equivalent expression /// to preserve the structure of the pattern. /// /// The conversion is done as follows: /// - `PatternMatchSingleton`: Boolean and None literals /// - `PatternMatchValue`: The value itself /// - `PatternMatchSequence`: List literal /// - `PatternMatchMapping`: Dictionary literal /// - `PatternMatchClass`: Call expression /// - `PatternMatchStar`: Starred expression /// - `PatternMatchAs`: The pattern itself or the name /// - `PatternMatchOr`: Binary expression with `|` operator /// /// Note that the sequence pattern is always converted to a list literal even /// if it was surrounded by parentheses. /// /// # Note /// /// This function returns an invalid [`ast::ExprName`] if the given pattern is a [`Pattern::MatchAs`] /// with both the pattern and name present. This is because it cannot be converted to an expression /// without dropping one of them as there's no way to represent `x as y` as a valid expression. pub(super) fn pattern_to_expr(pattern: Pattern) -> Expr { match pattern { Pattern::MatchSingleton(ast::PatternMatchSingleton { range, node_index, value, }) => match value { ast::Singleton::True => Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: true, range, node_index, }), ast::Singleton::False => Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: false, range, node_index, }), ast::Singleton::None => Expr::NoneLiteral(ast::ExprNoneLiteral { range, node_index }), }, Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => *value, // We don't know which kind of sequence this is: `case [1, 2]:` or `case (1, 2):`. Pattern::MatchSequence(ast::PatternMatchSequence { range, node_index, patterns, }) => Expr::List(ast::ExprList { elts: patterns.into_iter().map(pattern_to_expr).collect(), ctx: ExprContext::Store, range, node_index, }), Pattern::MatchMapping(ast::PatternMatchMapping { range, node_index, keys, patterns, rest, }) => { let mut items: Vec = keys .into_iter() .zip(patterns) .map(|(key, pattern)| ast::DictItem { key: Some(key), value: pattern_to_expr(pattern), }) .collect(); if let Some(rest) = rest { let value = Expr::Name(ast::ExprName { range: rest.range, node_index: node_index.clone(), id: rest.id, ctx: ExprContext::Store, }); items.push(ast::DictItem { key: None, value }); } items.shrink_to_fit(); Expr::Dict(ast::ExprDict { range, node_index, items, }) } Pattern::MatchClass(ast::PatternMatchClass { range, node_index, cls, arguments, }) => { debug_assert_eq!(range.end(), arguments.end()); Expr::Call(ast::ExprCall { range_start: range.start(), node_index: node_index.clone(), func: cls, arguments: ast::Arguments { range: arguments.range, node_index: node_index.clone(), args: arguments .patterns .into_iter() .map(pattern_to_expr) .collect(), keywords: arguments .keywords .into_iter() .map(|keyword_pattern| ast::Keyword { range: keyword_pattern.range, node_index: node_index.clone(), arg: Some(keyword_pattern.attr), value: pattern_to_expr(keyword_pattern.pattern), }) .collect(), }, }) } Pattern::MatchStar(ast::PatternMatchStar { range, node_index, name, }) => { if let Some(name) = name { Expr::Starred(ast::ExprStarred { range, node_index: node_index.clone(), value: Box::new(Expr::Name(ast::ExprName { range: name.range, node_index, id: name.id, ctx: ExprContext::Store, })), ctx: ExprContext::Store, }) } else { Expr::Starred(ast::ExprStarred { range, node_index: node_index.clone(), value: Box::new(Expr::Name(ast::ExprName { range: TextRange::new(range.end() - "_".text_len(), range.end()), id: Name::new_static("_"), ctx: ExprContext::Store, node_index, })), ctx: ExprContext::Store, }) } } Pattern::MatchAs(ast::PatternMatchAs { range, node_index, pattern, name, }) => match (pattern, name) { (Some(_), Some(_)) => Expr::Name(ast::ExprName { range, node_index, id: Name::empty(), ctx: ExprContext::Invalid, }), (Some(pattern), None) => pattern_to_expr(*pattern), (None, Some(name)) => Expr::Name(ast::ExprName { range: name.range, node_index, id: name.id, ctx: ExprContext::Store, }), (None, None) => Expr::Name(ast::ExprName { range, node_index, id: Name::new_static("_"), ctx: ExprContext::Store, }), }, Pattern::MatchOr(ast::PatternMatchOr { patterns, node_index, .. }) => { let to_bin_expr = |left: Pattern, right: Pattern| ast::ExprBinOp { range: TextRange::new(left.start(), right.end()), left: Box::new(pattern_to_expr(left)), op: ast::Operator::BitOr, right: Box::new(pattern_to_expr(right)), node_index: node_index.clone(), }; let mut iter = patterns.into_iter(); match (iter.next(), iter.next()) { (Some(left), Some(right)) => { Expr::BinOp(iter.fold(to_bin_expr(left, right), |expr_bin_op, pattern| { ast::ExprBinOp { range: TextRange::new(expr_bin_op.start(), pattern.end()), left: Box::new(Expr::BinOp(expr_bin_op)), op: ast::Operator::BitOr, right: Box::new(pattern_to_expr(pattern)), node_index: node_index.clone(), } })) } _ => unreachable!("Or patterns can only be formed with at least two patterns."), } } } } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/scratch_buffer.rs000064400000000000000000000072241046102023000241620ustar00use std::vec::Drain; use drop_bomb::DebugDropBomb; use thin_vec::ThinVec; /// Reusable scratch storage that preserves entries belonging to outer parser frames. #[derive(Debug)] pub(super) struct ScratchBuffer { buffer: Vec, } impl ScratchBuffer { pub(super) fn new() -> Self { Self { buffer: Vec::new() } } pub(super) fn with_capacity(capacity: usize) -> Self { Self { buffer: Vec::with_capacity(capacity), } } #[inline] pub(super) fn push(&mut self, value: T) { self.buffer.push(value); } #[inline] pub(super) fn is_empty(&self, snapshot: &ScratchSnapshot) -> bool { debug_assert!( self.buffer.len() >= snapshot.len, "Scratch buffer snapshots must be restored in reverse order of creation." ); self.buffer.len() == snapshot.len } #[inline] pub(super) fn snapshot(&self) -> ScratchSnapshot { ScratchSnapshot { len: self.buffer.len(), bomb: DebugDropBomb::new("Scratch buffer snapshots must be restored."), } } #[inline] pub(super) fn take>(&mut self, snapshot: ScratchSnapshot) -> C { self.drain_snapshot(snapshot).collect() } #[inline] pub(super) fn take_thin_vec(&mut self, mut snapshot: ScratchSnapshot) -> ThinVec { if self.is_empty(&snapshot) { snapshot.bomb.defuse(); return ThinVec::new(); } let drain = self.drain_snapshot(snapshot); let mut result = ThinVec::with_capacity(drain.len()); result.extend(drain); result } #[inline] fn drain_snapshot(&mut self, mut snapshot: ScratchSnapshot) -> Drain<'_, T> { debug_assert!( self.buffer.len() >= snapshot.len, "Scratch buffer snapshots must be restored in reverse order of creation." ); snapshot.bomb.defuse(); self.buffer.drain(snapshot.len..) } } impl Drop for ScratchBuffer { fn drop(&mut self) { debug_assert!( self.buffer.is_empty() || std::thread::panicking(), "Scratch buffers must be empty when dropped." ); } } pub(super) struct ScratchSnapshot { len: usize, bomb: DebugDropBomb, } #[cfg(test)] mod tests { use super::ScratchBuffer; #[test] #[cfg(debug_assertions)] #[should_panic(expected = "Scratch buffers must be empty when dropped.")] fn buffer_must_be_empty_when_dropped() { let mut buffer = ScratchBuffer::new(); buffer.push(1); } #[test] #[cfg(debug_assertions)] #[should_panic(expected = "Scratch buffer snapshots must be restored.")] fn snapshot_must_be_restored() { let buffer = ScratchBuffer::::new(); let _snapshot = buffer.snapshot(); } #[test] #[cfg(debug_assertions)] #[should_panic( expected = "Scratch buffer snapshots must be restored in reverse order of creation." )] fn snapshot_must_be_restored_in_reverse_order() { let mut buffer = ScratchBuffer::new(); buffer.push(1); let snapshot = buffer.snapshot(); buffer.buffer.clear(); let _: Vec<_> = buffer.take(snapshot); } #[test] fn snapshot_is_empty_relative_to_its_buffer() { let mut buffer = ScratchBuffer::new(); let outer_snapshot = buffer.snapshot(); buffer.push(1); let snapshot = buffer.snapshot(); assert!(buffer.is_empty(&snapshot)); buffer.push(2); assert!(!buffer.is_empty(&snapshot)); let _: Vec<_> = buffer.take(snapshot); let _: Vec<_> = buffer.take(outer_snapshot); } } ruff_python_parser__parser__tests__expr_mode_invalid_syntax1.snap000064400000000000000000000002321046102023000400630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: UnexpectedExpressionToken, location: 6..12, } ruff_python_parser__parser__tests__expr_mode_invalid_syntax2.snap000064400000000000000000000002321046102023000400640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: UnexpectedExpressionToken, location: 7..13, } ruff_python_parser__parser__tests__expr_mode_invalid_syntax3.snap000064400000000000000000000002321046102023000400650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: UnexpectedExpressionToken, location: 7..13, } ruff_python_parser__parser__tests__expr_mode_valid_syntax.snap000064400000000000000000000003361046102023000374600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: parsed.expr() --- Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("first"), ctx: Load, }, ) ruff_python_parser__parser__tests__fstring_expr_inner_line_continuation_and_t_string.snap000064400000000000000000000002551046102023000451520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: Lexical( LineContinuationError, ), location: 3..4, } ruff_python_parser__parser__tests__fstring_expr_inner_line_continuation_newline_t_string.snap000064400000000000000000000003111046102023000460420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: Lexical( TStringError( SingleRbrace, ), ), location: 8..9, } ruff_python_parser__parser__tests__ipython_escape_commands.snap000064400000000000000000000442261046102023000376120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: parsed.syntax() --- Module( ModModule { node_index: NodeIndex(None), range: 0..953, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..42, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 27..40, left: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("a"), ctx: Load, }, ), op: Mod, right: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("b"), ctx: Load, }, ), }, ), }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 66..73, kind: Help2, value: "a.foo", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 74..80, kind: Help, value: "a.foo", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 81..88, kind: Help, value: "a.foo", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 89..100, kind: Help2, value: "a.foo()", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 115..128, kind: Magic, value: "timeit a = b", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 129..147, kind: Magic, value: "timeit foo(b) % 3", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 148..176, kind: Magic, value: "alias showPath pwd && ls -a", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 177..205, kind: Magic, value: "timeit a = foo(b); b = 2", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 206..226, kind: Magic, value: "matplotlib --inline", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 227..253, kind: Magic, value: "matplotlib --inline", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 277..309, kind: Shell, value: "pwd && ls -a | sed 's/^/\\ /'", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 310..347, kind: Shell, value: "pwd && ls -a | sed 's/^/\\\\ /'", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 348..393, kind: ShCap, value: "cd /Users/foo/Library/Application\\ Support/", }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 566..626, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 570..573, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 573..575, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 581..626, value: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 598..620, left: Name( ExprName { node_index: NodeIndex(None), range: 598..599, id: Name("a"), ctx: Load, }, ), ops: [ NotEq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 619..620, id: Name("b"), ctx: Load, }, ), ], }, ), ), }, ), ], }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 656..664, kind: Paren, value: "foo 1 2", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 665..673, kind: Quote2, value: "foo 1 2", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 674..682, kind: Quote, value: "foo 1 2", }, ), For( StmtFor { node_index: NodeIndex(None), range: 711..737, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 715..716, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 720..728, func: Name( ExprName { node_index: NodeIndex(None), range: 720..725, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 725..728, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 726..727, value: Int( 5, ), }, ), ], keywords: [], }, }, ), body: [ IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 734..737, kind: Shell, value: "ls", }, ), ], orelse: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 739..748, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 739..741, id: Name("p1"), ctx: Store, }, ), ], value: IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 744..748, kind: Shell, value: "pwd", }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 749..763, target: Name( ExprName { node_index: NodeIndex(None), range: 749..751, id: Name("p2"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 753..756, id: Name("str"), ctx: Load, }, ), value: Some( IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 759..763, kind: Shell, value: "pwd", }, ), ), simple: true, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 764..784, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 764..767, id: Name("foo"), ctx: Store, }, ), ], value: IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 770..784, kind: Magic, value: "foo bar", }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 785..796, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 785..788, id: Name("bar"), ctx: Store, }, ), ], value: IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 791..796, kind: Magic, value: "foo?", }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 797..808, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 797..800, id: Name("baz"), ctx: Store, }, ), ], value: IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 803..808, kind: Shell, value: "pwd?", }, ), }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 810..815, kind: Magic, value: " foo", }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 816..837, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 816..819, id: Name("foo"), ctx: Store, }, ), ], value: IpyEscapeCommand( ExprIpyEscapeCommand { node_index: NodeIndex(None), range: 822..837, kind: Magic, value: "foo # comment", }, ), }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 862..866, kind: Help, value: "foo", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 867..876, kind: Help2, value: "foo.bar", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 877..889, kind: Help, value: "foo.bar.baz", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 890..898, kind: Help2, value: "foo[0]", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 899..909, kind: Help, value: "foo[0][1]", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 910..929, kind: Help2, value: "foo.bar[0].baz[1]", }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 930..953, kind: Help2, value: "foo.bar[0].baz[2].egg", }, ), ], }, ) ruff_python_parser__parser__tests__tstring_fstring_middle.snap000064400000000000000000000002221046102023000374470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: ExpectedExpression, location: 3..4, } ruff_python_parser__parser__tests__tstring_fstring_middle_fuzzer.snap000064400000000000000000000003141046102023000410560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: error --- ParseError { error: Lexical( UnrecognizedToken { tok: '\0', }, ), location: 5..6, } ruff_python_parser__parser__tests__unicode_aliases.snap000064400000000000000000000025521046102023000360420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/snapshots--- source: crates/ruff_python_parser/src/parser/tests.rs expression: suite --- [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..37, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 4..37, value: StringLiteralValue { inner: Single( StringLiteral { range: 4..37, node_index: NodeIndex(None), value: "\u{8}another cool trick", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/statement.rs000064400000000000000000004476071046102023000232230ustar00use std::fmt::{Display, Write}; use ruff_python_ast::name::Name; use ruff_python_ast::token::TokenKind; use ruff_python_ast::{ self as ast, AtomicNodeIndex, DecoratorList, ExceptHandler, Expr, ExprContext, IpyEscapeKind, Operator, PythonVersion, Stmt, Suite, WithItem, }; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::error::StarTupleKind; use crate::parser::expression::{ArgumentsContext, EXPR_SET, ParsedExpr}; use crate::parser::progress::ParserProgress; use crate::parser::{ FunctionKind, IpyEscapeContext, Parser, RecoveryContext, RecoveryContextKind, WithItemKind, helpers, }; use crate::token_set::TokenSet; use crate::{Mode, ParseErrorType, UnsupportedSyntaxErrorKind}; use super::Parenthesized; use super::expression::ExpressionContext; /// Tokens that represent compound statements. const COMPOUND_STMT_SET: TokenSet = TokenSet::new([ TokenKind::Match, TokenKind::If, TokenKind::With, TokenKind::While, TokenKind::For, TokenKind::Try, TokenKind::Def, TokenKind::Class, TokenKind::Async, TokenKind::At, ]); /// Tokens that represent simple statements, but doesn't include expressions. const SIMPLE_STMT_SET: TokenSet = TokenSet::new([ TokenKind::Pass, TokenKind::Return, TokenKind::Break, TokenKind::Continue, TokenKind::Global, TokenKind::Nonlocal, TokenKind::Assert, TokenKind::Yield, TokenKind::Del, TokenKind::Raise, TokenKind::Import, TokenKind::From, TokenKind::Type, TokenKind::IpyEscapeCommand, ]); /// Tokens that represent simple statements, including expressions. const SIMPLE_STMT_WITH_EXPR_SET: TokenSet = SIMPLE_STMT_SET.union(EXPR_SET); /// Tokens that represents all possible statements, including simple, compound, /// and expression statements. const STMTS_SET: TokenSet = SIMPLE_STMT_WITH_EXPR_SET.union(COMPOUND_STMT_SET); /// Tokens that represent operators that can be used in augmented assignments. const AUGMENTED_ASSIGN_SET: TokenSet = TokenSet::new([ TokenKind::PlusEqual, TokenKind::MinusEqual, TokenKind::StarEqual, TokenKind::DoubleStarEqual, TokenKind::SlashEqual, TokenKind::DoubleSlashEqual, TokenKind::PercentEqual, TokenKind::AtEqual, TokenKind::AmperEqual, TokenKind::VbarEqual, TokenKind::CircumflexEqual, TokenKind::LeftShiftEqual, TokenKind::RightShiftEqual, ]); impl<'src> Parser<'src> { /// Returns `true` if the current token is the start of a compound statement. pub(super) fn at_compound_stmt(&self) -> bool { self.at_ts(COMPOUND_STMT_SET) } /// Returns `true` if the current token is the start of a simple statement, /// including expressions. fn at_simple_stmt(&self) -> bool { self.at_ts(SIMPLE_STMT_WITH_EXPR_SET) || self.at_soft_keyword() } /// Returns `true` if the current token is the start of a simple, compound or expression /// statement. pub(super) fn at_stmt(&self) -> bool { self.at_ts(STMTS_SET) || self.at_soft_keyword() } /// Checks if the parser is currently positioned at the start of a type parameter. pub(super) fn at_type_param(&self) -> bool { let token = self.current_token_kind(); matches!( token, TokenKind::Star | TokenKind::DoubleStar | TokenKind::Name ) || token.is_keyword() } /// Parses a compound or a single simple statement. /// /// See: /// - /// - pub(super) fn parse_statement(&mut self) -> Stmt { let start = self.node_start(); match self.current_token_kind() { TokenKind::If => Stmt::If(self.parse_if_statement()), TokenKind::For => Stmt::For(self.parse_for_statement(start)), TokenKind::While => Stmt::While(self.parse_while_statement()), TokenKind::Def => { Stmt::FunctionDef(self.parse_function_definition(DecoratorList::new(), start)) } TokenKind::Class => { Stmt::ClassDef(self.parse_class_definition(DecoratorList::new(), start)) } TokenKind::Try => Stmt::Try(self.parse_try_statement()), TokenKind::With => Stmt::With(self.parse_with_statement(start)), TokenKind::At => self.parse_decorators(), TokenKind::Async => self.parse_async_statement(), token => { if token == TokenKind::Match { // Match is considered a soft keyword, so we will treat it as an identifier if // it's followed by an unexpected token. match self.classify_match_token() { MatchTokenKind::Keyword => { return Stmt::Match(self.parse_match_statement()); } MatchTokenKind::KeywordOrIdentifier => { if let Some(match_stmt) = self.try_parse_match_statement() { return Stmt::Match(match_stmt); } } MatchTokenKind::Identifier => {} } } self.parse_single_simple_statement() } } } /// Parses a single simple statement. /// /// This statement must be terminated by a newline or semicolon. /// /// Use [`Parser::parse_simple_statements`] to parse a sequence of simple statements. fn parse_single_simple_statement(&mut self) -> Stmt { let stmt = self.parse_simple_statement(); // The order of the token is important here. let has_eaten_semicolon = self.eat(TokenKind::Semi); let has_eaten_newline = self.eat(TokenKind::Newline); if !has_eaten_newline { if !has_eaten_semicolon && self.at_simple_stmt() { // test_err simple_stmts_on_same_line // a b // a + b c + d // break; continue pass; continue break self.add_error( ParseErrorType::SimpleStatementsOnSameLine, self.current_token_range(), ); } else if self.at_compound_stmt() { // test_err simple_and_compound_stmt_on_same_line // a; if b: pass; b self.add_error( ParseErrorType::SimpleAndCompoundStatementOnSameLine, self.current_token_range(), ); } } stmt } /// Parses a sequence of simple statements. /// /// If there is more than one statement in this sequence, it is expected to be separated by a /// semicolon. The sequence can optionally end with a semicolon, but regardless of whether /// a semicolon is present or not, it is expected to end with a newline. /// /// Matches the `simple_stmts` rule in the [Python grammar]. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_simple_statements(&mut self) -> Suite { let stmts_snapshot = self.stmt_scratch.snapshot(); let mut progress = ParserProgress::default(); loop { progress.assert_progressing(self); let stmt = self.parse_simple_statement(); self.stmt_scratch.push(stmt); if !self.eat(TokenKind::Semi) { if self.at_simple_stmt() { // test_err simple_stmts_on_same_line_in_block // if True: break; continue pass; continue break self.add_error( ParseErrorType::SimpleStatementsOnSameLine, self.current_token_range(), ); } else { // test_ok simple_stmts_in_block // if True: pass // if True: pass; // if True: pass; continue // if True: pass; continue; // x = 1 break; } } if !self.at_simple_stmt() { break; } } // Ideally, we should use `expect` here but we use `eat` for better error message. Later, // if the parser isn't at the start of a compound statement, we'd `expect` a newline. if !self.eat(TokenKind::Newline) { if self.at_compound_stmt() { // test_err simple_and_compound_stmt_on_same_line_in_block // if True: pass if False: pass // if True: pass; if False: pass self.add_error( ParseErrorType::SimpleAndCompoundStatementOnSameLine, self.current_token_range(), ); } else { // test_err multiple_clauses_on_same_line // if True: pass elif False: pass else: pass // if True: pass; elif False: pass; else: pass // for x in iter: break else: pass // for x in iter: break; else: pass // try: pass except exc: pass else: pass finally: pass // try: pass; except exc: pass; else: pass; finally: pass self.add_error( ParseErrorType::ExpectedToken { found: self.current_token_kind(), expected: TokenKind::Newline, }, self.current_token_range(), ); } } // test_ok simple_stmts_with_semicolons // return; import a; from x import y; z; type T = int self.stmt_scratch.take_thin_vec(stmts_snapshot) } /// Parses a simple statement. /// /// See: fn parse_simple_statement(&mut self) -> Stmt { match self.current_token_kind() { TokenKind::Return => Stmt::Return(self.parse_return_statement()), TokenKind::Import => { let start = self.node_start(); Stmt::Import(self.parse_import_statement(start, false)) } TokenKind::From => { let start = self.node_start(); Stmt::ImportFrom(self.parse_from_import_statement(start, false)) } TokenKind::Pass => Stmt::Pass(self.parse_pass_statement()), TokenKind::Continue => Stmt::Continue(self.parse_continue_statement()), TokenKind::Break => Stmt::Break(self.parse_break_statement()), TokenKind::Raise => Stmt::Raise(self.parse_raise_statement()), TokenKind::Del => Stmt::Delete(self.parse_delete_statement()), TokenKind::Assert => Stmt::Assert(self.parse_assert_statement()), TokenKind::Global => Stmt::Global(self.parse_global_statement()), TokenKind::Nonlocal => Stmt::Nonlocal(self.parse_nonlocal_statement()), TokenKind::IpyEscapeCommand => { Stmt::IpyEscapeCommand(self.parse_ipython_escape_command_statement()) } token => { if token == TokenKind::Lazy { let start = self.node_start(); let lazy_range = self.current_token_range(); match self.peek() { // test_ok lazy_import_stmt_py315 // # parse_options: {"target-version": "3.15"} // lazy import foo // lazy import foo as bar // lazy from bar import baz // lazy from sys import x as y // lazy = 1 // import foo as lazy // from lazy import qux // test_ok lazy_import_relative_py315 // # parse_options: {"target-version": "3.15"} // lazy from . import basic2 // lazy from .basic2 import x, f // lazy from . import b, x // test_ok lazy_import_soft_keyword_split_py315 // # parse_options: {"target-version": "3.15"} // lazy // import os // // lazy # comment // from sys import path // test_err lazy_import_stmt_py314 // # parse_options: {"target-version": "3.14"} // lazy import foo // lazy from bar import baz TokenKind::Import => { self.bump(TokenKind::Lazy); self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::LazyImportStatement, lazy_range, ); return Stmt::Import(self.parse_import_statement(start, true)); } TokenKind::From => { self.bump(TokenKind::Lazy); self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::LazyImportStatement, lazy_range, ); return Stmt::ImportFrom(self.parse_from_import_statement(start, true)); } _ => {} } } if token == TokenKind::Type { // Type is considered a soft keyword, so we will treat it as an identifier if // it's followed by an unexpected token. let (first, second) = self.peek2(); if (first == TokenKind::Name || first.is_soft_keyword()) && matches!(second, TokenKind::Lsqb | TokenKind::Equal) { return Stmt::TypeAlias(self.parse_type_alias_statement()); } } let start = self.node_start(); // test_err yield_after_comma // def f(): 1, yield 1 // test_ok yield_after_comma_parenthesized // def f(): 1, (yield 1) // simple_stmt: `... | yield_stmt | star_expressions | ...` let parsed_expr = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); if self.at(TokenKind::Equal) { Stmt::Assign(self.parse_assign_statement(parsed_expr, start)) } else if self.at(TokenKind::Colon) { Stmt::AnnAssign(self.parse_annotated_assignment_statement(parsed_expr, start)) } else if let Some(op) = self.current_token_kind().as_augmented_assign_operator() { Stmt::AugAssign(self.parse_augmented_assignment_statement( parsed_expr, op, start, )) } else if self.options.mode == Mode::Ipython && self.at(TokenKind::Question) { Stmt::IpyEscapeCommand( self.parse_ipython_help_end_escape_command_statement(&parsed_expr), ) } else { Stmt::Expr(ast::StmtExpr { range: self.node_range(start), value: Box::new(parsed_expr.expr), node_index: AtomicNodeIndex::NONE, }) } } } } /// Parses a delete statement. /// /// # Panics /// /// If the parser isn't positioned at a `del` token. /// /// See: fn parse_delete_statement(&mut self) -> ast::StmtDelete { let start = self.node_start(); self.bump(TokenKind::Del); // test_err del_incomplete_target // del x, y. // z // del x, y[ // z let targets = self.parse_comma_separated_list_into_vec( RecoveryContextKind::DeleteTargets, |parser| { // Allow starred expression to raise a better error message for // an invalid delete target later. let mut target = parser.parse_conditional_expression_or_higher_impl( ExpressionContext::starred_conditional(), ); helpers::set_expr_ctx(&mut target.expr, ExprContext::Del); // test_err invalid_del_target // del x + 1 // del {'x': 1} // del {'x', 'y'} // del None, True, False, 1, 1.0, "abc" parser.validate_delete_target(&target.expr); target.expr }, ); if targets.is_empty() { // test_err del_stmt_empty // del self.add_error( ParseErrorType::EmptyDeleteTargets, self.current_token_range(), ); } ast::StmtDelete { targets, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `return` statement. /// /// # Panics /// /// If the parser isn't positioned at a `return` token. /// /// See: fn parse_return_statement(&mut self) -> ast::StmtReturn { let start = self.node_start(); self.bump(TokenKind::Return); // test_err return_stmt_invalid_expr // return * // return yield x // return yield from x // return x := 1 // return *x and y let value = self.at_expr().then(|| { let parsed_expr = self.parse_expression_list(ExpressionContext::starred_bitwise_or()); // test_ok iter_unpack_return_py37 // # parse_options: {"target-version": "3.7"} // rest = (4, 5, 6) // def f(): return (1, 2, 3, *rest) // test_ok iter_unpack_return_py38 // # parse_options: {"target-version": "3.8"} // rest = (4, 5, 6) // def f(): return 1, 2, 3, *rest // test_err iter_unpack_return_py37 // # parse_options: {"target-version": "3.7"} // rest = (4, 5, 6) // def f(): return 1, 2, 3, *rest self.check_tuple_unpacking( &parsed_expr, UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Return), ); Box::new(parsed_expr.expr) }); ast::StmtReturn { range: self.node_range(start), value, node_index: AtomicNodeIndex::NONE, } } /// Report [`UnsupportedSyntaxError`]s for each starred element in `expr` if it is an /// unparenthesized tuple. /// /// This method can be used to check for tuple unpacking in `return`, `yield`, and `for` /// statements, which are only allowed after [Python 3.8] and [Python 3.9], respectively. /// /// [Python 3.8]: https://github.com/python/cpython/issues/76298 /// [Python 3.9]: https://github.com/python/cpython/issues/90881 pub(super) fn check_tuple_unpacking(&mut self, expr: &Expr, kind: UnsupportedSyntaxErrorKind) { if kind.is_supported(self.options.target_version) { return; } let Expr::Tuple(ast::ExprTuple { elts, parenthesized: false, .. }) = expr else { return; }; for elt in elts { if elt.is_starred_expr() { self.add_unsupported_syntax_error(kind, elt.range()); } } } /// Parses a `raise` statement. /// /// # Panics /// /// If the parser isn't positioned at a `raise` token. /// /// See: fn parse_raise_statement(&mut self) -> ast::StmtRaise { let start = self.node_start(); self.bump(TokenKind::Raise); let exc = match self.current_token_kind() { TokenKind::Newline => None, TokenKind::From => { // test_err raise_stmt_from_without_exc // raise from exc // raise from None self.add_error( ParseErrorType::OtherError( "Exception missing in `raise` statement with cause".to_string(), ), self.current_token_range(), ); None } _ => { // test_err raise_stmt_invalid_exc // raise *x // raise yield x // raise x := 1 let exc = self.parse_expression_list(ExpressionContext::default()); if let Some(ast::ExprTuple { parenthesized: false, .. }) = exc.as_tuple_expr() { // test_err raise_stmt_unparenthesized_tuple_exc // raise x, // raise x, y // raise x, y from z self.add_error(ParseErrorType::UnparenthesizedTupleExpression, &exc); } Some(Box::new(exc.expr)) } }; let cause = self.eat(TokenKind::From).then(|| { // test_err raise_stmt_invalid_cause // raise x from *y // raise x from yield y // raise x from y := 1 let cause = self.parse_expression_list(ExpressionContext::default()); if let Some(ast::ExprTuple { parenthesized: false, .. }) = cause.as_tuple_expr() { // test_err raise_stmt_unparenthesized_tuple_cause // raise x from y, // raise x from y, z self.add_error(ParseErrorType::UnparenthesizedTupleExpression, &cause); } Box::new(cause.expr) }); ast::StmtRaise { range: self.node_range(start), exc, cause, node_index: AtomicNodeIndex::NONE, } } /// Parses an import statement. /// /// # Panics /// /// If the parser isn't positioned at an `import` token. /// /// See: fn parse_import_statement(&mut self, start: TextSize, is_lazy: bool) -> ast::StmtImport { self.bump(TokenKind::Import); // test_err import_stmt_parenthesized_names // import (a) // import (a, b) // test_err import_stmt_star_import // import * // import x, *, y // test_err import_stmt_trailing_comma // import , // import x, y, let names_snapshot = self.alias_scratch.snapshot(); self.parse_comma_separated_list(RecoveryContextKind::ImportNames, |parser| { let alias = parser.parse_alias(ImportStyle::Import); parser.alias_scratch.push(alias); }); let names: Vec<_> = self.alias_scratch.take(names_snapshot); if names.is_empty() { // test_err import_stmt_empty // import self.add_error(ParseErrorType::EmptyImportNames, self.current_token_range()); } ast::StmtImport { names, is_lazy, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `from` import statement. /// /// # Panics /// /// If the parser isn't positioned at a `from` token. /// /// See: fn parse_from_import_statement( &mut self, start: TextSize, is_lazy: bool, ) -> ast::StmtImportFrom { self.bump(TokenKind::From); let mut leading_dots = 0; let mut progress = ParserProgress::default(); loop { progress.assert_progressing(self); if self.eat(TokenKind::Dot) { leading_dots += 1; } else if self.eat(TokenKind::Ellipsis) { leading_dots += 3; } else { break; } } let module = if self.at_name_or_soft_keyword() { // test_ok from_import_soft_keyword_module_name // from match import pattern // from type import bar // from case import pattern // from lazy import qux // from match.type.case import foo Some(self.parse_dotted_name()) } else { if leading_dots == 0 { // test_err from_import_missing_module // from // from import x self.add_error( ParseErrorType::OtherError("Expected a module name".to_string()), self.current_token_range(), ); } None }; // test_ok from_import_no_space // from.import x // from...import x self.expect(TokenKind::Import); let names_start = self.node_start(); let names_snapshot = self.alias_scratch.snapshot(); let mut seen_star_import = false; let parenthesized = Parenthesized::from(self.eat(TokenKind::Lpar)); // test_err from_import_unparenthesized_trailing_comma // from a import b, // from a import b as c, // from a import b, c, self.parse_comma_separated_list( RecoveryContextKind::ImportFromAsNames(parenthesized), |parser| { // test_err from_import_dotted_names // from x import a. // from x import a.b // from x import a, b.c, d, e.f, g let alias = parser.parse_alias(ImportStyle::ImportFrom); seen_star_import |= alias.name.id == "*"; parser.alias_scratch.push(alias); }, ); let names: Vec<_> = self.alias_scratch.take(names_snapshot); if names.is_empty() { // test_err from_import_empty_names // from x import // from x import () // from x import ,, self.add_error(ParseErrorType::EmptyImportNames, self.current_token_range()); } if seen_star_import && parenthesized.is_yes() { // test_err from_import_parenthesized_star // from x import (*) self.add_error( ParseErrorType::OtherError("Star import cannot be parenthesized".to_string()), self.node_range(names_start), ); } if seen_star_import && names.len() > 1 { // test_err from_import_star_with_other_names // from x import *, a // from x import a, *, b // from x import *, a as b // from x import *, *, a self.add_error( ParseErrorType::OtherError("Star import must be the only import".to_string()), self.node_range(names_start), ); } if parenthesized.is_yes() { // test_err from_import_missing_rpar // from x import (a, b // 1 + 1 // from x import (a, b, // 2 + 2 self.expect(TokenKind::Rpar); } ast::StmtImportFrom { module, names, level: leading_dots, is_lazy, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `import` or `from` import name. /// /// See: /// - /// - fn parse_alias(&mut self, style: ImportStyle) -> ast::Alias { let start = self.node_start(); if self.eat(TokenKind::Star) { let range = self.node_range(start); return ast::Alias { name: ast::Identifier { id: Name::new_static("*"), range, node_index: AtomicNodeIndex::NONE, }, asname: None, range, node_index: AtomicNodeIndex::NONE, }; } let name = match style { ImportStyle::Import => self.parse_dotted_name(), ImportStyle::ImportFrom => self.parse_identifier(), }; let asname = if self.eat(TokenKind::As) { if self.at_name_or_soft_keyword() { // test_ok import_as_name_soft_keyword // import foo as match // import bar as case // import baz as type // import qux as lazy Some(self.parse_identifier()) } else { // test_err import_alias_missing_asname // import x as self.add_error( ParseErrorType::OtherError("Expected symbol after `as`".to_string()), self.current_token_range(), ); None } } else { None }; ast::Alias { range: self.node_range(start), name, asname, node_index: AtomicNodeIndex::NONE, } } /// Parses a dotted name. /// /// A dotted name is a sequence of identifiers separated by a single dot. fn parse_dotted_name(&mut self) -> ast::Identifier { let start = self.node_start(); let first = self.parse_identifier(); if !self.at(TokenKind::Dot) { return first; } let snapshot = self.name_buffer.len(); self.name_buffer.push_str(&first.id); let mut progress = ParserProgress::default(); while self.eat(TokenKind::Dot) { progress.assert_progressing(self); // test_err dotted_name_multiple_dots // import a..b // import a...b self.name_buffer.push('.'); let identifier = self.parse_identifier(); self.name_buffer.push_str(&identifier.id); } let id = self.name_interner.intern(&self.name_buffer[snapshot..]); self.name_buffer.truncate(snapshot); // test_ok dotted_name_normalized_spaces // import a.b.c // import a . b . c ast::Identifier { id, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `pass` statement. /// /// # Panics /// /// If the parser isn't positioned at a `pass` token. /// /// See: fn parse_pass_statement(&mut self) -> ast::StmtPass { let start = self.node_start(); self.bump(TokenKind::Pass); ast::StmtPass { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `continue` statement. /// /// # Panics /// /// If the parser isn't positioned at a `continue` token. /// /// See: fn parse_continue_statement(&mut self) -> ast::StmtContinue { let start = self.node_start(); self.bump(TokenKind::Continue); ast::StmtContinue { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `break` statement. /// /// # Panics /// /// If the parser isn't positioned at a `break` token. /// /// See: fn parse_break_statement(&mut self) -> ast::StmtBreak { let start = self.node_start(); self.bump(TokenKind::Break); ast::StmtBreak { range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `assert` statement. /// /// # Panics /// /// If the parser isn't positioned at an `assert` token. /// /// See: fn parse_assert_statement(&mut self) -> ast::StmtAssert { let start = self.node_start(); self.bump(TokenKind::Assert); // test_err assert_empty_test // assert // test_err assert_invalid_test_expr // assert *x // assert assert x // assert yield x // assert x := 1 let test = self.parse_conditional_expression_or_higher(); let msg = if self.eat(TokenKind::Comma) { if self.at_expr() { // test_err assert_invalid_msg_expr // assert False, *x // assert False, assert x // assert False, yield x // assert False, x := 1 Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } else { // test_err assert_empty_msg // assert x, self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; ast::StmtAssert { test: Box::new(test.expr), msg, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a global statement. /// /// # Panics /// /// If the parser isn't positioned at a `global` token. /// /// See: fn parse_global_statement(&mut self) -> ast::StmtGlobal { let start = self.node_start(); self.bump(TokenKind::Global); // test_err global_stmt_trailing_comma // global , // global x, // global x, y, // test_err global_stmt_expression // global x + 1 let names = self.parse_comma_separated_list_into_vec( RecoveryContextKind::Identifiers, Parser::parse_identifier, ); if names.is_empty() { // test_err global_stmt_empty // global self.add_error(ParseErrorType::EmptyGlobalNames, self.current_token_range()); } // test_ok global_stmt // global x // global x, y, z ast::StmtGlobal { range: self.node_range(start), names, node_index: AtomicNodeIndex::NONE, } } /// Parses a nonlocal statement. /// /// # Panics /// /// If the parser isn't positioned at a `nonlocal` token. /// /// See: fn parse_nonlocal_statement(&mut self) -> ast::StmtNonlocal { let start = self.node_start(); self.bump(TokenKind::Nonlocal); // test_err nonlocal_stmt_trailing_comma // def _(): // nonlocal , // nonlocal x, // nonlocal x, y, // test_err nonlocal_stmt_expression // def _(): // nonlocal x + 1 let names = self.parse_comma_separated_list_into_vec( RecoveryContextKind::Identifiers, Parser::parse_identifier, ); if names.is_empty() { // test_err nonlocal_stmt_empty // def _(): // nonlocal self.add_error( ParseErrorType::EmptyNonlocalNames, self.current_token_range(), ); } // test_ok nonlocal_stmt // def _(): // nonlocal x // nonlocal x, y, z ast::StmtNonlocal { range: self.node_range(start), names, node_index: AtomicNodeIndex::NONE, } } /// Parses a type alias statement. /// /// # Panics /// /// If the parser isn't positioned at a `type` token. /// /// See: fn parse_type_alias_statement(&mut self) -> ast::StmtTypeAlias { let start = self.node_start(); let type_range = self.current_token_range(); self.bump(TokenKind::Type); // test_ok type_stmt_py312 // # parse_options: {"target-version": "3.12"} // type x = int // test_err type_stmt_py311 // # parse_options: {"target-version": "3.11"} // type x = int self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::TypeAliasStatement, type_range, ); let mut name = Expr::Name(self.parse_name(ExpressionContext::default())); helpers::set_expr_ctx(&mut name, ExprContext::Store); let type_params = self.try_parse_type_params(); self.expect(TokenKind::Equal); // test_err type_alias_incomplete_stmt // type // type x // type x = // test_err type_alias_invalid_value_expr // type x = *y // type x = yield y // type x = yield from y // type x = x := 1 let value = self.parse_conditional_expression_or_higher(); ast::StmtTypeAlias { name: Box::new(name), type_params: type_params.map(Box::new), value: Box::new(value.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an IPython escape command at the statement level. /// /// # Panics /// /// If the parser isn't positioned at an `IpyEscapeCommand` token. fn parse_ipython_escape_command_statement(&mut self) -> ast::StmtIpyEscapeCommand { let start = self.node_start(); let (value, kind) = self.bump_ipython_escape_command(IpyEscapeContext::LogicalLineStart); let range = self.node_range(start); if self.options.mode != Mode::Ipython { self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, range); } ast::StmtIpyEscapeCommand { range, kind, value, node_index: AtomicNodeIndex::NONE, } } /// Parses an IPython help end escape command at the statement level. /// /// # Panics /// /// If the parser isn't positioned at a `?` token. fn parse_ipython_help_end_escape_command_statement( &mut self, parsed_expr: &ParsedExpr, ) -> ast::StmtIpyEscapeCommand { // 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 for IPython. fn unparse_expr(parser: &mut Parser, expr: &Expr, buffer: &mut String) { match expr { Expr::Name(ast::ExprName { id, .. }) => { buffer.push_str(id.as_str()); } Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { unparse_expr(parser, value, buffer); buffer.push('['); if let Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Int(integer), .. }) = &**slice { let _ = write!(buffer, "{integer}"); } else { parser.add_error( ParseErrorType::OtherError( "Only integer literals are allowed in subscript expressions \ in help end escape command" .to_string(), ), slice.range(), ); buffer.push_str(parser.src_text(slice.range())); } buffer.push(']'); } Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { unparse_expr(parser, value, buffer); buffer.push('.'); buffer.push_str(attr.as_str()); } _ => { parser.add_error( ParseErrorType::OtherError( "Expected name, subscript or attribute expression \ in help end escape command" .to_string(), ), expr, ); } } } let start = self.node_start(); self.bump(TokenKind::Question); let kind = if self.eat(TokenKind::Question) { IpyEscapeKind::Help2 } else { IpyEscapeKind::Help }; if parsed_expr.is_parenthesized { let token_range = self.node_range(start); self.add_error( ParseErrorType::OtherError( "Help end escape command cannot be applied on a parenthesized expression" .to_string(), ), token_range, ); } if self.at(TokenKind::Question) { self.add_error( ParseErrorType::OtherError( "Maximum of 2 `?` tokens are allowed in help end escape command".to_string(), ), self.current_token_range(), ); } let mut value = String::new(); unparse_expr(self, &parsed_expr.expr, &mut value); ast::StmtIpyEscapeCommand { value: value.into_boxed_str(), kind, range: self.node_range(parsed_expr.start()), node_index: AtomicNodeIndex::NONE, } } /// Parse an assignment statement. /// /// # Panics /// /// If the parser isn't positioned at an `=` token. /// /// See: fn parse_assign_statement(&mut self, target: ParsedExpr, start: TextSize) -> ast::StmtAssign { self.bump(TokenKind::Equal); let mut targets = vec![target.expr]; // test_err assign_stmt_missing_rhs // x = // 1 + 1 // x = y = // 2 + 2 // x = = y // 3 + 3 // test_err assign_stmt_keyword_target // a = pass = c // a + b // a = b = pass = c // a + b // test_err assign_stmt_invalid_value_expr // x = (*a and b,) // x = (42, *yield x) // x = (42, *yield from x) // x = (*lambda x: x,) // x = x := 1 let mut value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); if self.at(TokenKind::Equal) { // This path is only taken when there are more than one assignment targets. self.parse_list(RecoveryContextKind::AssignmentTargets, |parser| { parser.bump(TokenKind::Equal); let mut parsed_expr = parser.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); std::mem::swap(&mut value, &mut parsed_expr); targets.push(parsed_expr.expr); }); } for target in &mut targets { helpers::set_expr_ctx(target, ExprContext::Store); // test_err assign_stmt_invalid_target // 1 = 1 // x = 1 = 2 // x = 1 = y = 2 = z // ["a", "b"] = ["a", "b"] self.validate_assignment_target(target); } ast::StmtAssign { targets, value: Box::new(value.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an annotated assignment statement. /// /// # Panics /// /// If the parser isn't positioned at a `:` token. /// /// See: fn parse_annotated_assignment_statement( &mut self, mut target: ParsedExpr, start: TextSize, ) -> ast::StmtAnnAssign { self.bump(TokenKind::Colon); // test_err ann_assign_stmt_invalid_target // "abc": str = "def" // call(): str = "no" // *x: int = 1, 2 // # Tuple assignment // x,: int = 1 // x, y: int = 1, 2 // (x, y): int = 1, 2 // # List assignment // [x]: int = 1 // [x, y]: int = 1, 2 self.validate_annotated_assignment_target(&target.expr); helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); // test_ok ann_assign_stmt_simple_target // a: int # simple // (a): int // a.b: int // a[0]: int let simple = target.is_name_expr() && !target.is_parenthesized; // test_err ann_assign_stmt_invalid_annotation // x: *int = 1 // x: yield a = 1 // x: yield from b = 1 // x: y := int = 1 // test_err ann_assign_stmt_type_alias_annotation // a: type X = int // lambda: type X = int let annotation = self.parse_conditional_expression_or_higher(); let value = if self.eat(TokenKind::Equal) { if self.at_expr() { // test_err ann_assign_stmt_invalid_value // x: Any = *a and b // x: Any = x := 1 // x: list = [x, *a | b, *a or b] Some(Box::new( self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()) .expr, )) } else { // test_err ann_assign_stmt_missing_rhs // x: int = self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; ast::StmtAnnAssign { target: Box::new(target.expr), annotation: Box::new(annotation.expr), value, simple, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an augmented assignment statement. /// /// # Panics /// /// If the parser isn't positioned at an augmented assignment token. /// /// See: fn parse_augmented_assignment_statement( &mut self, mut target: ParsedExpr, op: Operator, start: TextSize, ) -> ast::StmtAugAssign { // Consume the operator self.bump_ts(AUGMENTED_ASSIGN_SET); if !matches!( &target.expr, Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) ) { // test_err aug_assign_stmt_invalid_target // 1 += 1 // "a" += "b" // *x += 1 // pass += 1 // x += pass // (x + y) += 1 self.add_error(ParseErrorType::InvalidAugmentedAssignmentTarget, &target); } helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); // test_err aug_assign_stmt_missing_rhs // x += // 1 + 1 // x += y += // 2 + 2 // test_err aug_assign_stmt_invalid_value // x += *a and b // x += *yield x // x += *yield from x // x += *lambda x: x // x += y := 1 let value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); ast::StmtAugAssign { target: Box::new(target.expr), op, value: Box::new(value.expr), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `if` statement. /// /// # Panics /// /// If the parser isn't positioned at an `if` token. /// /// See: fn parse_if_statement(&mut self) -> ast::StmtIf { let start = self.node_start(); self.bump(TokenKind::If); // test_err if_stmt_invalid_test_expr // if *x: ... // if yield x: ... // if yield from x: ... // test_err if_stmt_missing_test // if : ... let test = self.parse_named_expression_or_higher(ExpressionContext::default()); // test_err if_stmt_missing_colon // if x // if x // pass // a = 1 self.expect(TokenKind::Colon); // test_err if_stmt_empty_body // if True: // 1 + 1 let body = self.parse_body(Clause::If); // test_err if_stmt_misspelled_elif // if True: // pass // elf: // pass // else: // pass let elif_else_snapshot = self.elif_else_scratch.snapshot(); self.parse_clauses(Clause::ElIf, |parser| { let clause = parser.parse_elif_or_else_clause(ElifOrElse::Elif); parser.elif_else_scratch.push(clause); }); if self.at(TokenKind::Else) { let clause = self.parse_elif_or_else_clause(ElifOrElse::Else); self.elif_else_scratch.push(clause); } ast::StmtIf { test: Box::new(test.expr), body, elif_else_clauses: self.elif_else_scratch.take(elif_else_snapshot), range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `elif` or `else` clause. /// /// # Panics /// /// If the parser isn't positioned at an `elif` or `else` token. fn parse_elif_or_else_clause(&mut self, kind: ElifOrElse) -> ast::ElifElseClause { let start = self.node_start(); self.bump(kind.as_token_kind()); let test = if kind.is_elif() { // test_err if_stmt_invalid_elif_test_expr // if x: // pass // elif *x: // pass // elif yield x: // pass Some( self.parse_named_expression_or_higher(ExpressionContext::default()) .expr, ) } else { None }; // test_err if_stmt_elif_missing_colon // if x: // pass // elif y // pass // else: // pass self.expect(TokenKind::Colon); let body = self.parse_body(kind.as_clause()); ast::ElifElseClause { test, body, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `try` statement. /// /// # Panics /// /// If the parser isn't positioned at a `try` token. /// /// See: fn parse_try_statement(&mut self) -> ast::StmtTry { let try_start = self.node_start(); self.bump(TokenKind::Try); self.expect(TokenKind::Colon); let mut is_star: Option = None; let try_body = self.parse_body(Clause::Try); let has_except = self.at(TokenKind::Except); // test_err try_stmt_mixed_except_kind // try: // pass // except: // pass // except* ExceptionGroup: // pass // try: // pass // except* ExceptionGroup: // pass // except: // pass // try: // pass // except: // pass // except: // pass // except* ExceptionGroup: // pass // except* ExceptionGroup: // pass let mut mixed_except_ranges = Vec::new(); let mut handlers = Vec::new(); self.parse_clauses(Clause::Except, |p| { let (handler, kind) = p.parse_except_clause(); if let ExceptClauseKind::Star(range) = kind { p.add_unsupported_syntax_error(UnsupportedSyntaxErrorKind::ExceptStar, range); } if is_star.is_none() { is_star = Some(kind.is_star()); } else if is_star != Some(kind.is_star()) { mixed_except_ranges.push(handler.range()); } if handlers.is_empty() { handlers.reserve_exact(1); } handlers.push(handler); }); handlers.shrink_to_fit(); // Empty handler has `is_star` false. let is_star = is_star.unwrap_or_default(); for handler_err_range in mixed_except_ranges { self.add_error( ParseErrorType::OtherError( "Cannot have both 'except' and 'except*' on the same 'try'".to_string(), ), handler_err_range, ); } // test_err try_stmt_misspelled_except // try: // pass // exept: # spellchecker:disable-line // pass // finally: // pass // a = 1 // try: // pass // except: // pass // exept: # spellchecker:disable-line // pass // b = 1 let orelse = if self.eat(TokenKind::Else) { self.expect(TokenKind::Colon); self.parse_body(Clause::Else) } else { Suite::new() }; let (finalbody, has_finally) = if self.eat(TokenKind::Finally) { self.expect(TokenKind::Colon); (self.parse_body(Clause::Finally), true) } else { (Suite::new(), false) }; if !has_except && !has_finally { // test_err try_stmt_missing_except_finally // try: // pass // try: // pass // else: // pass self.add_error( ParseErrorType::OtherError( "Expected `except` or `finally` after `try` block".to_string(), ), self.current_token_range(), ); } if has_finally && self.at(TokenKind::Else) { // test_err try_stmt_invalid_order // try: // pass // finally: // pass // else: // pass self.add_error( ParseErrorType::OtherError( "`else` block must come before `finally` block".to_string(), ), self.current_token_range(), ); } // test_ok except_star_py311 // # parse_options: {"target-version": "3.11"} // try: ... // except* ValueError: ... // test_err except_star_py310 // # parse_options: {"target-version": "3.10"} // try: ... // except* ValueError: ... // except* KeyError: ... // except * Error: ... ast::StmtTry { body: try_body, handlers, orelse, finalbody, is_star, range: self.node_range(try_start), node_index: AtomicNodeIndex::NONE, } } /// Parses an `except` clause of a `try` statement. /// /// # Panics /// /// If the parser isn't positioned at an `except` token. fn parse_except_clause(&mut self) -> (ExceptHandler, ExceptClauseKind) { let start = self.node_start(); self.bump(TokenKind::Except); let star_token_range = self.current_token_range(); let block_kind = if self.eat(TokenKind::Star) { ExceptClauseKind::Star(star_token_range) } else { ExceptClauseKind::Normal }; let type_ = if self.at_expr() { // test_err except_stmt_invalid_expression // try: // pass // except yield x: // pass // try: // pass // except* *x: // pass let parsed_expr = self.parse_expression_list(ExpressionContext::default()); if matches!( parsed_expr.expr, Expr::Tuple(ast::ExprTuple { parenthesized: false, .. }) ) { if self.at(TokenKind::As) { // test_err except_stmt_unparenthesized_tuple_as // try: // pass // except x, y as exc: // pass // try: // pass // except* x, y as eg: // pass self.add_error( ParseErrorType::OtherError( "Multiple exception types must be parenthesized when using `as`" .to_string(), ), &parsed_expr, ); } else { // test_err except_stmt_unparenthesized_tuple_no_as_py313 // # parse_options: {"target-version": "3.13"} // try: // pass // except x, y: // pass // try: // pass // except* x, y: // pass // test_ok except_stmt_unparenthesized_tuple_no_as_py314 // # parse_options: {"target-version": "3.14"} // try: // pass // except x, y: // pass // try: // pass // except* x, y: // pass self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::UnparenthesizedExceptionTypes, parsed_expr.range(), ); } } Some(Box::new(parsed_expr.expr)) } else { if block_kind.is_star() || self.at(TokenKind::As) { // test_err except_stmt_missing_exception // try: // pass // except as exc: // pass // # If a '*' is present then exception type is required // try: // pass // except*: // pass // except* // pass // except* as exc: // pass self.add_error( ParseErrorType::OtherError("Expected one or more exception types".to_string()), self.current_token_range(), ); } None }; let name = if self.eat(TokenKind::As) { if self.at_name_or_soft_keyword() { // test_ok except_stmt_as_name_soft_keyword // try: ... // except Exception as match: ... // except Exception as case: ... // except Exception as type: ... Some(self.parse_identifier()) } else { // test_err except_stmt_missing_as_name // try: // pass // except Exception as: // pass // except Exception as // pass self.add_error( ParseErrorType::OtherError("Expected name after `as`".to_string()), self.current_token_range(), ); None } } else { None }; // test_err except_stmt_missing_exception_and_as_name // try: // pass // except as: // pass self.expect(TokenKind::Colon); let except_body = self.parse_body(Clause::Except); ( ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, name, body: except_body, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }), block_kind, ) } /// Parses a `for` statement. /// /// The given `start` offset is the start of either the `for` token or the /// `async` token if it's an async for statement. /// /// # Panics /// /// If the parser isn't positioned at a `for` token. /// /// See: fn parse_for_statement(&mut self, start: TextSize) -> ast::StmtFor { self.bump(TokenKind::For); // test_err for_stmt_missing_target // for in x: ... // test_ok for_in_target_valid_expr // for d[x in y] in target: ... // for (x in y)[0] in iter: ... // for (x in y).attr in iter: ... // test_err for_stmt_invalid_target_in_keyword // for d(x in y) in target: ... // for (x in y)() in iter: ... // for (x in y) in iter: ... // for (x in y, z) in iter: ... // for [x in y, z] in iter: ... // for {x in y, z} in iter: ... // test_err for_stmt_invalid_target_binary_expr // for x not in y in z: ... // for x == y in z: ... // for x or y in z: ... // for -x in y: ... // for not x in y: ... // for x | y in z: ... let mut target = self.parse_expression_list(ExpressionContext::starred_conditional().with_in_excluded()); helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); // test_err for_stmt_invalid_target // for 1 in x: ... // for "a" in x: ... // for *x and y in z: ... // for *x | y in z: ... // for await x in z: ... // for yield x in y: ... // for [x, 1, y, *["a"]] in z: ... self.validate_assignment_target(&target.expr); // test_err for_stmt_missing_in_keyword // for a b: ... // for a: ... self.expect(TokenKind::In); // test_err for_stmt_missing_iter // for x in: // a = 1 // test_err for_stmt_invalid_iter_expr // for x in *a and b: ... // for x in yield a: ... // for target in x := 1: ... let iter = self.parse_expression_list(ExpressionContext::starred_bitwise_or()); // test_ok for_iter_unpack_py39 // # parse_options: {"target-version": "3.9"} // for x in *a, b: ... // for x in a, *b: ... // for x in *a, *b: ... // test_ok for_iter_unpack_py38 // # parse_options: {"target-version": "3.8"} // for x in (*a, b): ... // for x in ( a, *b): ... // for x in (*a, *b): ... // test_err for_iter_unpack_py38 // # parse_options: {"target-version": "3.8"} // for x in *a, b: ... // for x in a, *b: ... // for x in *a, *b: ... self.check_tuple_unpacking( &iter, UnsupportedSyntaxErrorKind::UnparenthesizedUnpackInFor, ); self.expect(TokenKind::Colon); let body = self.parse_body(Clause::For); let orelse = if self.eat(TokenKind::Else) { self.expect(TokenKind::Colon); self.parse_body(Clause::Else) } else { Suite::new() }; ast::StmtFor { target: Box::new(target.expr), iter: Box::new(iter.expr), is_async: false, body, orelse, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a `while` statement. /// /// # Panics /// /// If the parser isn't positioned at a `while` token. /// /// See: fn parse_while_statement(&mut self) -> ast::StmtWhile { let start = self.node_start(); self.bump(TokenKind::While); // test_err while_stmt_missing_test // while : ... // while : // a = 1 // test_err while_stmt_invalid_test_expr // while *x: ... // while yield x: ... // while a, b: ... // while a := 1, b: ... let test = self.parse_named_expression_or_higher(ExpressionContext::default()); // test_err while_stmt_missing_colon // while ( // a < 30 # comment // ) // pass self.expect(TokenKind::Colon); let body = self.parse_body(Clause::While); let orelse = if self.eat(TokenKind::Else) { self.expect(TokenKind::Colon); self.parse_body(Clause::Else) } else { Suite::new() }; ast::StmtWhile { test: Box::new(test.expr), body, orelse, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a function definition. /// /// The given `start` offset is the start of either of the following: /// - `def` token /// - `async` token if it's an asynchronous function definition with no decorators /// - `@` token if the function definition has decorators /// /// # Panics /// /// If the parser isn't positioned at a `def` token. /// /// See: fn parse_function_definition( &mut self, decorator_list: DecoratorList, start: TextSize, ) -> ast::StmtFunctionDef { self.bump(TokenKind::Def); // test_err function_def_missing_identifier // def (): ... // def () -> int: ... let name = self.parse_identifier(); // test_err function_def_unclosed_type_param_list // def foo[T1, *T2(a, b): // return a + b // x = 10 let type_params = self.try_parse_type_params(); // test_ok function_type_params_py312 // # parse_options: {"target-version": "3.12"} // def foo[T](): ... // test_err function_type_params_py311 // # parse_options: {"target-version": "3.11"} // def foo[T](): ... // def foo[](): ... if let Some(ast::TypeParams { range, .. }) = &type_params { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::TypeParameterList, *range, ); } // test_ok function_def_parameter_range // def foo( // first: int, // second: int, // ) -> int: ... // test_err function_def_unclosed_parameter_list // def foo(a: int, b: // def foo(): // return 42 // def foo(a: int, b: str // x = 10 let parameters = self.parse_parameters(FunctionKind::FunctionDef); let returns = if self.eat(TokenKind::Rarrow) { if self.at_expr() { // test_ok function_def_valid_return_expr // def foo() -> int | str: ... // def foo() -> lambda x: x: ... // def foo() -> int if True else str: ... // test_err function_def_invalid_return_expr // def foo() -> *int: ... // def foo() -> (*int): ... // def foo() -> yield x: ... let returns = self.parse_expression_list(ExpressionContext::default()); if matches!( returns.expr, Expr::Tuple(ast::ExprTuple { parenthesized: false, .. }) ) { // test_ok function_def_parenthesized_return_types // def foo() -> (int,): ... // def foo() -> (int, str): ... // test_err function_def_unparenthesized_return_types // def foo() -> int,: ... // def foo() -> int, str: ... self.add_error( ParseErrorType::OtherError( "Multiple return types must be parenthesized".to_string(), ), returns.range(), ); } Some(Box::new(returns.expr)) } else { // test_err function_def_missing_return_type // def foo() -> : ... self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; self.expect(TokenKind::Colon); // test_err function_def_empty_body // def foo(): // def foo() -> int: // x = 42 let body = self.parse_body(Clause::FunctionDef); ast::StmtFunctionDef { name, type_params: type_params.map(Box::new), parameters: Box::new(parameters), body, decorator_list, is_async: false, returns, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a class definition. /// /// The given `start` offset is the start of either the `def` token or the /// `@` token if the class definition has decorators. /// /// # Panics /// /// If the parser isn't positioned at a `class` token. /// /// See: fn parse_class_definition( &mut self, decorator_list: DecoratorList, start: TextSize, ) -> ast::StmtClassDef { self.bump(TokenKind::Class); // test_err class_def_missing_name // class : ... // class (): ... // class (metaclass=ABC): ... let name = self.parse_identifier(); // test_err class_def_unclosed_type_param_list // class Foo[T1, *T2(a, b): // pass // x = 10 let type_params = self.try_parse_type_params(); // test_ok class_type_params_py312 // # parse_options: {"target-version": "3.12"} // class Foo[S: (str, bytes), T: float, *Ts, **P]: ... // test_err class_type_params_py311 // # parse_options: {"target-version": "3.11"} // class Foo[S: (str, bytes), T: float, *Ts, **P]: ... // class Foo[]: ... if let Some(ast::TypeParams { range, .. }) = &type_params { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::TypeParameterList, *range, ); } // test_ok class_def_arguments // class Foo: ... // class Foo(): ... // class Foo((base for base in bases)): ... // class Foo(*(base for base in bases)): ... // test_err class_def_unparenthesized_generator_argument // class Foo(base for base in bases): ... let arguments = self .at(TokenKind::Lpar) .then(|| Box::new(self.parse_arguments(ArgumentsContext::ClassDefinition))); self.expect(TokenKind::Colon); // test_err class_def_empty_body // class Foo: // class Foo(): // x = 42 let body = self.parse_body(Clause::Class); ast::StmtClassDef { range: self.node_range(start), decorator_list, name, type_params: type_params.map(Box::new), arguments, body, node_index: AtomicNodeIndex::NONE, } } /// Parses a `with` statement /// /// The given `start` offset is the start of either the `with` token or the /// `async` token if it's an async with statement. /// /// # Panics /// /// If the parser isn't positioned at a `with` token. /// /// See: fn parse_with_statement(&mut self, start: TextSize) -> ast::StmtWith { self.bump(TokenKind::With); let mut items = self.parse_with_items(); items.shrink_to_fit(); self.expect(TokenKind::Colon); let body = self.parse_body(Clause::With); ast::StmtWith { items, body, is_async: false, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a list of with items. /// /// See: fn parse_with_items(&mut self) -> Vec { if !self.at_expr() { self.add_error( ParseErrorType::OtherError( "Expected the start of an expression after `with` keyword".to_string(), ), self.current_token_range(), ); return vec![]; } let open_paren_range = self.current_token_range(); if self.at(TokenKind::Lpar) { if let (Some(items), has_trailing_comma) = self.try_parse_parenthesized_with_items() { // test_ok tuple_context_manager_py38 // # parse_options: {"target-version": "3.8"} // with ( // foo, // bar, // baz, // ) as tup: ... // test_ok single_parenthesized_item_context_manager_py38 // # parse_options: {"target-version": "3.8"} // with ( // open('foo.txt')) as foo: ... // with ( // open('foo.txt')): ... // test_err tuple_context_manager_py38 // # parse_options: {"target-version": "3.8"} // # these cases are _syntactically_ valid before Python 3.9 because the `with` item // # is parsed as a tuple, but this will always cause a runtime error, so we flag it // # anyway // with (foo, bar): ... // with ( // foo, // bar, // baz, // ): ... // with (foo,): ... // test_ok parenthesized_context_manager_py39 // # parse_options: {"target-version": "3.9"} // with (foo as x, bar as y): ... // with (foo, bar as y): ... // with (foo as x, bar): ... // test_err parenthesized_context_manager_py38 // # parse_options: {"target-version": "3.8"} // with (foo as x, bar as y): ... // with (foo, bar as y): ... // with (foo as x, bar): ... if items.len() > 1 || has_trailing_comma { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::ParenthesizedContextManager, open_paren_range, ); } self.expect(TokenKind::Rpar); items } else { // test_ok ambiguous_lpar_with_items_if_expr // with (x) if True else y: ... // with (x for x in iter) if True else y: ... // with (x async for x in iter) if True else y: ... // with (x)[0] if True else y: ... // test_ok ambiguous_lpar_with_items_binary_expr // # It doesn't matter what's inside the parentheses, these tests need to make sure // # all binary expressions parses correctly. // with (a) and b: ... // with (a) is not b: ... // # Make sure precedence works // with (a) or b and c: ... // with (a) and b or c: ... // with (a | b) << c | d: ... // # Postfix should still be parsed first // with (a)[0] + b * c: ... self.parse_comma_separated_list_into_vec_with_capacity( RecoveryContextKind::WithItems(WithItemKind::ParenthesizedExpression), |p| p.parse_with_item(WithItemParsingState::Regular).item, 1, ) } } else { self.parse_comma_separated_list_into_vec_with_capacity( RecoveryContextKind::WithItems(WithItemKind::Unparenthesized), |p| p.parse_with_item(WithItemParsingState::Regular).item, 1, ) } } /// Try parsing with-items coming after an ambiguous `(` token. /// /// To understand the ambiguity, consider the following example: /// /// ```python /// with (item1, item2): ... # Parenthesized with items /// with (item1, item2) as f: ... # Parenthesized expression /// ``` /// /// When the parser is at the `(` token after the `with` keyword, it doesn't know if `(` is /// used to parenthesize the with items or if it's part of a parenthesized expression of the /// first with item. The challenge here is that until the parser sees the matching `)` token, /// it can't resolve the ambiguity. /// /// This method resolves the ambiguity using speculative parsing. It starts with an assumption /// that it's a parenthesized with items. Then, once it finds the matching `)`, it checks if /// the assumption still holds true. If the initial assumption was correct, this will return /// the parsed with items. Otherwise, rewind the parser back to the starting `(` token, /// returning [`None`]. /// /// # Panics /// /// If the parser isn't positioned at a `(` token. /// /// See: fn try_parse_parenthesized_with_items(&mut self) -> (Option>, bool) { let checkpoint = self.checkpoint(); // We'll start with the assumption that the with items are parenthesized. let mut with_item_kind = WithItemKind::Parenthesized; self.bump(TokenKind::Lpar); let mut parsed_with_items = Vec::with_capacity(1); let mut has_optional_vars = false; // test_err with_items_parenthesized_missing_comma // with (item1 item2): ... // with (item1 as f1 item2): ... // with (item1, item2 item3, item4): ... // with (item1, item2 as f1 item3, item4): ... // with (item1, item2: ... let has_trailing_comma = self.parse_comma_separated_list(RecoveryContextKind::WithItems(with_item_kind), |p| { let parsed_with_item = p.parse_with_item(WithItemParsingState::Speculative); has_optional_vars |= parsed_with_item.item.optional_vars.is_some(); parsed_with_items.push(parsed_with_item); }); // Check if our assumption is incorrect and it's actually a parenthesized expression. if has_optional_vars { // If any of the with item has optional variables, then our assumption is correct // and it is a parenthesized with items. Now, we need to restrict the grammar for a // with item's context expression which is: // // with_item: expression ... // // So, named, starred and yield expressions not allowed. for parsed_with_item in &parsed_with_items { if parsed_with_item.is_parenthesized { // Parentheses resets the precedence. continue; } let error = match parsed_with_item.item.context_expr { Expr::Named(_) => ParseErrorType::UnparenthesizedNamedExpression, Expr::Starred(_) => ParseErrorType::InvalidStarredExpressionUsage, Expr::Yield(_) | Expr::YieldFrom(_) => { ParseErrorType::InvalidYieldExpressionUsage } _ => continue, }; self.add_error(error, &parsed_with_item.item.context_expr); } } else if self.at(TokenKind::Rpar) && ( // test_err with_items_parenthesized_missing_colon // # `)` followed by a newline // with (item1, item2) // pass matches!(self.peek(), TokenKind::Colon | TokenKind::Newline) ) { if parsed_with_items.is_empty() { // No with items, treat it as a parenthesized expression to create an empty // tuple expression. with_item_kind = WithItemKind::ParenthesizedExpression; } else { // These expressions, if unparenthesized, are only allowed if it's a // parenthesized expression and none of the with items have an optional // variable. if parsed_with_items.iter().any(|parsed_with_item| { !parsed_with_item.is_parenthesized && matches!( parsed_with_item.item.context_expr, Expr::Named(_) | Expr::Starred(_) | Expr::Yield(_) | Expr::YieldFrom(_) ) }) { with_item_kind = WithItemKind::ParenthesizedExpression; } } } else { // For any other token followed by `)`, if any of the items has an optional // variables (`as ...`), then our assumption is correct. Otherwise, treat // it as a parenthesized expression. For example: // // ```python // with (item1, item2 as f): ... // ``` // // This also helps in raising the correct syntax error for the following // case: // ```python // with (item1, item2 as f) as x: ... // # ^^ // # Expecting `:` but got `as` // ``` with_item_kind = WithItemKind::ParenthesizedExpression; } let with_items = if with_item_kind.is_parenthesized() { let with_items: Vec<_> = parsed_with_items .into_iter() .map(|parsed_with_item| parsed_with_item.item) .collect(); Some(with_items) } else { self.rewind(checkpoint); None }; (with_items, has_trailing_comma) } /// Parses a single `with` item. /// /// See: fn parse_with_item(&mut self, state: WithItemParsingState) -> ParsedWithItem { let start = self.node_start(); // The grammar for the context expression of a with item depends on the state // of with item parsing. let context_expr = match state { WithItemParsingState::Speculative => { // If it's in a speculative state, the parenthesis (`(`) could be part of any of the // following expression: // // Tuple expression - star_named_expression // Generator expression - named_expression // Parenthesized expression - (yield_expr | named_expression) // Parenthesized with items - expression // // Here, the right side specifies the grammar for an element corresponding to the // expression mentioned in the left side. // // So, the grammar used should be able to parse an element belonging to any of the // above expression. At a later point, once the parser understands where the // parenthesis belongs to, it'll validate and report errors for any invalid expression // usage. // // Thus, we can conclude that the grammar used should be: // (yield_expr | star_named_expression) self.parse_named_expression_or_higher( ExpressionContext::yield_or_starred_bitwise_or(), ) } WithItemParsingState::Regular => self.parse_conditional_expression_or_higher(), }; let optional_vars = self .at(TokenKind::As) .then(|| Box::new(self.parse_with_item_optional_vars().expr)); ParsedWithItem { is_parenthesized: context_expr.is_parenthesized, item: ast::WithItem { range: self.node_range(start), context_expr: context_expr.expr, optional_vars, node_index: AtomicNodeIndex::NONE, }, } } /// Parses the optional variables in a `with` item. /// /// # Panics /// /// If the parser isn't positioned at an `as` token. fn parse_with_item_optional_vars(&mut self) -> ParsedExpr { self.bump(TokenKind::As); let mut target = self .parse_conditional_expression_or_higher_impl(ExpressionContext::starred_conditional()); // This has the same semantics as an assignment target. self.validate_assignment_target(&target.expr); helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); target } /// Try parsing a `match` statement. /// /// This uses speculative parsing to remove the ambiguity of whether the `match` token is used /// as a keyword or an identifier. This ambiguity arises only in if the `match` token is /// followed by certain tokens. For example, if `match` is followed by `[`, we can't know if /// it's used in the context of a subscript expression or as a list expression: /// /// ```python /// # Subscript expression; `match` is an identifier /// match[x] /// /// # List expression; `match` is a keyword /// match [x, y]: /// case [1, 2]: /// pass /// ``` /// /// This is done by parsing the subject expression considering `match` as a keyword token. /// Then, based on certain heuristics we'll determine if our assumption is true. If so, we'll /// continue parsing the entire match statement. Otherwise, return `None`. /// /// # Panics /// /// If the parser isn't positioned at a `match` token. /// /// See: fn try_parse_match_statement(&mut self) -> Option { let checkpoint = self.checkpoint(); let start = self.node_start(); self.bump(TokenKind::Match); let subject = self.parse_match_subject_expression(); match self.current_token_kind() { // test_ok match_annotated_assignment // match[0]: int // match [x, y, z]: dict TokenKind::Colon if self.peek() == TokenKind::Newline => { // `match` is a keyword — colon followed by newline confirms // this is a match statement, not an annotated assignment like // `match [x, y, z]: {dict}` or `match[0]: int`. self.bump(TokenKind::Colon); let cases = self.parse_match_body(); Some(ast::StmtMatch { subject: Box::new(subject), cases, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } TokenKind::Newline if matches!(self.peek2(), (TokenKind::Indent, TokenKind::Case)) => { // `match` is a keyword // test_err match_expected_colon // match [1, 2] // case _: ... self.add_error( ParseErrorType::ExpectedToken { found: self.current_token_kind(), expected: TokenKind::Colon, }, self.current_token_range(), ); let cases = self.parse_match_body(); Some(ast::StmtMatch { subject: Box::new(subject), cases, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, }) } _ => { // `match` is an identifier self.rewind(checkpoint); None } } } /// Parses a match statement. /// /// # Panics /// /// If the parser isn't positioned at a `match` token. /// /// See: fn parse_match_statement(&mut self) -> ast::StmtMatch { let start = self.node_start(); self.bump(TokenKind::Match); let match_range = self.node_range(start); let subject = self.parse_match_subject_expression(); self.expect(TokenKind::Colon); let cases = self.parse_match_body(); // test_err match_before_py310 // # parse_options: { "target-version": "3.9" } // match 2: // case 1: // pass // test_ok match_after_py310 // # parse_options: { "target-version": "3.10" } // match 2: // case 1: // pass self.add_unsupported_syntax_error(UnsupportedSyntaxErrorKind::Match, match_range); ast::StmtMatch { subject: Box::new(subject), cases, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses the subject expression for a `match` statement. fn parse_match_subject_expression(&mut self) -> Expr { let start = self.node_start(); // Subject expression grammar is: // // subject_expr: // | star_named_expression ',' star_named_expressions? // | named_expression // // First try with `star_named_expression`, then if there's no comma, // we'll restrict it to `named_expression`. let subject = self.parse_named_expression_or_higher(ExpressionContext::starred_bitwise_or()); // test_ok match_stmt_subject_expr // match x := 1: // case _: ... // match (x := 1): // case _: ... // # Starred expressions are only allowed in tuple expression // match *x | y, z: // case _: ... // match await x: // case _: ... // test_err match_stmt_invalid_subject_expr // match (*x): // case _: ... // # Starred expression precedence test // match *x and y, z: // case _: ... // match yield x: // case _: ... if self.at(TokenKind::Comma) { let tuple = self.parse_tuple_expression(subject.expr, start, Parenthesized::No, |p| { p.parse_named_expression_or_higher(ExpressionContext::starred_bitwise_or()) }); Expr::Tuple(tuple) } else { if subject.is_unparenthesized_starred_expr() { // test_err match_stmt_single_starred_subject // match *foo: // case _: ... self.add_error(ParseErrorType::InvalidStarredExpressionUsage, &subject); } subject.expr } } /// Parses the body of a `match` statement. /// /// This method expects that the parser is positioned at a `Newline` token. If not, it adds a /// syntax error and continues parsing. fn parse_match_body(&mut self) -> Vec { // test_err match_stmt_no_newline_before_case // match foo: case _: ... self.expect(TokenKind::Newline); // Use `eat` instead of `expect` for better error message. if !self.eat(TokenKind::Indent) { // test_err match_stmt_expect_indented_block // match foo: // case _: ... self.add_error( ParseErrorType::OtherError( "Expected an indented block after `match` statement".to_string(), ), self.current_token_range(), ); } let cases = self.parse_match_case_blocks(); // TODO(dhruvmanila): Should we expect `Dedent` only if there was an `Indent` present? self.expect(TokenKind::Dedent); cases } /// Parses a list of match case blocks. fn parse_match_case_blocks(&mut self) -> Vec { let mut cases = vec![]; if !self.at(TokenKind::Case) { // test_err match_stmt_expected_case_block // match x: // x = 1 // match x: // match y: // case _: ... self.add_error( ParseErrorType::OtherError("Expected `case` block".to_string()), self.current_token_range(), ); return cases; } let mut progress = ParserProgress::default(); while self.at(TokenKind::Case) { progress.assert_progressing(self); cases.push(self.parse_match_case()); } cases } /// Parses a single match case block. /// /// # Panics /// /// If the parser isn't positioned at a `case` token. /// /// See: fn parse_match_case(&mut self) -> ast::MatchCase { let start = self.node_start(); self.bump(TokenKind::Case); // test_err match_stmt_missing_pattern // match x: // case : ... let pattern = self.parse_match_patterns(); let guard = if self.eat(TokenKind::If) { if self.at_expr() { // test_ok match_stmt_valid_guard_expr // match x: // case y if a := 1: ... // match x: // case y if a if True else b: ... // match x: // case y if lambda a: b: ... // match x: // case y if (yield x): ... // test_err match_stmt_invalid_guard_expr // match x: // case y if *a: ... // match x: // case y if (*a): ... // match x: // case y if yield x: ... Some(Box::new( self.parse_named_expression_or_higher(ExpressionContext::default()) .expr, )) } else { // test_err match_stmt_missing_guard_expr // match x: // case y if: ... self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; self.expect(TokenKind::Colon); // test_err case_expect_indented_block // match subject: // case 1: // case 2: ... let body = self.parse_body(Clause::Case); ast::MatchCase { pattern, guard, body, range: self.node_range(start), node_index: AtomicNodeIndex::NONE, } } /// Parses a statement that is valid after an `async` token. /// /// If the statement is not a valid `async` statement, an error will be reported /// and it will be parsed as a statement. /// /// See: /// - /// - /// - fn parse_async_statement(&mut self) -> Stmt { let async_start = self.node_start(); self.bump(TokenKind::Async); match self.current_token_kind() { // test_ok async_function_definition // async def foo(): ... TokenKind::Def => Stmt::FunctionDef(ast::StmtFunctionDef { is_async: true, ..self.parse_function_definition(DecoratorList::new(), async_start) }), // test_ok async_with_statement // async with item: ... TokenKind::With => Stmt::With(ast::StmtWith { is_async: true, ..self.parse_with_statement(async_start) }), // test_ok async_for_statement // async for target in iter: ... TokenKind::For => Stmt::For(ast::StmtFor { is_async: true, ..self.parse_for_statement(async_start) }), kind => { // test_err async_unexpected_token // async class Foo: ... // async while test: ... // async x = 1 // async async def foo(): ... // async match test: // case _: ... self.add_error( ParseErrorType::UnexpectedTokenAfterAsync(kind), self.current_token_range(), ); // Although this statement is not a valid `async` statement, // we still parse it. Guard the recursive recovery path so // `async async async ...` cannot overflow the parser stack. if let Some(stmt) = self.with_recursion(Self::parse_statement) { stmt } else { let range = self.node_range(async_start); self.add_error(ParseErrorType::RecursionLimitExceeded, range); Stmt::Expr(ast::StmtExpr { range, value: Box::new(Expr::Name(ast::ExprName { range, id: Name::new_static("async"), ctx: ExprContext::Invalid, node_index: AtomicNodeIndex::NONE, })), node_index: AtomicNodeIndex::NONE, }) } } } } /// Parses a decorator list followed by a class, function or async function definition. /// /// See: fn parse_decorators(&mut self) -> Stmt { let start = self.node_start(); let mut decorators = DecoratorList::new(); let mut progress = ParserProgress::default(); // test_err decorator_missing_expression // @def foo(): ... // @ // def foo(): ... // @@ // def foo(): ... // @test // @ // class Test while self.at(TokenKind::At) { progress.assert_progressing(self); let decorator_start = self.node_start(); self.bump(TokenKind::At); let parsed_expr = if self.at(TokenKind::Def) || self.at(TokenKind::Class) { Expr::Name(self.parse_missing_name()).into() } else { self.parse_named_expression_or_higher(ExpressionContext::default()) }; if self.options.target_version < PythonVersion::PY39 { // test_ok decorator_expression_dotted_ident_py38 // # parse_options: { "target-version": "3.8" } // @buttons.clicked.connect // def spam(): ... // test_ok decorator_expression_identity_hack_py38 // # parse_options: { "target-version": "3.8" } // def _(x): return x // @_(buttons[0].clicked.connect) // def spam(): ... // test_ok decorator_expression_eval_hack_py38 // # parse_options: { "target-version": "3.8" } // @eval("buttons[0].clicked.connect") // def spam(): ... // test_ok decorator_expression_py39 // # parse_options: { "target-version": "3.9" } // @buttons[0].clicked.connect // def spam(): ... // @(x := lambda x: x)(foo) // def bar(): ... // test_err decorator_expression_py38 // # parse_options: { "target-version": "3.8" } // @buttons[0].clicked.connect // def spam(): ... // test_err decorator_named_expression_py37 // # parse_options: { "target-version": "3.7" } // @(x := lambda x: x)(foo) // def bar(): ... // test_err decorator_dict_literal_py38 // # parse_options: { "target-version": "3.8" } // @{3: 3} // def bar(): ... // test_err decorator_float_literal_py38 // # parse_options: { "target-version": "3.8" } // @3.14 // def bar(): ... // test_ok decorator_await_expression_py39 // # parse_options: { "target-version": "3.9" } // async def foo(): // @await bar // def baz(): ... // test_err decorator_await_expression_py38 // # parse_options: { "target-version": "3.8" } // async def foo(): // @await bar // def baz(): ... // test_err decorator_non_toplevel_call_expression_py38 // # parse_options: { "target-version": "3.8" } // @foo().bar() // def baz(): ... let relaxed_decorator_error = match &parsed_expr.expr { Expr::Call(expr_call) => { helpers::detect_invalid_pre_py39_decorator_node(&expr_call.func) } expr => helpers::detect_invalid_pre_py39_decorator_node(expr), }; if let Some((error, range)) = relaxed_decorator_error { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::RelaxedDecorator(error), range, ); } } // test_err decorator_invalid_expression // @*x // @(*x) // @((*x)) // @yield x // @yield from x // def foo(): ... decorators.push(ast::Decorator { expression: parsed_expr.expr, range: self.node_range(decorator_start), node_index: AtomicNodeIndex::NONE, }); // test_err decorator_missing_newline // @x def foo(): ... // @x async def foo(): ... // @x class Foo: ... self.expect(TokenKind::Newline); } decorators.shrink_to_fit(); match self.current_token_kind() { TokenKind::Def => Stmt::FunctionDef(self.parse_function_definition(decorators, start)), TokenKind::Class => Stmt::ClassDef(self.parse_class_definition(decorators, start)), TokenKind::Async if self.peek() == TokenKind::Def => { self.bump(TokenKind::Async); // test_ok decorator_async_function // @decorator // async def foo(): ... Stmt::FunctionDef(ast::StmtFunctionDef { is_async: true, ..self.parse_function_definition(decorators, start) }) } _ => { // test_err decorator_unexpected_token // @foo // async with x: ... // @foo // x = 1 self.add_error( ParseErrorType::OtherError( "Expected class, function definition or async function definition \ after decorator" .to_string(), ), self.current_token_range(), ); let range = self.node_range(start); ast::StmtFunctionDef { node_index: AtomicNodeIndex::default(), range, is_async: false, decorator_list: decorators, name: ast::Identifier { id: Name::empty(), range: self.missing_node_range(), node_index: AtomicNodeIndex::NONE, }, type_params: None, parameters: Box::new(ast::Parameters { range: self.missing_node_range(), ..ast::Parameters::default() }), returns: None, body: Suite::new(), } .into() } } } /// Parses the body of the given [`Clause`]. /// /// This could either be a single statement that's on the same line as the /// clause header or an indented block. fn parse_body(&mut self, parent_clause: Clause) -> Suite { // Note: The test cases in this method chooses a clause at random to test // the error logic. let newline_range = self.current_token_range(); if self.eat(TokenKind::Newline) { if self.at(TokenKind::Indent) { return self.parse_block(); } // test_err clause_expect_indented_block // # Here, the error is highlighted at the `pass` token // if True: // pass // # The parser is at the end of the program, so let's highlight // # at the newline token after `:` // if True: self.add_error( ParseErrorType::OtherError(format!( "Expected an indented block after {parent_clause}" )), if self.current_token_range().is_empty() { newline_range } else { self.current_token_range() }, ); } else { if self.at_simple_stmt() { return self.parse_simple_statements(); } // test_err clause_expect_single_statement // if True: if True: pass self.add_error( ParseErrorType::OtherError("Expected a simple statement".to_string()), self.current_token_range(), ); } Suite::new() } /// Parses a block of statements. /// /// # Panics /// /// If the parser isn't positioned at an `Indent` token. fn parse_block(&mut self) -> Suite { self.bump(TokenKind::Indent); let statements = if let Some(statements) = self.with_recursion(|parser| { let snapshot = parser.stmt_scratch.snapshot(); parser.parse_list(RecoveryContextKind::BlockStatements, |parser| { let statement = parser.parse_statement(); parser.stmt_scratch.push(statement); }); parser.stmt_scratch.take_thin_vec(snapshot) }) { statements } else { self.report_recursion_limit_exceeded(self.current_token_range()); Suite::new() }; self.expect(TokenKind::Dedent); statements } /// Parses a single parameter for the given function kind. /// /// Matches either the `param_no_default_star_annotation` or `param_no_default` /// rule in the [Python grammar] depending on whether star annotation is allowed /// or not. /// /// Use [`Parser::parse_parameter_with_default`] to allow parameter with default /// values. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_parameter( &mut self, start: TextSize, function_kind: FunctionKind, allow_star_annotation: AllowStarAnnotation, ) -> ast::Parameter { let name = self.parse_identifier(); // Annotations are only allowed for function definition. For lambda expression, // the `:` token would indicate its body. let annotation = match function_kind { FunctionKind::FunctionDef if self.eat(TokenKind::Colon) => { if self.at_expr() { let parsed_expr = match allow_star_annotation { AllowStarAnnotation::Yes => { // test_ok param_with_star_annotation // def foo(*args: *int | str): ... // def foo(*args: *(int or str)): ... // test_err param_with_invalid_star_annotation // def foo(*args: *): ... // def foo(*args: (*tuple[int])): ... // def foo(*args: *int or str): ... // def foo(*args: *yield x): ... // # def foo(*args: **int): ... let parsed_expr = self.parse_conditional_expression_or_higher_impl( ExpressionContext::starred_bitwise_or(), ); // test_ok param_with_star_annotation_py311 // # parse_options: {"target-version": "3.11"} // def foo(*args: *Ts): ... // test_ok param_with_star_annotation_py310 // # parse_options: {"target-version": "3.10"} // # regression tests for https://github.com/astral-sh/ruff/issues/16874 // # starred parameters are fine, just not the annotation // from typing import Annotated, Literal // def foo(*args: Ts): ... // def foo(*x: Literal["this should allow arbitrary strings"]): ... // def foo(*x: Annotated[str, "this should allow arbitrary strings"]): ... // def foo(*args: str, **kwds: int): ... // def union(*x: A | B): ... // test_err param_with_star_annotation_py310 // # parse_options: {"target-version": "3.10"} // def foo(*args: *Ts): ... if parsed_expr.is_starred_expr() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::StarAnnotation, parsed_expr.range(), ); } parsed_expr } AllowStarAnnotation::No => { // test_ok param_with_annotation // def foo(arg: int): ... // def foo(arg: lambda x: x): ... // test_err param_with_invalid_annotation // def foo(arg: *int): ... // def foo(arg: yield int): ... // def foo(arg: x := int): ... self.parse_conditional_expression_or_higher() } }; Some(Box::new(parsed_expr.expr)) } else { // test_err param_missing_annotation // def foo(x:): ... // def foo(x:,): ... self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } _ => None, }; ast::Parameter { range: self.node_range(start), name, annotation, node_index: AtomicNodeIndex::NONE, } } /// Parses a parameter with an optional default expression. /// /// Matches the `param_maybe_default` rule in the [Python grammar]. /// /// This method doesn't allow star annotation. Use [`Parser::parse_parameter`] /// instead. /// /// [Python grammar]: https://docs.python.org/3/reference/grammar.html fn parse_parameter_with_default( &mut self, start: TextSize, function_kind: FunctionKind, ) -> ast::ParameterWithDefault { let parameter = self.parse_parameter(start, function_kind, AllowStarAnnotation::No); let default = if self.eat(TokenKind::Equal) { if self.at_expr() { // test_ok param_with_default // def foo(x=lambda y: y): ... // def foo(x=1 if True else 2): ... // def foo(x=await y): ... // def foo(x=(yield y)): ... // test_err param_with_invalid_default // def foo(x=*int): ... // def foo(x=(*int)): ... // def foo(x=yield y): ... Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } else { // test_err param_missing_default // def foo(x=): ... // def foo(x: int = ): ... self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; ast::ParameterWithDefault { range: self.node_range(start), parameter, default, node_index: AtomicNodeIndex::NONE, } } /// Parses a parameter list for the given function kind. /// /// See: pub(super) fn parse_parameters(&mut self, function_kind: FunctionKind) -> ast::Parameters { let start = self.node_start(); if matches!(function_kind, FunctionKind::FunctionDef) { self.expect(TokenKind::Lpar); } // TODO(dhruvmanila): This has the same problem as `parse_match_pattern_mapping` // has where if there are multiple kwarg or vararg, the last one will win and // the parser will drop the previous ones. Another thing is the vararg and kwarg // uses `Parameter` (not `ParameterWithDefault`) which means that the parser cannot // recover well from `*args=(1, 2)`. let mut parameters = ast::Parameters::default(); let parameters_snapshot = self.parameter_scratch.snapshot(); let mut args_snapshot = None; let mut kwonlyargs_snapshot = None; let mut seen_default_param = false; // `a=10` let mut seen_positional_only_separator = false; // `/` let mut seen_keyword_only_separator = false; // `*` let mut seen_keyword_only_param_after_separator = false; // Range of the keyword only separator if it's the last parameter in the list. let mut last_keyword_only_separator_range = None; self.parse_comma_separated_list(RecoveryContextKind::Parameters(function_kind), |parser| { let param_start = parser.node_start(); if parameters.kwarg.is_some() { // test_err params_follows_var_keyword_param // def foo(**kwargs, a, /, b=10, *, *args): ... parser.add_error( ParseErrorType::ParamAfterVarKeywordParam, parser.current_token_range(), ); } match parser.current_token_kind() { TokenKind::Star => { let star_range = parser.current_token_range(); parser.bump(TokenKind::Star); kwonlyargs_snapshot.get_or_insert_with(|| parser.parameter_scratch.snapshot()); if parser.at_name_or_soft_keyword() { let param = parser.parse_parameter( param_start, function_kind, AllowStarAnnotation::Yes, ); let param_star_range = parser.node_range(star_range.start()); if parser.at(TokenKind::Equal) { // test_err params_var_positional_with_default // def foo(a, *args=(1, 2)): ... parser.add_error( ParseErrorType::VarParameterWithDefault, parser.current_token_range(), ); } if seen_keyword_only_separator || parameters.vararg.is_some() { // test_err params_multiple_varargs // def foo(a, *, *args, b): ... // # def foo(a, *, b, c, *args): ... // def foo(a, *args1, *args2, b): ... // def foo(a, *args1, b, c, *args2): ... parser.add_error( ParseErrorType::OtherError( "Only one '*' parameter allowed".to_string(), ), param_star_range, ); } // TODO(dhruvmanila): The AST doesn't allow multiple `vararg`, so let's // choose to keep the first one so that the parameters remain in preorder. if parameters.vararg.is_none() { parameters.vararg = Some(Box::new(param)); } last_keyword_only_separator_range = None; } else { if seen_keyword_only_separator { // test_err params_multiple_star_separator // def foo(a, *, *, b): ... // def foo(a, *, b, c, *): ... parser.add_error( ParseErrorType::OtherError( "Only one '*' separator allowed".to_string(), ), star_range, ); } if parameters.vararg.is_some() { // test_err params_star_separator_after_star_param // def foo(a, *args, *, b): ... // def foo(a, *args, b, c, *): ... parser.add_error( ParseErrorType::OtherError( "Keyword-only parameter separator not allowed \ after '*' parameter" .to_string(), ), star_range, ); } seen_keyword_only_separator = true; last_keyword_only_separator_range = Some(star_range); } } TokenKind::DoubleStar => { let double_star_range = parser.current_token_range(); parser.bump(TokenKind::DoubleStar); let param = parser.parse_parameter(param_start, function_kind, AllowStarAnnotation::No); let param_double_star_range = parser.node_range(double_star_range.start()); if parameters.kwarg.is_some() { // test_err params_multiple_kwargs // def foo(a, **kwargs1, **kwargs2): ... parser.add_error( ParseErrorType::OtherError( "Only one '**' parameter allowed".to_string(), ), param_double_star_range, ); } if parser.at(TokenKind::Equal) { // test_err params_var_keyword_with_default // def foo(a, **kwargs={'b': 1, 'c': 2}): ... parser.add_error( ParseErrorType::VarParameterWithDefault, parser.current_token_range(), ); } if seen_keyword_only_separator && !seen_keyword_only_param_after_separator { // test_ok params_seen_keyword_only_param_after_star // def foo(*, a, **kwargs): ... // def foo(*, a=10, **kwargs): ... // test_err params_kwarg_after_star_separator // def foo(*, **kwargs): ... parser.add_error( ParseErrorType::ExpectedKeywordParam, param_double_star_range, ); } parameters.kwarg = Some(Box::new(param)); last_keyword_only_separator_range = None; } TokenKind::Slash => { let slash_range = parser.current_token_range(); parser.bump(TokenKind::Slash); if parser.parameter_scratch.is_empty(¶meters_snapshot) && parameters.vararg.is_none() && parameters.kwarg.is_none() { // test_err params_no_arg_before_slash // def foo(/): ... // def foo(/, a): ... parser.add_error( ParseErrorType::OtherError( "Position-only parameter separator not allowed as first parameter" .to_string(), ), slash_range, ); } if seen_positional_only_separator { // test_err params_multiple_slash_separator // def foo(a, /, /, b): ... // def foo(a, /, b, c, /): ... parser.add_error( ParseErrorType::OtherError( "Only one '/' separator allowed".to_string(), ), slash_range, ); } if seen_keyword_only_separator || parameters.vararg.is_some() { // test_err params_star_after_slash // def foo(*a, /): ... // def foo(a, *args, b, /): ... // def foo(a, *, /, b): ... // def foo(a, *, b, c, /, d): ... parser.add_error( ParseErrorType::OtherError( "'/' parameter must appear before '*' parameter".to_string(), ), slash_range, ); } if !seen_positional_only_separator { // We should only split if we're seeing the separator for the // first time, otherwise it's a user error. if kwonlyargs_snapshot.is_none() { args_snapshot = Some(parser.parameter_scratch.snapshot()); } seen_positional_only_separator = true; // test_ok pos_only_py38 // # parse_options: {"target-version": "3.8"} // def foo(a, /): ... // test_err pos_only_py37 // # parse_options: {"target-version": "3.7"} // def foo(a, /): ... // def foo(a, /, b, /): ... // def foo(a, *args, /, b): ... // def foo(a, //): ... parser.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::PositionalOnlyParameter, slash_range, ); } last_keyword_only_separator_range = None; } _ if parser.at_name_or_soft_keyword() => { let param = parser.parse_parameter_with_default(param_start, function_kind); // TODO(dhruvmanila): Pyright seems to only highlight the first non-default argument // https://github.com/microsoft/pyright/blob/3b70417dd549f6663b8f86a76f75d8dfd450f4a8/packages/pyright-internal/src/parser/parser.ts#L2038-L2042 if param.default.is_none() && seen_default_param && !seen_keyword_only_separator && parameters.vararg.is_none() { // test_ok params_non_default_after_star // def foo(a=10, *, b, c=11, d): ... // def foo(a=10, *args, b, c=11, d): ... // test_err params_non_default_after_default // def foo(a=10, b, c: int): ... parser.add_error(ParseErrorType::NonDefaultParamAfterDefaultParam, ¶m); } seen_default_param |= param.default.is_some(); if seen_keyword_only_separator { seen_keyword_only_param_after_separator = true; } parser.parameter_scratch.push(param); last_keyword_only_separator_range = None; } _ => { // This corresponds to the expected token kinds for `is_list_element`. unreachable!("Expected Name, '*', '**', or '/'"); } } }); if let Some(star_range) = last_keyword_only_separator_range { // test_err params_expected_after_star_separator // def foo(*): ... // def foo(*,): ... // def foo(a, *): ... // def foo(a, *,): ... // def foo(*, **kwargs): ... self.add_error(ParseErrorType::ExpectedKeywordParam, star_range); } if matches!(function_kind, FunctionKind::FunctionDef) { self.expect(TokenKind::Rpar); } if let Some(kwonlyargs_snapshot) = kwonlyargs_snapshot { parameters.kwonlyargs = self.parameter_scratch.take_thin_vec(kwonlyargs_snapshot); } if let Some(args_snapshot) = args_snapshot { parameters.args = self.parameter_scratch.take_thin_vec(args_snapshot); parameters.posonlyargs = self.parameter_scratch.take_thin_vec(parameters_snapshot); } else if seen_positional_only_separator { parameters.posonlyargs = self.parameter_scratch.take_thin_vec(parameters_snapshot); } else { parameters.args = self.parameter_scratch.take_thin_vec(parameters_snapshot); } parameters.range = self.node_range(start); parameters } /// Try to parse a type parameter list. If the parser is not at the start of a /// type parameter list, return `None`. /// /// See: fn try_parse_type_params(&mut self) -> Option { self.at(TokenKind::Lsqb).then(|| self.parse_type_params()) } /// Parses a type parameter list. /// /// # Panics /// /// If the parser isn't positioned at a `[` token. /// /// See: fn parse_type_params(&mut self) -> ast::TypeParams { let start = self.node_start(); self.bump(TokenKind::Lsqb); let type_params = self.parse_comma_separated_list_into_vec( RecoveryContextKind::TypeParams, Parser::parse_type_param, ); if type_params.is_empty() { // test_err type_params_empty // def foo[](): // pass // type ListOrSet[] = list | set self.add_error(ParseErrorType::EmptyTypeParams, self.current_token_range()); } self.expect(TokenKind::Rsqb); ast::TypeParams { range: self.node_range(start), type_params, node_index: AtomicNodeIndex::NONE, } } /// Parses a type parameter. /// /// See: fn parse_type_param(&mut self) -> ast::TypeParam { let start = self.node_start(); // TODO(dhruvmanila): CPython throws an error if `TypeVarTuple` or `ParamSpec` // has bounds: // // type X[*T: int] = int // ^^^^^ // SyntaxError: cannot use bound with TypeVarTuple // // We should do the same but currently we can't without throwing away the parsed // expression because the AST can't contain it. // test_ok type_param_type_var_tuple // type X[*Ts] = int // type X[*Ts = int] = int // type X[*Ts = *int] = int // type X[T, *Ts] = int // type X[T, *Ts = int] = int if self.eat(TokenKind::Star) { let name = self.parse_identifier(); let default = if self.eat(TokenKind::Equal) { if self.at_expr() { // test_err type_param_type_var_tuple_invalid_default_expr // type X[*Ts = *int] = int // type X[*Ts = *int or str] = int // type X[*Ts = yield x] = int // type X[*Ts = yield from x] = int // type X[*Ts = x := int] = int Some(Box::new( self.parse_conditional_expression_or_higher_impl( ExpressionContext::starred_bitwise_or(), ) .expr, )) } else { // test_err type_param_type_var_tuple_missing_default // type X[*Ts =] = int // type X[*Ts =, T2] = int self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; // test_err type_param_type_var_tuple_bound // type X[*T: int] = int ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { range: self.node_range(start), name, default, node_index: AtomicNodeIndex::NONE, }) // test_ok type_param_param_spec // type X[**P] = int // type X[**P = int] = int // type X[T, **P] = int // type X[T, **P = int] = int } else if self.eat(TokenKind::DoubleStar) { let name = self.parse_identifier(); let default = if self.eat(TokenKind::Equal) { if self.at_expr() { // test_err type_param_param_spec_invalid_default_expr // type X[**P = *int] = int // type X[**P = yield x] = int // type X[**P = yield from x] = int // type X[**P = x := int] = int // type X[**P = *int] = int Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } else { // test_err type_param_param_spec_missing_default // type X[**P =] = int // type X[**P =, T2] = int self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; // test_err type_param_param_spec_bound // type X[**T: int] = int ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { range: self.node_range(start), name, default, node_index: AtomicNodeIndex::NONE, }) // test_ok type_param_type_var // type X[T] = int // type X[T = int] = int // type X[T: int = int] = int // type X[T: (int, int) = int] = int // type X[T: int = int, U: (int, int) = int] = int } else { let name = self.parse_identifier(); let bound = if self.eat(TokenKind::Colon) { if self.at_expr() { // test_err type_param_invalid_bound_expr // type X[T: *int] = int // type X[T: yield x] = int // type X[T: yield from x] = int // type X[T: x := int] = int Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } else { // test_err type_param_missing_bound // type X[T: ] = int // type X[T1: , T2] = int self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; let equal_token_start = self.node_start(); let default = if self.eat(TokenKind::Equal) { if self.at_expr() { // test_err type_param_type_var_invalid_default_expr // type X[T = *int] = int // type X[T = yield x] = int // type X[T = (yield x)] = int // type X[T = yield from x] = int // type X[T = x := int] = int // type X[T: int = *int] = int Some(Box::new(self.parse_conditional_expression_or_higher().expr)) } else { // test_err type_param_type_var_missing_default // type X[T =] = int // type X[T: int =] = int // type X[T1 =, T2] = int self.add_error( ParseErrorType::ExpectedExpression, self.current_token_range(), ); None } } else { None }; // test_ok type_param_default_py313 // # parse_options: {"target-version": "3.13"} // type X[T = int] = int // def f[T = int](): ... // class C[T = int](): ... // test_err type_param_default_py312 // # parse_options: {"target-version": "3.12"} // type X[T = int] = int // def f[T = int](): ... // class C[T = int](): ... // class D[S, T = int, U = uint](): ... if default.is_some() { self.add_unsupported_syntax_error( UnsupportedSyntaxErrorKind::TypeParamDefault, self.node_range(equal_token_start), ); } ast::TypeParam::TypeVar(ast::TypeParamTypeVar { range: self.node_range(start), name, bound, default, node_index: AtomicNodeIndex::NONE, }) } } /// Validate that the given expression is a valid assignment target. /// /// If the expression is a list or tuple, then validate each element in the list. /// If it's a starred expression, then validate the value of the starred expression. /// /// Report an error for each invalid assignment expression found. pub(super) fn validate_assignment_target(&mut self, expr: &Expr) { match expr { Expr::Starred(ast::ExprStarred { value, .. }) => self.validate_assignment_target(value), Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) => { for expr in elts { self.validate_assignment_target(expr); } } Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) => {} _ => self.add_error(ParseErrorType::InvalidAssignmentTarget, expr.range()), } } /// Validate that the given expression is a valid annotated assignment target. /// /// Unlike [`Parser::validate_assignment_target`], starred, list and tuple /// expressions aren't allowed here. fn validate_annotated_assignment_target(&mut self, expr: &Expr) { match expr { Expr::List(_) => self.add_error( ParseErrorType::OtherError( "Only single target (not list) can be annotated".to_string(), ), expr, ), Expr::Tuple(_) => self.add_error( ParseErrorType::OtherError( "Only single target (not tuple) can be annotated".to_string(), ), expr, ), Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) => {} _ => self.add_error(ParseErrorType::InvalidAnnotatedAssignmentTarget, expr), } } /// Validate that the given expression is a valid delete target. /// /// If the expression is a list or tuple, then validate each element in the list. /// /// See: fn validate_delete_target(&mut self, expr: &Expr) { match expr { Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) => { for expr in elts { self.validate_delete_target(expr); } } Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) => {} _ => self.add_error(ParseErrorType::InvalidDeleteTarget, expr), } } /// Classify the `match` soft keyword token. /// /// # Panics /// /// If the parser isn't positioned at a `match` token. fn classify_match_token(&mut self) -> MatchTokenKind { assert_eq!(self.current_token_kind(), TokenKind::Match); let (first, second) = self.peek2(); match first { // test_ok match_classify_as_identifier_1 // match not in case TokenKind::Not if second == TokenKind::In => MatchTokenKind::Identifier, // test_ok match_classify_as_keyword_1 // match foo: // case _: ... // match 1: // case _: ... // match 1.0: // case _: ... // match 1j: // case _: ... // match "foo": // case _: ... // match f"foo {x}": // case _: ... // match {1, 2}: // case _: ... // match ~foo: // case _: ... // match ...: // case _: ... // match not foo: // case _: ... // match await foo(): // case _: ... // match lambda foo: foo: // case _: ... // test_err match_classify_as_keyword // match yield foo: // case _: ... TokenKind::Name | TokenKind::Int | TokenKind::Float | TokenKind::Complex | TokenKind::String | TokenKind::FStringStart | TokenKind::TStringStart | TokenKind::Lbrace | TokenKind::Tilde | TokenKind::Ellipsis | TokenKind::Not | TokenKind::Await | TokenKind::Yield | TokenKind::Lambda => MatchTokenKind::Keyword, // test_ok match_classify_as_keyword_or_identifier // match (1, 2) # Identifier // match (1, 2): # Keyword // case _: ... // match [1:] # Identifier // match [1, 2]: # Keyword // case _: ... // match * foo # Identifier // match - foo # Identifier // match -foo: # Keyword // case _: ... // test_err match_classify_as_keyword_or_identifier // match *foo: # Keyword // case _: ... TokenKind::Lpar | TokenKind::Lsqb | TokenKind::Star | TokenKind::Plus | TokenKind::Minus => MatchTokenKind::KeywordOrIdentifier, _ => { if first.is_soft_keyword() || first.is_singleton() { // test_ok match_classify_as_keyword_2 // match match: // case _: ... // match case: // case _: ... // match type: // case _: ... // match None: // case _: ... // match True: // case _: ... // match False: // case _: ... MatchTokenKind::Keyword } else { // test_ok match_classify_as_identifier_2 // match // match != foo // (foo, match) // [foo, match] // {foo, match} // match; // match: int // match, // match.foo // match / foo // match << foo // match and foo // match is not foo MatchTokenKind::Identifier } } } } /// Parses a sequence of clauses. /// /// The parser only continues for as long as it sees the token indicating the start of the /// specific clause. Unlike [`Parser::parse_list`], this method does not perform error recovery /// when the next token is not a list terminator or the start of a list element. /// /// The special method is necessary because Python uses indentation over explicit delimiters to /// indicate the end of a clause. /// /// ```python /// if True: ... /// elif False: ... /// elf x: .... /// else: ... /// ``` /// /// It would be nice if the above example would recover and either skip over the `elf x: ...` /// or parse it as a nested statement so that the parser recognises the `else` clause. But /// Python makes this hard (without writing custom error recovery logic) because `elf x: ` /// could also be an annotated assignment that went wrong ;) /// /// For now, don't recover when parsing clause headers, but add the terminator tokens (e.g. /// `Else`) to the recovery context so that expression recovery stops when it encounters an /// `else` token. fn parse_clauses(&mut self, clause: Clause, mut parse_clause: impl FnMut(&mut Parser<'src>)) { let mut progress = ParserProgress::default(); let recovery_kind = match clause { Clause::ElIf => RecoveryContextKind::Elif, Clause::Except => RecoveryContextKind::Except, _ => unreachable!("Clause is not supported"), }; let saved_context = self.recovery_context; self.recovery_context = self .recovery_context .union(RecoveryContext::from_kind(recovery_kind)); while recovery_kind.is_list_element(self) { progress.assert_progressing(self); parse_clause(self); } self.recovery_context = saved_context; } } #[derive(Copy, Clone)] enum Clause { If, Else, ElIf, For, With, Class, While, FunctionDef, Case, Try, Except, Finally, } impl Display for Clause { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Clause::If => write!(f, "`if` statement"), Clause::Else => write!(f, "`else` clause"), Clause::ElIf => write!(f, "`elif` clause"), Clause::For => write!(f, "`for` statement"), Clause::With => write!(f, "`with` statement"), Clause::Class => write!(f, "`class` definition"), Clause::While => write!(f, "`while` statement"), Clause::FunctionDef => write!(f, "function definition"), Clause::Case => write!(f, "`case` block"), Clause::Try => write!(f, "`try` statement"), Clause::Except => write!(f, "`except` clause"), Clause::Finally => write!(f, "`finally` clause"), } } } /// The classification of the `match` token. /// /// The `match` token is a soft keyword which means, depending on the context, it can be used as a /// keyword or an identifier. #[derive(Debug, Clone, Copy)] enum MatchTokenKind { /// The `match` token is used as a keyword. /// /// For example: /// ```python /// match foo: /// case _: /// pass /// ``` Keyword, /// The `match` token is used as an identifier. /// /// For example: /// ```python /// match.values() /// match is None /// ```` Identifier, /// The `match` token is used as either a keyword or an identifier. /// /// For example: /// ```python /// # Used as a keyword /// match [x, y]: /// case [1, 2]: /// pass /// /// # Used as an identifier /// match[x] /// ``` KeywordOrIdentifier, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum WithItemParsingState { /// Parsing the with items without any ambiguity. Regular, /// Parsing the with items in a speculative mode. Speculative, } #[derive(Debug)] struct ParsedWithItem { /// The contained with item. item: WithItem, /// If the context expression of the item is parenthesized. is_parenthesized: bool, } #[derive(Debug, Copy, Clone)] enum ElifOrElse { Elif, Else, } impl ElifOrElse { const fn is_elif(self) -> bool { matches!(self, ElifOrElse::Elif) } const fn as_token_kind(self) -> TokenKind { match self { ElifOrElse::Elif => TokenKind::Elif, ElifOrElse::Else => TokenKind::Else, } } const fn as_clause(self) -> Clause { match self { ElifOrElse::Elif => Clause::ElIf, ElifOrElse::Else => Clause::Else, } } } /// The kind of the except clause. #[derive(Debug, Copy, Clone)] enum ExceptClauseKind { /// A normal except clause e.g., `except Exception as e: ...`. Normal, /// An except clause with a star e.g., `except *: ...`. /// /// Contains the star's [`TextRange`] for error reporting. Star(TextRange), } impl ExceptClauseKind { const fn is_star(self) -> bool { matches!(self, ExceptClauseKind::Star(..)) } } #[derive(Debug, Copy, Clone)] enum AllowStarAnnotation { Yes, No, } #[derive(Debug, Copy, Clone)] enum ImportStyle { /// E.g., `import foo, bar` Import, /// E.g., `from foo import bar, baz` ImportFrom, } ast_serialize-0.13.1/crates/ruff_python_parser/src/parser/tests.rs000064400000000000000000000413001046102023000223350ustar00use ruff_python_ast::{Expr, InterpolatedStringElement, IpyEscapeKind, Number, Stmt}; use crate::{Mode, ParseErrorType, ParseOptions, parse, parse_expression, parse_module}; #[test] fn test_modes() { let source = "a[0][1][2][3][4]"; assert!(parse(source, ParseOptions::from(Mode::Expression)).is_ok()); assert!(parse(source, ParseOptions::from(Mode::Module)).is_ok()); } #[test] fn test_expr_mode_invalid_syntax1() { let source = "first second"; let error = parse_expression(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_expr_mode_invalid_syntax2() { let source = r"first second "; let error = parse_expression(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_expr_mode_invalid_syntax3() { let source = r"first second third "; let error = parse_expression(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_expr_mode_valid_syntax() { let source = "first "; let parsed = parse_expression(source).unwrap(); insta::assert_debug_snapshot!(parsed.expr()); } #[test] fn test_unicode_aliases() { // https://github.com/RustPython/RustPython/issues/4566 let source = r#"x = "\N{BACKSPACE}another cool trick""#; let suite = parse_module(source).unwrap().into_suite(); insta::assert_debug_snapshot!(suite); } #[test] fn nfkc_normalizes_names() { let parsed = parse_expression("𝒞").unwrap(); let Expr::Name(name) = parsed.expr() else { panic!("expected name expression, got {:?}", parsed.expr()); }; assert_eq!(name.id.as_str(), "C"); } #[test] fn nfkc_normalizes_dotted_names() { let suite = parse_module("import 𝒞.𝒟").unwrap().into_suite(); let [Stmt::Import(import)] = suite.as_slice() else { panic!("expected a single import statement, got {suite:?}"); }; let [alias] = import.names.as_slice() else { panic!("expected a single import alias, got {:?}", import.names); }; assert_eq!(alias.name.id.as_str(), "C.D"); } #[test] fn number_values() { let cases = [ ("1E400", Number::Float(f64::INFINITY)), ( "1E400J", Number::Complex { real: 0.0, imag: f64::INFINITY, }, ), ( "123_456_789_123_456_789_123_456_789_123_456_789", Number::Int("123456789123456789123456789123456789".parse().unwrap()), ), ( "000_123_456_789_123_456_789_123_456_789_123_456_789J", Number::Complex { real: 0.0, imag: 1.234_567_891_234_567_8e35, }, ), ]; for (source, expected) in cases { let parsed = parse_expression(source).unwrap(); let Expr::NumberLiteral(number) = parsed.expr() else { panic!( "expected number expression for {source:?}, got {:?}", parsed.expr() ); }; assert_eq!(number.value, expected, "source: {source:?}"); } } #[test] fn malformed_radix_literals() { for source in ["0x", "0o", "0b", "0x_", "0x__1"] { assert!(parse_expression(source).is_err(), "source: {source:?}"); } } #[test] fn interpolated_string_escaped_brace_values() { let cases = [ (r"f'\{{1}}'", r"\{1}"), (r"f'\}}'", r"\}"), (r"f'\\{{1}}'", r"\{1}"), (r"f'\\\{{1}}'", r"\\{1}"), (r"t'\{{1}}'", r"\{1}"), (r"t'\}}'", r"\}"), (r"t'\\{{1}}'", r"\{1}"), (r"t'\\\{{1}}'", r"\\{1}"), (r"rf'\{{1}}'", r"\{1}"), (r"rt'\{{1}}'", r"\{1}"), ]; for (source, expected) in cases { let parsed = parse_expression(source).unwrap(); let elements = match parsed.expr() { Expr::FString(string) => &string.as_single_part_fstring().unwrap().elements, Expr::TString(string) => &string.as_single_part_tstring().unwrap().elements, expression => panic!("expected interpolated string for {source:?}, got {expression:?}"), }; let [InterpolatedStringElement::Literal(literal)] = &**elements else { panic!("expected one literal element for {source:?}"); }; assert_eq!(&*literal.value, expected, "source: {source:?}"); } } #[test] fn ipython_escape_command_values() { let cases = [ ("?foo?", IpyEscapeKind::Help, "foo"), ("?? foo?", IpyEscapeKind::Help, "foo"), ("?? foo ?", IpyEscapeKind::Help2, " foo ?"), ("?foo??", IpyEscapeKind::Help2, "foo"), ("%foo?", IpyEscapeKind::Help, "%foo"), ("%foo??", IpyEscapeKind::Help2, "%foo"), ("%%foo???", IpyEscapeKind::Magic2, "foo???"), ("!pwd?", IpyEscapeKind::Shell, "pwd?"), ("?? \\\n foo?", IpyEscapeKind::Help, "foo"), ("?? \\\r foo?", IpyEscapeKind::Help, "foo"), ("?? \\\r\n foo?", IpyEscapeKind::Help, "foo"), ]; for (source, expected_kind, expected_value) in cases { let suite = parse(source, ParseOptions::from(Mode::Ipython)) .unwrap() .try_into_module() .unwrap() .into_suite(); let [Stmt::IpyEscapeCommand(command)] = suite.as_slice() else { panic!("expected one IPython escape command for {source:?}, got {suite:?}"); }; assert_eq!(command.kind, expected_kind, "source: {source:?}"); assert_eq!(&*command.value, expected_value, "source: {source:?}"); } } #[test] fn ipython_escape_command_expression_values() { let cases = [ ("x = !!foo", IpyEscapeKind::Shell, "!foo"), ("x = %%foo", IpyEscapeKind::Magic, "%foo"), ]; for (source, expected_kind, expected_value) in cases { let suite = parse(source, ParseOptions::from(Mode::Ipython)) .unwrap() .try_into_module() .unwrap() .into_suite(); let [Stmt::Assign(assign)] = suite.as_slice() else { panic!("expected one assignment for {source:?}, got {suite:?}"); }; let Expr::IpyEscapeCommand(command) = assign.value.as_ref() else { panic!( "expected an IPython escape command for {source:?}, got {:?}", assign.value ); }; assert_eq!(command.kind, expected_kind, "source: {source:?}"); assert_eq!(&*command.value, expected_value, "source: {source:?}"); } } #[test] fn test_ipython_escape_commands() { let parsed = parse( r" # Normal Python code ( a % b ) # Dynamic object info ??a.foo ?a.foo ?a.foo? ??a.foo()?? # Line magic %timeit a = b %timeit foo(b) % 3 %alias showPath pwd && ls -a %timeit a =\ foo(b); b = 2 %matplotlib --inline %matplotlib \ --inline # System shell access !pwd && ls -a | sed 's/^/\ /' !pwd \ && ls -a | sed 's/^/\\ /' !!cd /Users/foo/Library/Application\ Support/ # Let's add some Python code to make sure that earlier escapes were handled # correctly and that we didn't consume any of the following code as a result # of the escapes. def foo(): return ( a != b ) # Transforms into `foo(..)` /foo 1 2 ;foo 1 2 ,foo 1 2 # Indented escape commands for a in range(5): !ls p1 = !pwd p2: str = !pwd foo = %foo \ bar bar = %foo? baz = !pwd? % 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(), ParseOptions::from(Mode::Ipython), ) .unwrap(); insta::assert_debug_snapshot!(parsed.syntax()); } #[test] fn test_fstring_expr_inner_line_continuation_and_t_string() { let source = r#"f'{\t"i}'"#; let parsed = parse_expression(source); let error = parsed.unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_fstring_expr_inner_line_continuation_newline_t_string() { let source = r#"f'{\ t"i}'"#; let parsed = parse_expression(source); let error = parsed.unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_tstring_fstring_middle() { let source = "t'{:{F'{\0}F"; let parsed = parse_expression(source); let error = parsed.unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_tstring_fstring_middle_fuzzer() { let source = "A1[A\u{c}\0:+,>1t'{:f\0:{f\"f\0:\0{fm\0:{f:\u{10}\0\0\0:bb\0{@f>f\u{1}'\0f"; let parsed = parse_expression(source); let error = parsed.unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn recursion_limit_nested_parens() { let src = format!("{}1{}", "(".repeat(1_000), ")".repeat(1_000)); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_normal_python_unaffected() { // 50 levels is well above what real-world Python ever produces and well // below the default cap — the point is to confirm the default doesn't // reject ordinary input. let src = format!("x = {}1{}", "(".repeat(50), ")".repeat(50)); parse_module(&src).unwrap(); } #[test] fn recursion_limit_preserves_prior_statements() { // Recursion-limit recovery is limited for now: we drain the rest of the file but keep the // statements parsed before the overflowing statement. // TODO: Recover at the next newline so the trailing statement is preserved too. let src = format!( "before = 1\n{}1{}\nafter = 2\n", "(".repeat(1_000), ")".repeat(1_000), ); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let parsed = crate::parse_unchecked(&src, opts) .try_into_module() .unwrap(); assert!(matches!( parsed.errors().first().map(|error| &error.error), Some(ParseErrorType::RecursionLimitExceeded) )); assert!(matches!(parsed.suite().first(), Some(Stmt::Assign(_)))); } #[test] fn recursion_limit_nested_def_blocks() { // Nested function definitions exercise instrumentation on // `parse_statement` rather than `parse_lhs_expression`. Each level // needs one more leading tab to make indentation valid. let depth = 400; let mut src = String::new(); for i in 0..depth { src.push_str(&"\t".repeat(i)); src.push_str("def f():\n"); } src.push_str(&"\t".repeat(depth)); src.push_str("pass\n"); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_nested_lists() { let src = format!("{}1{}", "[".repeat(1_000), "]".repeat(1_000)); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_nested_calls() { let src = format!("x = {}1{}", "f(".repeat(1_000), ")".repeat(1_000)); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_nested_subscripts() { let src = format!("x = {}1{}", "a[".repeat(1_000), "]".repeat(1_000)); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_nested_match_patterns() { // Deeply parenthesised match patterns — exercises pattern-parsing // instrumentation in addition to statement / expression paths. let mut src = String::from("match x:\n case "); for _ in 0..600 { src.push('('); } src.push('y'); for _ in 0..600 { src.push(')'); } src.push_str(": pass\n"); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_binary_paren_interplay() { // `1+(1+(1+(1+...)))` — each level alternates a binary operator and a // parenthesised sub-expression, exactly like the pattern described in // the tracking issue. let depth = 2_000; let mut src = String::new(); for _ in 0..depth { src.push_str("1+("); } src.push('1'); for _ in 0..depth { src.push(')'); } let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn recursion_limit_first_error_is_recursion_not_noise() { // When the limit is hit the outer parser frames will emit secondary // errors as they unwind. Callers read the first error via `into_result` // / `Parsed::errors()`, so `RecursionLimitExceeded` must come first, and // the drain-to-EOF after reporting the recursion limit should keep the total count // small rather than producing one noisy error per unwound frame. let src = format!("{}1{}", "(".repeat(2_000), ")".repeat(2_000)); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(50); let parsed = crate::parse_unchecked(&src, opts); let errors = parsed.errors(); let first = errors.first().expect("expected at least one error"); assert!(matches!( first.error, ParseErrorType::RecursionLimitExceeded )); // Exactly one `RecursionLimitExceeded` — guards against a regression // where the unwind loops and re-triggers the limit check. let recursion_errors = errors .iter() .filter(|e| matches!(e.error, ParseErrorType::RecursionLimitExceeded)) .count(); assert_eq!(recursion_errors, 1); // Small, bounded tail of follow-up errors from the unwinding frames. // Today this is 0; the generous cap is a regression gate, not a spec. assert!( errors.len() <= 8, "expected a small number of errors, got {}: {errors:?}", errors.len(), ); } #[test] fn recursion_limit_default_set() { let opts = ParseOptions::from(Mode::Module); // Guards against someone accidentally unsetting the default. Real-world // Python never approaches this depth, and the value must stay within the // threading stack's capacity — see the const's docs in `options.rs`. assert!(opts.max_recursion_depth() >= 200); assert!(opts.max_recursion_depth() <= 2000); } #[test] fn recursion_limit_right_assoc_pow_chain() { // `1**1**1**...**1` — `**` is right-associative, so the right operand // is parsed by a recursive `parse_binary_expression_or_higher` call // *without* any intervening parentheses or atom nesting. This exercises // the binary-expression recursion path directly, unlike the // `1+(1+(...))` interplay test which recurses through parenthesised // atoms. let depth = 2_000; let mut src = String::with_capacity(depth * 3 + 1); for _ in 0..depth { src.push_str("1**"); } src.push('1'); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!( matches!(err.error, ParseErrorType::RecursionLimitExceeded), "expected RecursionLimitExceeded, got {:?}", err.error ); } #[test] fn recursion_limit_ternary_else_chain() { // `1 if 1 else 1 if 1 else ...` — the `else` operand recurses at the // conditional layer (`parse_if_expression` -> `orelse`), which is not // covered by the `parse_lhs_expression` guard. let depth = 2_000; let mut src = String::with_capacity(depth * 12 + 1); for _ in 0..depth { src.push_str("1 if 1 else "); } src.push('1'); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!( matches!(err.error, ParseErrorType::RecursionLimitExceeded), "expected RecursionLimitExceeded, got {:?}", err.error ); } #[test] fn recursion_limit_nested_lambda_chain() { // `lambda: lambda: lambda: ...` — the lambda body recurses at the // conditional layer (`parse_lambda_expr` -> body), bypassing the // `parse_lhs_expression` guard entirely. let depth = 2_000; let mut src = String::from("x = "); for _ in 0..depth { src.push_str("lambda: "); } src.push('1'); let opts = ParseOptions::from(Mode::Module).with_max_recursion_depth(100); let err = parse(&src, opts).unwrap_err(); assert!( matches!(err.error, ParseErrorType::RecursionLimitExceeded), "expected RecursionLimitExceeded, got {:?}", err.error ); } ast_serialize-0.13.1/crates/ruff_python_parser/src/semantic_errors.rs000064400000000000000000003004521046102023000231040ustar00//! [`SemanticSyntaxChecker`] for AST-based syntax errors. //! //! This checker is not responsible for traversing the AST itself. Instead, its //! [`SemanticSyntaxChecker::visit_stmt`] and [`SemanticSyntaxChecker::visit_expr`] methods should //! be called in a parent `Visitor`'s `visit_stmt` and `visit_expr` methods, respectively. use ruff_python_ast::{ self as ast, Expr, ExprContext, IrrefutablePatternKind, Pattern, PythonVersion, Stmt, StmtExpr, StmtFunctionDef, StmtImportFrom, comparable::HashableExpr, helpers, visitor::{Visitor, walk_expr, walk_stmt}, }; use ruff_text_size::{Ranged, TextRange, TextSize}; use rustc_hash::{FxBuildHasher, FxHashSet}; use std::fmt::Display; #[derive(Debug, Default)] pub struct SemanticSyntaxChecker { /// The checker has traversed past the `__future__` import boundary. /// /// For example, the checker could be visiting `x` in: /// /// ```python /// from __future__ import annotations /// /// import os /// /// x: int = 1 /// ``` /// /// Python considers it a syntax error to import from `__future__` after any other /// non-`__future__`-importing statements. seen_futures_boundary: bool, /// The checker has traversed past the module docstring boundary (i.e. seen any statement in the /// module). seen_module_docstring_boundary: bool, } impl SemanticSyntaxChecker { pub fn new() -> Self { Self::default() } } impl SemanticSyntaxChecker { fn add_error( context: &Ctx, kind: SemanticSyntaxErrorKind, range: TextRange, ) { context.report_semantic_error(SemanticSyntaxError { kind, range, python_version: context.python_version(), }); } fn check_lazy_import_context( ctx: &Ctx, range: TextRange, kind: LazyImportKind, ) -> bool { if let Some(context) = ctx.lazy_import_context() { Self::add_error( ctx, SemanticSyntaxErrorKind::LazyImportNotAllowed { context, kind }, range, ); return true; } false } fn check_stmt(&mut self, stmt: &ast::Stmt, ctx: &Ctx) { match stmt { Stmt::ImportFrom(StmtImportFrom { range, module, level, names, is_lazy, .. }) => { let mut handled_lazy_error = false; if *is_lazy { // test_ok lazy_import_semantic_ok_py315 // # parse_options: {"target-version": "3.15"} // import contextlib // with contextlib.nullcontext(): // lazy import os // with contextlib.nullcontext(): // lazy from sys import path // test_err lazy_import_invalid_context_py315 // # parse_options: {"target-version": "3.15"} // try: // lazy import os // except: // pass // // try: // x // except* Exception: // lazy import sys // // def func(): // lazy import math // // async def async_func(): // lazy from json import loads // // class MyClass: // lazy import typing // // def outer(): // class Inner: // lazy import json if Self::check_lazy_import_context(ctx, *range, LazyImportKind::ImportFrom) { handled_lazy_error = true; } else if names.iter().any(|alias| alias.name.as_str() == "*") { // test_err lazy_import_invalid_from_py315 // # parse_options: {"target-version": "3.15"} // lazy from os import * // lazy from __future__ import annotations // // def func(): // lazy from sys import * Self::add_error(ctx, SemanticSyntaxErrorKind::LazyImportStar, *range); handled_lazy_error = true; } else if matches!(module.as_deref(), Some("__future__")) { Self::add_error(ctx, SemanticSyntaxErrorKind::LazyFutureImport, *range); handled_lazy_error = true; } } if handled_lazy_error { // Skip the regular `from`-import validations after reporting the lazy-specific // syntax error with the highest precedence. } else if matches!(module.as_deref(), Some("__future__")) { for name in names { if !is_known_future_feature(&name.name) { // test_ok valid_future_feature // from __future__ import annotations // test_err invalid_future_feature // from __future__ import invalid_feature // from __future__ import annotations, invalid_feature // from __future__ import invalid_feature_1, invalid_feature_2 Self::add_error( ctx, SemanticSyntaxErrorKind::FutureFeatureNotDefined( name.name.to_string(), ), name.range, ); } } if self.seen_futures_boundary { Self::add_error(ctx, SemanticSyntaxErrorKind::LateFutureImport, *range); } } for alias in names { if alias.name.as_str() == "*" && !ctx.in_module_scope() { // test_err import_from_star // def f1(): // from module import * // class C: // from module import * // def f2(): // from ..module import * // def f3(): // from module import *, * // test_ok import_from_star // from module import * Self::add_error( ctx, SemanticSyntaxErrorKind::NonModuleImportStar( helpers::format_import_from(*level, module.as_deref()).to_string(), ), *range, ); break; } } } Stmt::Import(ast::StmtImport { range, is_lazy: true, .. }) => { Self::check_lazy_import_context(ctx, *range, LazyImportKind::Import); } Stmt::Match(match_stmt) => { Self::irrefutable_match_case(match_stmt, ctx); for case in &match_stmt.cases { let mut visitor = MatchPatternVisitor { names: FxHashSet::default(), ctx, }; visitor.visit_pattern(&case.pattern); } } Stmt::FunctionDef(ast::StmtFunctionDef { type_params, parameters, .. }) => { if let Some(type_params) = type_params { Self::duplicate_type_parameter_name(type_params, ctx); Self::type_parameter_default_order(type_params, ctx); } Self::duplicate_parameter_name(parameters, ctx); } Stmt::Global(ast::StmtGlobal { names, .. }) => { for name in names { if ctx.is_bound_parameter(name) { Self::add_error( ctx, SemanticSyntaxErrorKind::GlobalParameter(name.to_string()), name.range, ); } } } Stmt::ClassDef(ast::StmtClassDef { type_params: Some(type_params), .. }) | Stmt::TypeAlias(ast::StmtTypeAlias { type_params: Some(type_params), .. }) => { Self::duplicate_type_parameter_name(type_params, ctx); Self::type_parameter_default_order(type_params, ctx); } Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { if let [Expr::Starred(ast::ExprStarred { range, .. })] = targets.as_slice() { // test_ok single_starred_assignment_target // (*a,) = (1,) // *a, = (1,) // [*a] = (1,) // test_err single_starred_assignment_target // *a = (1,) Self::add_error( ctx, SemanticSyntaxErrorKind::SingleStarredAssignment, *range, ); } // test_ok assign_stmt_starred_expr_value // _ = 4 // _ = [4] // _ = (*[1],) // _ = *[1], // test_err assign_stmt_starred_expr_value // _ = *[42] // _ = *{42} // _ = *list() // _ = *(p + q) Self::invalid_star_expression(value, ctx); } Stmt::Return(ast::StmtReturn { value, range, node_index: _, }) => { if let Some(value) = value { // test_err single_star_return // def f(): return *x Self::invalid_star_expression(value, ctx); } if !ctx.in_function_scope() { Self::add_error(ctx, SemanticSyntaxErrorKind::ReturnOutsideFunction, *range); } } Stmt::For(ast::StmtFor { target, iter, is_async, .. }) => { // test_err single_star_for // for _ in *x: ... // for *x in xs: ... Self::invalid_star_expression(target, ctx); Self::invalid_star_expression(iter, ctx); if *is_async { Self::await_outside_async_function( ctx, stmt, AwaitOutsideAsyncFunctionKind::AsyncFor, ); } } Stmt::With(ast::StmtWith { is_async: true, .. }) => { Self::await_outside_async_function( ctx, stmt, AwaitOutsideAsyncFunctionKind::AsyncWith, ); } Stmt::Nonlocal(ast::StmtNonlocal { names, range, .. }) => { // test_ok nonlocal_declaration_at_module_level // def _(): // nonlocal x // test_err nonlocal_declaration_at_module_level // nonlocal x // nonlocal x, y if ctx.in_module_scope() { Self::add_error( ctx, SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel, *range, ); } if !ctx.in_module_scope() { for name in names { if !ctx.has_nonlocal_binding(name) { Self::add_error( ctx, SemanticSyntaxErrorKind::NonlocalWithoutBinding(name.to_string()), name.range, ); } } } } Stmt::Break(ast::StmtBreak { range, .. }) if !ctx.in_loop_context() => { Self::add_error(ctx, SemanticSyntaxErrorKind::BreakOutsideLoop, *range); } Stmt::Continue(ast::StmtContinue { range, .. }) if !ctx.in_loop_context() => { Self::add_error(ctx, SemanticSyntaxErrorKind::ContinueOutsideLoop, *range); } _ => {} } Self::debug_shadowing(stmt, ctx); Self::check_annotation(stmt, ctx); } fn check_annotation(stmt: &ast::Stmt, ctx: &Ctx) { match stmt { Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, .. }) => { if ctx.python_version() > PythonVersion::PY313 { // test_ok valid_annotation_py313 // # parse_options: {"target-version": "3.13"} // a: (x := 1) // def outer(): // b: (yield 1) // c: (yield from 1) // async def outer(): // d: (await 1) // test_err invalid_annotation_py314 // # parse_options: {"target-version": "3.14"} // a: (x := 1) // def outer(): // b: (yield 1) // c: (yield from 1) // async def outer(): // d: (await 1) let mut visitor = InvalidExpressionVisitor { position: InvalidExpressionPosition::TypeAnnotation, ctx, }; visitor.visit_expr(annotation); } if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { if let Some(global_stmt) = ctx.global(id.as_str()) { let global_start = global_stmt.start(); if !ctx.in_module_scope() || target.start() < global_start { Self::add_error( ctx, SemanticSyntaxErrorKind::AnnotatedGlobal(id.to_string()), target.range(), ); } } } } Stmt::FunctionDef(ast::StmtFunctionDef { type_params, parameters, returns, .. }) => { // test_ok valid_annotation_function_py313 // # parse_options: {"target-version": "3.13"} // def f() -> (y := 3): ... // def g(arg: (x := 1)): ... // def outer(): // def i(x: (yield 1)): ... // def k() -> (yield 1): ... // def m(x: (yield from 1)): ... // def o() -> (yield from 1): ... // async def outer(): // def f() -> (await 1): ... // def g(arg: (await 1)): ... // test_err invalid_annotation_function_py314 // # parse_options: {"target-version": "3.14"} // def f() -> (y := 3): ... // def g(arg: (x := 1)): ... // def outer(): // def i(x: (yield 1)): ... // def k() -> (yield 1): ... // def m(x: (yield from 1)): ... // def o() -> (yield from 1): ... // async def outer(): // def f() -> (await 1): ... // def g(arg: (await 1)): ... // test_err invalid_annotation_function // def d[T]() -> (await 1): ... // def e[T](arg: (await 1)): ... // def f[T]() -> (y := 3): ... // def g[T](arg: (x := 1)): ... // def h[T](x: (yield 1)): ... // def j[T]() -> (yield 1): ... // def l[T](x: (yield from 1)): ... // def n[T]() -> (yield from 1): ... // def p[T: (yield 1)](): ... # yield in TypeVar bound // def q[T = (yield 1)](): ... # yield in TypeVar default // def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default // def s[**Ts = (yield 1)](): ... # yield in ParamSpec default // def t[T: (x := 1)](): ... # named expr in TypeVar bound // def u[T = (x := 1)](): ... # named expr in TypeVar default // def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default // def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default // def t[T: (await 1)](): ... # await in TypeVar bound // def u[T = (await 1)](): ... # await in TypeVar default // def v[*Ts = (await 1)](): ... # await in TypeVarTuple default // def w[**Ts = (await 1)](): ... # await in ParamSpec default let mut visitor = InvalidExpressionVisitor { position: InvalidExpressionPosition::TypeAnnotation, ctx, }; if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } // the __future__ annotation error takes precedence over the generic error if ctx.future_annotations_or_stub() || ctx.python_version() > PythonVersion::PY313 { visitor.position = InvalidExpressionPosition::TypeAnnotation; } else if type_params.is_some() { visitor.position = InvalidExpressionPosition::GenericDefinition; } else { return; } for param in parameters .iter() .filter_map(ast::AnyParameterRef::annotation) { visitor.visit_expr(param); } if let Some(returns) = returns { visitor.visit_expr(returns); } } Stmt::ClassDef(ast::StmtClassDef { type_params: Some(type_params), arguments, .. }) => { // test_ok valid_annotation_class // class F(y := list): ... // def f(): // class G((yield 1)): ... // class H((yield from 1)): ... // async def f(): // class G((await 1)): ... // test_err invalid_annotation_class // class F[T](y := list): ... // class I[T]((yield 1)): ... // class J[T]((yield from 1)): ... // class K[T: (yield 1)]: ... # yield in TypeVar // class L[T: (x := 1)]: ... # named expr in TypeVar // class M[T]((await 1)): ... // class N[T: (await 1)]: ... let mut visitor = InvalidExpressionVisitor { position: InvalidExpressionPosition::TypeAnnotation, ctx, }; visitor.visit_type_params(type_params); if let Some(arguments) = arguments { visitor.position = InvalidExpressionPosition::GenericDefinition; visitor.visit_arguments(arguments); } } Stmt::TypeAlias(ast::StmtTypeAlias { type_params, value, .. }) => { // test_err invalid_annotation_type_alias // type X[T: (yield 1)] = int # TypeVar bound // type X[T = (yield 1)] = int # TypeVar default // type X[*Ts = (yield 1)] = int # TypeVarTuple default // type X[**Ts = (yield 1)] = int # ParamSpec default // type Y = (yield 1) # yield in value // type Y = (x := 1) # named expr in value // type Y[T: (await 1)] = int # await in bound // type Y = (await 1) # await in value let mut visitor = InvalidExpressionVisitor { position: InvalidExpressionPosition::TypeAlias, ctx, }; visitor.visit_expr(value); if let Some(type_params) = type_params { visitor.visit_type_params(type_params); } } _ => {} } } /// Emit a [`SemanticSyntaxErrorKind::InvalidStarExpression`] if `expr` is starred. fn invalid_star_expression(expr: &Expr, ctx: &Ctx) { // test_ok single_star_in_tuple // def f(): yield (*x,) // def f(): return (*x,) // for _ in (*x,): ... // for (*x,) in xs: ... if expr.is_starred_expr() { Self::add_error( ctx, SemanticSyntaxErrorKind::InvalidStarExpression, expr.range(), ); } } fn multiple_star_expression( ctx: &Ctx, expr_ctx: ExprContext, elts: &[Expr], range: TextRange, ) { if expr_ctx.is_store() { let mut has_starred = false; for elt in elts { if elt.is_starred_expr() { if has_starred { // test_err multiple_starred_assignment_target // (*a, *b) = (1, 2) // [*a, *b] = (1, 2) // (*a, *b, c) = (1, 2, 3) // [*a, *b, c] = (1, 2, 3) // (*a, *b, (*c, *d)) = (1, 2) // test_ok multiple_starred_assignment_target // (*a, b) = (1, 2) // (*_, normed), *_ = [(1,), 2] Self::add_error( ctx, SemanticSyntaxErrorKind::MultipleStarredExpressions, range, ); return; } has_starred = true; } } } } /// Check for [`SemanticSyntaxErrorKind::WriteToDebug`] in `stmt`. fn debug_shadowing(stmt: &ast::Stmt, ctx: &Ctx) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { name, type_params, parameters, .. }) => { // test_err debug_shadow_function // def __debug__(): ... # function name // def f[__debug__](): ... # type parameter name // def f(__debug__): ... # parameter name // lambda __debug__: 0 # lambda parameter name Self::check_identifier(name, ctx); if let Some(type_params) = type_params { for type_param in type_params.iter() { Self::check_identifier(type_param.name(), ctx); } } for parameter in parameters { Self::check_identifier(parameter.name(), ctx); } } Stmt::ClassDef(ast::StmtClassDef { name, type_params, .. }) => { // test_err debug_shadow_class // class __debug__: ... # class name // class C[__debug__]: ... # type parameter name Self::check_identifier(name, ctx); if let Some(type_params) = type_params { for type_param in type_params.iter() { Self::check_identifier(type_param.name(), ctx); } } } Stmt::TypeAlias(ast::StmtTypeAlias { type_params: Some(type_params), .. }) => { // test_err debug_shadow_type_alias // type __debug__ = list[int] # visited as an Expr but still flagged // type Debug[__debug__] = str for type_param in type_params.iter() { Self::check_identifier(type_param.name(), ctx); } } Stmt::Import(ast::StmtImport { names, .. }) | Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => { // test_err debug_shadow_import // import __debug__ // import debug as __debug__ // from x import __debug__ // from x import debug as __debug__ // test_ok debug_rename_import // import __debug__ as debug // from __debug__ import Some // from x import __debug__ as debug for name in names { match &name.asname { Some(asname) => Self::check_identifier(asname, ctx), None => Self::check_identifier(&name.name, ctx), } } } Stmt::Try(ast::StmtTry { handlers, .. }) => { // test_err debug_shadow_try // try: ... // except Exception as __debug__: ... for handler in handlers .iter() .filter_map(ast::ExceptHandler::as_except_handler) { if let Some(name) = &handler.name { Self::check_identifier(name, ctx); } } } // test_err debug_shadow_with // with open("foo.txt") as __debug__: ... _ => {} } } /// Check if `ident` is equal to `__debug__` and emit a /// [`SemanticSyntaxErrorKind::WriteToDebug`] if so. fn check_identifier(ident: &ast::Identifier, ctx: &Ctx) { if ident.id == "__debug__" { Self::add_error( ctx, SemanticSyntaxErrorKind::WriteToDebug(WriteToDebugKind::Store), ident.range, ); } } fn duplicate_type_parameter_name( type_params: &ast::TypeParams, ctx: &Ctx, ) { if type_params.len() < 2 { return; } for (i, type_param) in type_params.iter().enumerate() { if type_params .iter() .take(i) .any(|t| t.name().id == type_param.name().id) { // test_ok non_duplicate_type_parameter_names // type Alias[T] = list[T] // def f[T](t: T): ... // class C[T]: ... // class C[T, U, V]: ... // type Alias[T, U: str, V: (str, bytes), *Ts, **P, D = default] = ... // test_err duplicate_type_parameter_names // type Alias[T, T] = ... // def f[T, T](t: T): ... // class C[T, T]: ... // type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... // def f[T, T, T](): ... # two errors // def f[T, *T](): ... # star is still duplicate // def f[T, **T](): ... # as is double star Self::add_error( ctx, SemanticSyntaxErrorKind::DuplicateTypeParameter, type_param.range(), ); } } } fn type_parameter_default_order( type_params: &ast::TypeParams, ctx: &Ctx, ) { let mut seen_default = false; for type_param in type_params { let has_default = match type_param { ast::TypeParam::TypeVar(ast::TypeParamTypeVar { default, .. }) | ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) | ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => { default.is_some() } }; if seen_default && !has_default { // test_err type_parameter_default_order // class C[T = int, U]: ... // class C[T1, T2 = int, T3, T4]: ... // def f[T = int, U](): ... // type Alias[T = int, U] = ... Self::add_error( ctx, SemanticSyntaxErrorKind::TypeParameterDefaultOrder( type_param.name().id.to_string(), ), type_param.range(), ); } if has_default { seen_default = true; } } } fn duplicate_parameter_name( parameters: &ast::Parameters, ctx: &Ctx, ) { if parameters.len() < 2 { return; } let mut all_arg_names = FxHashSet::with_capacity_and_hasher(parameters.len(), FxBuildHasher); for parameter in parameters { let range = parameter.name().range(); let param_name = parameter.name().as_str(); if !all_arg_names.insert(param_name) { // test_err params_duplicate_names // def foo(a, a=10, *a, a, a: str, **a): ... Self::add_error( ctx, SemanticSyntaxErrorKind::DuplicateParameter(param_name.to_string()), range, ); } } } fn irrefutable_match_case(stmt: &ast::StmtMatch, ctx: &Ctx) { // test_ok irrefutable_case_pattern_at_end // match x: // case 2: ... // case var: ... // match x: // case 2: ... // case _: ... // match x: // case var if True: ... # don't try to refute a guarded pattern // case 2: ... // test_err irrefutable_case_pattern // match x: // case var: ... # capture pattern // case 2: ... // match x: // case _: ... // case 2: ... # wildcard pattern // match x: // case var1 as var2: ... # as pattern with irrefutable left-hand side // case 2: ... // match x: // case enum.variant | var: ... # or pattern with irrefutable part // case 2: ... for case in stmt .cases .iter() .rev() .skip(1) .filter_map(|case| match case.guard { Some(_) => None, None => case.pattern.irrefutable_pattern(), }) { Self::add_error( ctx, SemanticSyntaxErrorKind::IrrefutableCasePattern(case.kind), case.range, ); } } /// Check `stmt` for semantic syntax errors and update the checker's internal state. /// /// Note that this method should only be called when traversing `stmt` *and* its children. For /// example, if traversal of function bodies needs to be deferred, avoid calling `visit_stmt` on /// the function itself until the deferred body is visited too. Failing to defer `visit_stmt` in /// this case will break any internal state that depends on function scopes, such as `async` /// context detection. pub fn visit_stmt(&mut self, stmt: &ast::Stmt, ctx: &Ctx) { // check for errors self.check_stmt(stmt, ctx); // update internal state match stmt { Stmt::Expr(StmtExpr { value, .. }) if !self.seen_module_docstring_boundary && value.is_string_literal_expr() => {} Stmt::ImportFrom(StmtImportFrom { module, is_lazy, .. }) => { // Allow eager `__future__` imports until we see any other import. Lazy imports, // including `lazy from __future__ import ...`, always close the boundary. if *is_lazy || !matches!(module.as_deref(), Some("__future__")) { self.seen_futures_boundary = true; } } Stmt::FunctionDef(StmtFunctionDef { is_async, body, .. }) => { if *is_async { let mut visitor = ReturnVisitor::default(); visitor.visit_body(body); if visitor.has_yield { if let Some(return_range) = visitor.return_range { Self::add_error( ctx, SemanticSyntaxErrorKind::ReturnInGenerator, return_range, ); } } } self.seen_futures_boundary = true; } _ => { self.seen_futures_boundary = true; } } self.seen_module_docstring_boundary = true; } /// Check `expr` for semantic syntax errors and update the checker's internal state. pub fn visit_expr(&mut self, expr: &Expr, ctx: &Ctx) { match expr { Expr::ListComp(ast::ExprListComp { elt, generators, .. }) | Expr::SetComp(ast::ExprSetComp { elt, generators, .. }) => { Self::check_generator_expr(elt, generators, ctx); Self::check_generator_clauses(generators, ctx); Self::async_comprehension_in_sync_comprehension(ctx, generators); for generator in generators.iter().filter(|g| g.is_async) { Self::await_outside_async_function( ctx, generator, AwaitOutsideAsyncFunctionKind::AsyncComprehension, ); } } Expr::DictComp(ast::ExprDictComp { key, value, generators, .. }) => { if let Some(key) = key { Self::check_generator_expr(key, generators, ctx); } Self::check_generator_expr(value, generators, ctx); Self::check_generator_clauses(generators, ctx); Self::async_comprehension_in_sync_comprehension(ctx, generators); for generator in generators.iter().filter(|g| g.is_async) { Self::await_outside_async_function( ctx, generator, AwaitOutsideAsyncFunctionKind::AsyncComprehension, ); } } Expr::Generator(ast::ExprGenerator { elt, generators, .. }) => { Self::check_generator_expr(elt, generators, ctx); Self::check_generator_clauses(generators, ctx); // Note that `await_outside_async_function` is not called here because generators // are evaluated lazily. See the note in the function for more details. } Expr::Name(ast::ExprName { range, id, ctx: expr_ctx, node_index: _, }) => { // test_err write_to_debug_expr // del __debug__ // del x, y, __debug__, z // __debug__ = 1 // x, y, __debug__, z = 1, 2, 3, 4 // test_err del_debug_py39 // # parse_options: {"target-version": "3.9"} // del __debug__ // test_ok del_debug_py38 // # parse_options: {"target-version": "3.8"} // del __debug__ // test_ok read_from_debug // if __debug__: ... // x = __debug__ if id == "__debug__" { match expr_ctx { ExprContext::Store => Self::add_error( ctx, SemanticSyntaxErrorKind::WriteToDebug(WriteToDebugKind::Store), *range, ), ExprContext::Del => { let version = ctx.python_version(); if version >= PythonVersion::PY39 { Self::add_error( ctx, SemanticSyntaxErrorKind::WriteToDebug( WriteToDebugKind::Delete(version), ), *range, ); } } _ => {} } } // PLE0118 if let Some(stmt) = ctx.global(id) { let start = stmt.start(); if expr.start() < start { Self::add_error( ctx, SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration { name: id.to_string(), start, }, expr.range(), ); } } } Expr::Yield(ast::ExprYield { value, .. }) => { if let Some(value) = value { // test_err single_star_yield // def f(): yield *x Self::invalid_star_expression(value, ctx); } Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::Yield); } Expr::YieldFrom(_) => { Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::YieldFrom); if ctx.in_function_scope() && ctx.in_async_context() { // test_err yield_from_in_async_function // async def f(): yield from x Self::add_error( ctx, SemanticSyntaxErrorKind::YieldFromInAsyncFunction, expr.range(), ); } } Expr::Await(_) => { Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::Await); Self::await_outside_async_function(ctx, expr, AwaitOutsideAsyncFunctionKind::Await); } Expr::Tuple(ast::ExprTuple { elts, ctx: expr_ctx, range, .. }) | Expr::List(ast::ExprList { elts, ctx: expr_ctx, range, .. }) => { Self::multiple_star_expression(ctx, *expr_ctx, elts, *range); } Expr::Lambda(ast::ExprLambda { parameters: Some(parameters), .. }) => { for parameter in parameters { Self::check_identifier(parameter.name(), ctx); } Self::duplicate_parameter_name(parameters, ctx); } _ => {} } } /// PLE1142 fn await_outside_async_function( ctx: &Ctx, node: Node, kind: AwaitOutsideAsyncFunctionKind, ) { if ctx.in_async_context() { return; } // `await` is allowed at the top level of a Jupyter notebook. // See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html. if ctx.in_module_scope() && ctx.in_notebook() { return; } // Generators are evaluated lazily, so you can use `await` in them. For example: // // ```python // # This is valid // def f(): // (await x for x in y) // (x async for x in y) // // # This is invalid // def f(): // (x for x in await y) // [await x for x in y] // ``` // // This check is required in addition to avoiding calling this function in `visit_expr` // because the generator scope applies to nested parts of the `Expr::Generator` that are // visited separately. if ctx.in_generator_context() { return; } Self::add_error( ctx, SemanticSyntaxErrorKind::AwaitOutsideAsyncFunction(kind), node.range(), ); } /// F704 fn yield_outside_function( ctx: &Ctx, expr: &Expr, kind: YieldOutsideFunctionKind, ) { // We are intentionally not inspecting the async status of the scope for now to mimic F704. // await-outside-async is PLE1142 instead, so we'll end up emitting both syntax errors for // cases that trigger F704 if ctx.in_function_scope() { return; } if kind.is_await() { // `await` is allowed at the top level of a Jupyter notebook. // See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html. if ctx.in_module_scope() && ctx.in_notebook() { return; } if ctx.in_await_allowed_context() { return; } } else if ctx.in_yield_allowed_context() { return; } Self::add_error( ctx, SemanticSyntaxErrorKind::YieldOutsideFunction(kind), expr.range(), ); } /// Add a [`SemanticSyntaxErrorKind::ReboundComprehensionVariable`] if `expr` rebinds an /// iteration variable in `generators`. fn check_generator_expr( expr: &Expr, comprehensions: &[ast::Comprehension], ctx: &Ctx, ) { Self::check_rebound_variables( expr, comprehension_target_names(comprehensions), FxHashSet::default(), ctx, ); Self::check_class_body_expr(expr, ctx); } fn check_generator_clauses( generators: &[ast::Comprehension], ctx: &Ctx, ) { // test_ok starred_comprehension_target // [item for (*items,) in source] // test_err starred_comprehension_target // [item for *items in source] for (index, generator) in generators.iter().enumerate() { Self::invalid_star_expression(&generator.target, ctx); for if_expr in &generator.ifs { Self::check_rebound_variables( if_expr, comprehension_target_names(&generators[..=index]), comprehension_target_names(&generators[index + 1..]), ctx, ); Self::check_class_body_expr(if_expr, ctx); } let mut visitor = ComprehensionIterableNamedExpressionVisitor::default(); visitor.visit_expr(&generator.iter); for range in visitor.ranges { Self::add_error( ctx, SemanticSyntaxErrorKind::NamedExpressionInComprehensionIterable, range, ); } } } fn check_rebound_variables<'a, Ctx: SemanticSyntaxContext>( expr: &Expr, targets: FxHashSet<&'a ast::name::Name>, direct_targets: FxHashSet<&'a ast::name::Name>, ctx: &Ctx, ) { let mut visitor = ReboundComprehensionVisitor { targets, direct_targets, ranges: Vec::new(), }; visitor.visit_expr(expr); // TODO(brent): With multiple diagnostic ranges, mark both the named expression target // (currently reported) and the comprehension target it rebinds. for range in visitor.ranges { // test_err rebound_comprehension_variable // [(a := 0) for a in range(0)] // {(a := 0) for a in range(0)} // {(a := 0): val for a in range(0)} // {key: (a := 0) for a in range(0)} // ((a := 0) for a in range(0)) // [[(a := 0)] for a in range(0)] // [(a := 0) for b in range (0) for a in range(0)] // [(a := 0) for a in range (0) for b in range(0)] // [((a := 0), (b := 1)) for a in range (0) for b in range(0)] // test_ok non_rebound_comprehension_variable // [a := 0 for x in range(0)] Self::add_error( ctx, SemanticSyntaxErrorKind::ReboundComprehensionVariable, range, ); } } fn check_class_body_expr(expr: &Expr, ctx: &Ctx) { if !ctx.in_class_body_comprehension() { return; } let mut visitor = ClassBodyNamedExpressionVisitor::default(); visitor.visit_expr(expr); for range in visitor.ranges { Self::add_error( ctx, SemanticSyntaxErrorKind::NamedExpressionInClassBodyComprehension, range, ); } } fn async_comprehension_in_sync_comprehension( ctx: &Ctx, generators: &[ast::Comprehension], ) { let python_version = ctx.python_version(); if python_version >= PythonVersion::PY311 { return; } // async allowed at notebook top-level if ctx.in_notebook() && ctx.in_module_scope() { return; } if !ctx.in_sync_comprehension() { return; } for generator in generators.iter().filter(|generator| generator.is_async) { // test_ok nested_async_comprehension_py311 // # parse_options: {"target-version": "3.11"} // async def f(): return [[x async for x in foo(n)] for n in range(3)] # list // async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict // async def h(): return [{x async for x in foo(n)} for n in range(3)] # set // test_ok nested_async_comprehension_py310 // # parse_options: {"target-version": "3.10"} // async def f(): // [_ for n in range(3)] // [_ async for n in range(3)] // async def f(): // def g(): ... // [_ async for n in range(3)] // test_ok all_async_comprehension_py310 // # parse_options: {"target-version": "3.10"} // async def test(): return [[x async for x in elements(n)] async for n in range(3)] // test_err nested_async_comprehension_py310 // # parse_options: {"target-version": "3.10"} // async def f(): return [[x async for x in foo(n)] for n in range(3)] # list // async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict // async def h(): return [{x async for x in foo(n)} for n in range(3)] # set // async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] // async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)] Self::add_error( ctx, SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(python_version), generator.range, ); } } } fn is_known_future_feature(name: &str) -> bool { matches!( name, "nested_scopes" | "generators" | "division" | "absolute_import" | "with_statement" | "print_function" | "unicode_literals" | "barry_as_FLUFL" | "generator_stop" | "annotations" ) } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum LazyImportKind { Import, ImportFrom, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum LazyImportContext { Function, Class, TryExceptBlocks, } #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] pub struct SemanticSyntaxError { pub kind: SemanticSyntaxErrorKind, pub range: TextRange, pub python_version: PythonVersion, } impl Display for SemanticSyntaxError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.kind { SemanticSyntaxErrorKind::LateFutureImport => { f.write_str("__future__ imports must be at the top of the file") } SemanticSyntaxErrorKind::NamedExpressionInComprehensionIterable => f.write_str( "assignment expression cannot be used in a comprehension iterable expression", ), SemanticSyntaxErrorKind::NamedExpressionInClassBodyComprehension => f.write_str( "assignment expression within a comprehension cannot be used in a class body", ), SemanticSyntaxErrorKind::ReboundComprehensionVariable => { f.write_str("assignment expression cannot rebind comprehension variable") } SemanticSyntaxErrorKind::DuplicateTypeParameter => { f.write_str("duplicate type parameter") } SemanticSyntaxErrorKind::TypeParameterDefaultOrder(name) => { write!( f, "non default type parameter `{name}` follows default type parameter" ) } SemanticSyntaxErrorKind::MultipleCaseAssignment(name) => { write!(f, "multiple assignments to name `{name}` in pattern") } SemanticSyntaxErrorKind::MultipleStarredNamesInSequencePattern => { f.write_str("multiple starred names in sequence pattern") } SemanticSyntaxErrorKind::IrrefutableCasePattern(kind) => match kind { // These error messages are taken from CPython's syntax errors IrrefutablePatternKind::Name(name) => { write!( f, "name capture `{name}` makes remaining patterns unreachable" ) } IrrefutablePatternKind::Wildcard => { f.write_str("wildcard makes remaining patterns unreachable") } }, SemanticSyntaxErrorKind::SingleStarredAssignment => { f.write_str("starred assignment target must be in a list or tuple") } SemanticSyntaxErrorKind::WriteToDebug(kind) => match kind { WriteToDebugKind::Store => f.write_str("cannot assign to `__debug__`"), WriteToDebugKind::Delete(python_version) => { write!( f, "cannot delete `__debug__` on Python {python_version} (syntax was removed in 3.9)" ) } }, SemanticSyntaxErrorKind::InvalidExpression(kind, position) => { write!(f, "{kind} cannot be used within a {position}") } SemanticSyntaxErrorKind::DuplicateMatchKey(key) => { write!( f, "mapping pattern checks duplicate key `{}`", EscapeDefault(key) ) } SemanticSyntaxErrorKind::DuplicateMatchClassAttribute(name) => { write!(f, "attribute name `{name}` repeated in class pattern") } SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration { name, start: _ } => { write!(f, "name `{name}` is used prior to global declaration") } SemanticSyntaxErrorKind::LoadBeforeNonlocalDeclaration { name, start: _ } => { write!(f, "name `{name}` is used prior to nonlocal declaration") } SemanticSyntaxErrorKind::InvalidStarExpression => { f.write_str("Starred expression cannot be used here") } SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(python_version) => { write!( f, "cannot use an asynchronous comprehension inside of a synchronous comprehension \ on Python {python_version} (syntax was added in 3.11)", ) } SemanticSyntaxErrorKind::YieldOutsideFunction(kind) => { write!(f, "`{kind}` statement outside of a function") } SemanticSyntaxErrorKind::ReturnOutsideFunction => { f.write_str("`return` statement outside of a function") } SemanticSyntaxErrorKind::AwaitOutsideAsyncFunction(kind) => { write!(f, "{kind} outside of an asynchronous function") } SemanticSyntaxErrorKind::DuplicateParameter(name) => { write!(f, r#"Duplicate parameter "{name}""#) } SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => { write!(f, "nonlocal declaration not allowed at module level") } SemanticSyntaxErrorKind::NonlocalAndGlobal(name) => { write!(f, "name `{name}` is nonlocal and global") } SemanticSyntaxErrorKind::AnnotatedGlobal(name) => { write!(f, "annotated name `{name}` can't be global") } SemanticSyntaxErrorKind::AnnotatedNonlocal(name) => { write!(f, "annotated name `{name}` can't be nonlocal") } SemanticSyntaxErrorKind::YieldFromInAsyncFunction => { f.write_str("`yield from` statement in async function; use `async for` instead") } SemanticSyntaxErrorKind::NonModuleImportStar(name) => { write!(f, "`from {name} import *` only allowed at module level") } SemanticSyntaxErrorKind::MultipleStarredExpressions => { write!(f, "Two starred expressions in assignment") } SemanticSyntaxErrorKind::FutureFeatureNotDefined(name) => { write!(f, "Future feature `{name}` is not defined") } SemanticSyntaxErrorKind::LazyImportNotAllowed { context, kind } => { let statement = match kind { LazyImportKind::Import => "lazy import", LazyImportKind::ImportFrom => "lazy from ... import", }; let location = match context { LazyImportContext::Function => "functions", LazyImportContext::Class => "classes", LazyImportContext::TryExceptBlocks => "try/except blocks", }; write!(f, "{statement} not allowed inside {location}") } SemanticSyntaxErrorKind::LazyImportStar => { f.write_str("lazy from ... import * is not allowed") } SemanticSyntaxErrorKind::LazyFutureImport => { f.write_str("lazy from __future__ import is not allowed") } SemanticSyntaxErrorKind::BreakOutsideLoop => f.write_str("`break` outside loop"), SemanticSyntaxErrorKind::ContinueOutsideLoop => f.write_str("`continue` outside loop"), SemanticSyntaxErrorKind::GlobalParameter(name) => { write!( f, "name `{name}` cannot refer to a parameter and a global variable" ) } SemanticSyntaxErrorKind::DifferentMatchPatternBindings => { write!(f, "alternative patterns bind different names") } SemanticSyntaxErrorKind::NonlocalWithoutBinding(name) => { write!(f, "no binding for nonlocal `{name}` found") } SemanticSyntaxErrorKind::ReturnInGenerator => { write!(f, "`return` with value in async generator") } } } } impl Ranged for SemanticSyntaxError { fn range(&self) -> TextRange { self.range } } #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum SemanticSyntaxErrorKind { /// Represents a `lazy` import statement in an invalid context. LazyImportNotAllowed { context: LazyImportContext, kind: LazyImportKind, }, /// Represents the use of `lazy from ... import *`. LazyImportStar, /// Represents the use of `lazy from __future__ import ...`. LazyFutureImport, /// Represents the use of a `__future__` import after the beginning of a file. /// /// ## Examples /// /// ```python /// from pathlib import Path /// /// from __future__ import annotations /// ``` /// /// This corresponds to the [`late-future-import`] (`F404`) rule in ruff. /// /// [`late-future-import`]: https://docs.astral.sh/ruff/rules/late-future-import/ LateFutureImport, /// Represents the use of an assignment expression within a comprehension iterable clause. /// /// ## Examples /// /// ```python /// [x for x in (y := range(3))] /// [x for x in [z for z in range(3) if (y := z)]] /// ``` NamedExpressionInComprehensionIterable, /// Represents the use of an assignment expression within a comprehension nested directly or /// indirectly in a class body. /// /// ## Examples /// /// ```python /// class C: /// [(x := y) for y in range(3)] /// ``` NamedExpressionInClassBodyComprehension, /// Represents the rebinding of the iteration variable of a list, set, or dict comprehension or /// a generator expression. /// /// ## Examples /// /// ```python /// [(a := 0) for a in range(0)] /// {(a := 0) for a in range(0)} /// {(a := 0): val for a in range(0)} /// {key: (a := 0) for a in range(0)} /// ((a := 0) for a in range(0)) /// ``` ReboundComprehensionVariable, /// Represents a duplicate type parameter name in a function definition, class definition, or /// type alias statement. /// /// ## Examples /// /// ```python /// type Alias[T, T] = ... /// def f[T, T](t: T): ... /// class C[T, T]: ... /// ``` DuplicateTypeParameter, /// Represents a duplicate binding in a `case` pattern of a `match` statement. /// /// ## Examples /// /// ```python /// match x: /// case [x, y, x]: ... /// case x as x: ... /// case Class(x=1, x=2): ... /// ``` MultipleCaseAssignment(ast::name::Name), /// Represents multiple starred names in a sequence pattern. /// /// ## Examples /// /// ```python /// match x: /// case [*head, middle, *tail]: ... /// ``` MultipleStarredNamesInSequencePattern, /// Represents an irrefutable `case` pattern before the last `case` in a `match` statement. /// /// According to the [Python reference], "a match statement may have at most one irrefutable /// case block, and it must be last." /// /// ## Examples /// /// ```python /// match x: /// case value: ... # irrefutable capture pattern /// case other: ... /// /// match x: /// case _: ... # irrefutable wildcard pattern /// case other: ... /// ``` /// /// [Python reference]: https://docs.python.org/3/reference/compound_stmts.html#irrefutable-case-blocks IrrefutableCasePattern(IrrefutablePatternKind), /// Represents a single starred assignment target outside of a tuple or list. /// /// ## Examples /// /// ```python /// *a = (1,) # SyntaxError /// ``` /// /// A starred assignment target can only occur within a tuple or list: /// /// ```python /// b, *a = 1, 2, 3 /// (*a,) = 1, 2, 3 /// [*a] = 1, 2, 3 /// ``` SingleStarredAssignment, /// Represents a write to `__debug__`. This includes simple assignments and deletions as well /// other kinds of statements that can introduce bindings, such as type parameters in functions, /// classes, and aliases, `match` arms, and imports, among others. /// /// ## Examples /// /// ```python /// del __debug__ /// __debug__ = False /// def f(__debug__): ... /// class C[__debug__]: ... /// ``` /// /// See [BPO 45000] for more information. /// /// [BPO 45000]: https://github.com/python/cpython/issues/89163 WriteToDebug(WriteToDebugKind), /// Represents the use of an invalid expression kind in one of several locations. /// /// The kinds include `yield` and `yield from` expressions and named expressions, and locations /// include type parameter bounds and defaults, type annotations, type aliases, and base class /// lists. /// /// ## Examples /// /// ```python /// type X[T: (yield 1)] = int /// type Y = (yield 1) /// def f[T](x: int) -> (y := 3): return x /// ``` InvalidExpression(InvalidExpressionKind, InvalidExpressionPosition), /// Represents a duplicate key in a `match` mapping pattern. /// /// The [CPython grammar] allows keys in mapping patterns to be literals or attribute accesses: /// /// ```text /// key_value_pattern: /// | (literal_expr | attr) ':' pattern /// ``` /// /// But only literals are checked for duplicates: /// /// ```pycon /// >>> match x: /// ... case {"x": 1, "x": 2}: ... /// ... /// File "", line 2 /// case {"x": 1, "x": 2}: ... /// ^^^^^^^^^^^^^^^^ /// SyntaxError: mapping pattern checks duplicate key ('x') /// >>> match x: /// ... case {x.a: 1, x.a: 2}: ... /// ... /// >>> /// ``` /// /// ## Examples /// /// ```python /// match x: /// case {"x": 1, "x": 2}: ... /// ``` /// /// [CPython grammar]: https://docs.python.org/3/reference/grammar.html DuplicateMatchKey(String), /// Represents a duplicate attribute name in a `match` class pattern. /// /// ## Examples /// /// ```python /// match x: /// case Class(x=1, x=2): ... /// ``` DuplicateMatchClassAttribute(ast::name::Name), /// Represents the use of a `global` variable before its `global` declaration. /// /// ## Examples /// /// ```python /// counter = 1 /// def increment(): /// print(f"Adding 1 to {counter}") /// global counter /// counter += 1 /// ``` /// /// ## Known Issues /// /// Note that the order in which the parts of a `try` statement are visited was changed in 3.13, /// as tracked in Python issue [#111123]. For example, this code was valid on Python 3.12: /// /// ```python /// a = 10 /// def g(): /// try: /// 1 / 0 /// except: /// a = 1 /// else: /// global a /// ``` /// /// While this more intuitive behavior aligned with the textual order was a syntax error: /// /// ```python /// a = 10 /// def f(): /// try: /// pass /// except: /// global a /// else: /// a = 1 # SyntaxError: name 'a' is assigned to before global declaration /// ``` /// /// This was reversed in version 3.13 to make the second case valid and the first case a syntax /// error. We intentionally enforce the 3.13 ordering, regardless of the Python version, which /// will lead to both false positives and false negatives on 3.12 code that takes advantage of /// the old behavior. However, as mentioned in the Python issue, we expect code relying on this /// to be very rare and not worth the additional complexity to detect. /// /// [#111123]: https://github.com/python/cpython/issues/111123 LoadBeforeGlobalDeclaration { name: String, start: TextSize }, /// Represents the use of a `nonlocal` variable before its `nonlocal` declaration. /// /// ## Examples /// /// ```python /// def f(): /// counter = 0 /// def increment(): /// print(f"Adding 1 to {counter}") /// nonlocal counter # SyntaxError: name 'counter' is used prior to nonlocal declaration /// counter += 1 /// ``` /// /// ## Known Issues /// /// See [`LoadBeforeGlobalDeclaration`][Self::LoadBeforeGlobalDeclaration]. LoadBeforeNonlocalDeclaration { name: String, start: TextSize }, /// Represents the use of a starred expression in an invalid location, such as a `return` or /// `yield` statement. /// /// ## Examples /// /// ```python /// def f(): return *x /// def f(): yield *x /// for _ in *x: ... /// for *x in xs: ... /// ``` InvalidStarExpression, /// Represents the use of an asynchronous comprehension inside of a synchronous comprehension /// before Python 3.11. /// /// ## Examples /// /// Before Python 3.11, code like this produces a syntax error because of the implicit function /// scope introduced by the outer comprehension: /// /// ```python /// async def elements(n): yield n /// /// async def test(): return { n: [x async for x in elements(n)] for n in range(3)} /// ``` /// /// This was discussed in [BPO 33346] and fixed in Python 3.11. /// /// [BPO 33346]: https://github.com/python/cpython/issues/77527 AsyncComprehensionInSyncComprehension(PythonVersion), /// Represents the use of `yield`, `yield from`, or `await` outside of a function scope. /// /// /// ## Examples /// /// `yield` and `yield from` are only allowed if the immediately-enclosing scope is a function /// or lambda and not allowed otherwise: /// /// ```python /// yield 1 # error /// /// def f(): /// [(yield 1) for x in y] # error /// ``` /// /// `await` is additionally allowed in comprehensions, if the comprehension itself is in a /// function scope: /// /// ```python /// await 1 # error /// /// async def f(): /// await 1 # okay /// [await 1 for x in y] # also okay /// ``` /// /// This last case _is_ an error, but it has to do with the lambda not being an async function. /// For the sake of this error kind, this is okay. /// /// ## References /// /// See [PEP 255] for details on `yield`, [PEP 380] for the extension to `yield from`, [PEP 492] /// for async-await syntax, and [PEP 530] for async comprehensions. /// /// [PEP 255]: https://peps.python.org/pep-0255/ /// [PEP 380]: https://peps.python.org/pep-0380/ /// [PEP 492]: https://peps.python.org/pep-0492/ /// [PEP 530]: https://peps.python.org/pep-0530/ YieldOutsideFunction(YieldOutsideFunctionKind), /// Represents the use of `return` outside of a function scope. ReturnOutsideFunction, /// Represents the use of `await`, `async for`, or `async with` outside of an asynchronous /// function. /// /// ## Examples /// /// ```python /// def f(): /// await 1 # error /// async for x in y: ... # error /// async with x: ... # error /// ``` AwaitOutsideAsyncFunction(AwaitOutsideAsyncFunctionKind), /// Represents a duplicate parameter name in a function or lambda expression. /// /// ## Examples /// /// ```python /// def f(x, x): ... /// lambda x, x: ... /// ``` DuplicateParameter(String), /// Represents a nonlocal declaration at module level NonlocalDeclarationAtModuleLevel, /// Represents the same variable declared as both nonlocal and global NonlocalAndGlobal(String), /// Represents a type annotation on a variable that's been declared global AnnotatedGlobal(String), /// Represents a type annotation on a variable that's been declared nonlocal AnnotatedNonlocal(String), /// Represents the use of `yield from` inside an asynchronous function. YieldFromInAsyncFunction, /// Represents the use of `from import *` outside module scope. NonModuleImportStar(String), /// Represents the use of more than one starred expression in an assignment. /// /// Python only allows a single starred target when unpacking values on the /// left-hand side of an assignment. Using multiple starred expressions makes /// the statement invalid and results in a `SyntaxError`. MultipleStarredExpressions, /// Represents the use of a `__future__` feature that is not defined. FutureFeatureNotDefined(String), /// Represents the use of a `break` statement outside of a loop. BreakOutsideLoop, /// Represents the use of a `continue` statement outside of a loop. ContinueOutsideLoop, /// Represents a function parameter that is also declared as `global`. /// /// Declaring a parameter as `global` is invalid, since parameters are already /// bound in the local scope of the function. Using `global` on them introduces /// ambiguity and will result in a `SyntaxError`. GlobalParameter(String), /// Represents the use of alternative patterns in a `match` statement that bind different names. /// /// Python requires all alternatives in an OR pattern (`|`) to bind the same set of names. /// Using different names results in a `SyntaxError`. /// /// ## Example: /// /// ```python /// match 5: /// case [x] | [y]: # error /// ... /// ``` DifferentMatchPatternBindings, /// Represents a nonlocal statement for a name that has no binding in an enclosing scope. NonlocalWithoutBinding(String), /// Represents a default type parameter followed by a non-default type parameter. TypeParameterDefaultOrder(String), /// Represents a `return` statement with a value in an asynchronous generator. ReturnInGenerator, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum AwaitOutsideAsyncFunctionKind { Await, AsyncFor, AsyncWith, AsyncComprehension, } impl Display for AwaitOutsideAsyncFunctionKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { AwaitOutsideAsyncFunctionKind::Await => "`await`", AwaitOutsideAsyncFunctionKind::AsyncFor => "`async for`", AwaitOutsideAsyncFunctionKind::AsyncWith => "`async with`", AwaitOutsideAsyncFunctionKind::AsyncComprehension => "asynchronous comprehension", }) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum YieldOutsideFunctionKind { Yield, YieldFrom, Await, } impl YieldOutsideFunctionKind { pub fn is_await(&self) -> bool { matches!(self, Self::Await) } } impl Display for YieldOutsideFunctionKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { YieldOutsideFunctionKind::Yield => "yield", YieldOutsideFunctionKind::YieldFrom => "yield from", YieldOutsideFunctionKind::Await => "await", }) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum InvalidExpressionPosition { TypeVarBound, TypeVarDefault, TypeVarTupleDefault, ParamSpecDefault, TypeAnnotation, GenericDefinition, TypeAlias, } impl Display for InvalidExpressionPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { InvalidExpressionPosition::TypeVarBound => "TypeVar bound", InvalidExpressionPosition::TypeVarDefault => "TypeVar default", InvalidExpressionPosition::TypeVarTupleDefault => "TypeVarTuple default", InvalidExpressionPosition::ParamSpecDefault => "ParamSpec default", InvalidExpressionPosition::TypeAnnotation => "type annotation", InvalidExpressionPosition::GenericDefinition => "generic definition", InvalidExpressionPosition::TypeAlias => "type alias", }) } } #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum InvalidExpressionKind { Yield, NamedExpr, Await, } impl Display for InvalidExpressionKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { InvalidExpressionKind::Yield => "yield expression", InvalidExpressionKind::NamedExpr => "named expression", InvalidExpressionKind::Await => "await expression", }) } } #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] pub enum WriteToDebugKind { Store, Delete(PythonVersion), } fn comprehension_target_names( comprehensions: &[ast::Comprehension], ) -> FxHashSet<&ast::name::Name> { let mut visitor = helpers::StoredNameFinder::default(); for comprehension in comprehensions { visitor.visit_expr(&comprehension.target); } visitor.names.into_values().map(|name| &name.id).collect() } #[derive(Default)] struct ComprehensionIterableNamedExpressionVisitor { ranges: Vec, } impl Visitor<'_> for ComprehensionIterableNamedExpressionVisitor { fn visit_expr(&mut self, expr: &Expr) { if let Expr::Named(ast::ExprNamed { target, range, .. }) = expr && target.is_name_expr() { self.ranges.push(*range); } walk_expr(self, expr); } } #[derive(Default)] struct ClassBodyNamedExpressionVisitor { ranges: Vec, } impl Visitor<'_> for ClassBodyNamedExpressionVisitor { fn visit_expr(&mut self, expr: &Expr) { match expr { Expr::Lambda(ast::ExprLambda { parameters, .. }) => { // Defaults execute in the enclosing comprehension; lambda bodies do not. if let Some(parameters) = parameters { self.visit_parameters(parameters); } return; } Expr::ListComp(_) | Expr::SetComp(_) | Expr::DictComp(_) | Expr::Generator(_) => { // Nested comprehensions are checked when normal traversal reaches them. return; } Expr::Named(ast::ExprNamed { target, range, .. }) if target.is_name_expr() => { self.ranges.push(*range); } _ => {} } walk_expr(self, expr); } } /// Searches for named expressions (`x := y`) rebinding a comprehension or generator expression's /// iteration variables. struct ReboundComprehensionVisitor<'a> { /// Targets that apply inside nested comprehensions. targets: FxHashSet<&'a ast::name::Name>, /// Targets from later filter clauses, which do not apply inside nested comprehensions. direct_targets: FxHashSet<&'a ast::name::Name>, ranges: Vec, } impl Visitor<'_> for ReboundComprehensionVisitor<'_> { fn visit_expr(&mut self, expr: &Expr) { match expr { Expr::Lambda(ast::ExprLambda { parameters, .. }) => { if let Some(parameters) = parameters { self.visit_parameters(parameters); } return; } Expr::ListComp(_) | Expr::SetComp(_) | Expr::DictComp(_) | Expr::Generator(_) if !self.direct_targets.is_empty() => { let direct_targets = std::mem::take(&mut self.direct_targets); walk_expr(self, expr); self.direct_targets = direct_targets; return; } Expr::Named(ast::ExprNamed { target, .. }) => { if let Expr::Name(ast::ExprName { id, range, .. }) = &**target && (self.targets.contains(id) || self.direct_targets.contains(id)) { self.ranges.push(*range); } } _ => {} } walk_expr(self, expr); } } #[derive(Default)] struct ReturnVisitor { return_range: Option, has_yield: bool, } impl Visitor<'_> for ReturnVisitor { fn visit_stmt(&mut self, stmt: &Stmt) { match stmt { // Do not recurse into nested functions; they're evaluated separately. Stmt::FunctionDef(_) | Stmt::ClassDef(_) => {} Stmt::Return(ast::StmtReturn { value: Some(_), range, .. }) => { self.return_range = Some(*range); walk_stmt(self, stmt); } _ => walk_stmt(self, stmt), } } fn visit_expr(&mut self, expr: &Expr) { match expr { Expr::Lambda(_) => {} Expr::Yield(_) | Expr::YieldFrom(_) => { self.has_yield = true; } _ => walk_expr(self, expr), } } } struct MatchPatternVisitor<'a, Ctx> { names: FxHashSet<&'a ast::name::Name>, ctx: &'a Ctx, } impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> { fn visit_pattern(&mut self, pattern: &'a Pattern) { // test_ok class_keyword_in_case_pattern // match 2: // case Class(x=x): ... // test_err multiple_assignment_in_case_pattern // match 2: // case [y, z, y]: ... # MatchSequence // case [y, z, *y]: ... # MatchSequence // case [y, y, y]: ... # MatchSequence multiple // case {1: x, 2: x}: ... # MatchMapping duplicate pattern // case {1: x, **x}: ... # MatchMapping duplicate in **rest // case Class(x, x): ... # MatchClass positional // case Class(y=x, z=x): ... # MatchClass keyword // case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr // case x as x: ... # MatchAs // test_err multiple_starred_names_in_sequence_pattern // match subject: // case *first, *second, *third: ... match pattern { Pattern::MatchValue(_) | Pattern::MatchSingleton(_) => {} Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => { if let Some(name) = name { self.insert(name); } } Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { let mut seen_star_pattern = false; for pattern in patterns { if pattern.is_match_star() { if seen_star_pattern { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::MultipleStarredNamesInSequencePattern, pattern.range(), ); } seen_star_pattern = true; } self.visit_pattern(pattern); } } Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, rest, .. }) => { for pattern in patterns { self.visit_pattern(pattern); } if let Some(rest) = rest { self.insert(rest); } let mut seen = FxHashSet::default(); for key in keys .iter() // Signed and complex numbers are allowed as keys but are represented as unary // or binary expressions rather than literals. .filter(|key| { key.is_literal_expr() || key.is_unary_op_expr() || key.is_bin_op_expr() }) { if !seen.insert(HashableExpr::from(key)) { let key_range = key.range(); let duplicate_key = self.ctx.source()[key_range].to_string(); // test_ok duplicate_match_key_attr // match x: // case {x.a: 1, x.a: 2}: ... // test_err duplicate_match_key // match x: // case {"x": 1, "x": 2}: ... // case {b"x": 1, b"x": 2}: ... // case {0: 1, 0: 2}: ... // case {1.0: 1, 1.0: 2}: ... // case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... // case {True: 1, True: 2}: ... // case {None: 1, None: 2}: ... // case {0: 1, False: 2}: ... // case {1.0: 1, True: 2}: ... // case {-0: 1, False: 2}: ... // case {1 + 0j: 1, True: 2}: ... // case { // """x // y // z // """: 1, // """x // y // z // """: 2}: ... // case {"x": 1, "x": 2, "x": 3}: ... // case {0: 1, "x": 1, 0: 2, "x": 2}: ... // case [{"x": 1, "x": 2}]: ... // case Foo(x=1, y={"x": 1, "x": 2}): ... // case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... // case {2: 1, 2.0: 2}: ... // case {9007199254740993: 1, 9007199254740993 + 0j: 2}: ... SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::DuplicateMatchKey(duplicate_key), key_range, ); } } } Pattern::MatchClass(ast::PatternMatchClass { arguments, .. }) => { for pattern in &arguments.patterns { self.visit_pattern(pattern); } let mut seen = FxHashSet::default(); for keyword in &arguments.keywords { if !seen.insert(&keyword.attr.id) { // test_err duplicate_match_class_attr // match x: // case Class(x=1, x=2): ... // case [Class(x=1, x=2)]: ... // case {"x": x, "y": Foo(x=1, x=2)}: ... // case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... // case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::DuplicateMatchClassAttribute( keyword.attr.id.clone(), ), keyword.attr.range, ); } self.visit_pattern(&keyword.pattern); } } Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => { if let Some(pattern) = pattern { self.visit_pattern(pattern); } if let Some(name) = name { self.insert(name); } } Pattern::MatchOr(ast::PatternMatchOr { patterns, range, .. }) => { // each of these patterns should be visited separately because patterns can only be // duplicated within a single arm of the or pattern. For example, the case below is // a valid pattern. // test_ok multiple_assignment_in_case_pattern // match 2: // case Class(x) | [x] | x: ... let mut previous_names: Option> = None; for pattern in patterns { let mut visitor = Self { names: FxHashSet::default(), ctx: self.ctx, }; visitor.visit_pattern(pattern); let Some(prev) = &previous_names else { previous_names = Some(visitor.names); continue; }; if prev.symmetric_difference(&visitor.names).next().is_some() { // test_err different_match_pattern_bindings // match x: // case [a] | [b]: ... // case [a] | []: ... // case (x, y) | (x,): ... // case [a, _] | [a, b]: ... // case (x, (y | z)): ... // case [a] | [b] | [c]: ... // case [] | [a]: ... // case [a] | [C(x)]: ... // case [[a] | [b]]: ... // case [C(a)] | [C(b)]: ... // case [C(D(a))] | [C(D(b))]: ... // case [(a, b)] | [(c, d)]: ... // test_ok different_match_pattern_bindings // match x: // case [a] | [a]: ... // case (x, y) | (x, y): ... // case (x, (y | y)): ... // case [a, _] | [a, _]: ... // case [a] | [C(a)]: ... // test_ok nested_alternative_patterns // match ruff: // case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}: // ... // match 42: // case [[x] | [x]] | x: ... // match 42: // case [[x | x] | [x]] | x: ... // match 42: // case ast.Subscript(n, ast.Constant() | ast.Slice()) | ast.Attribute(n): ... SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::DifferentMatchPatternBindings, *range, ); break; } self.names.extend(visitor.names); } } } } /// Add an identifier to the set of visited names in `self` and emit a [`SemanticSyntaxError`] /// if `ident` has already been seen. fn insert(&mut self, ident: &'a ast::Identifier) { if !self.names.insert(&ident.id) { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::MultipleCaseAssignment(ident.id.clone()), ident.range(), ); } // test_err debug_shadow_match // match x: // case __debug__: ... SemanticSyntaxChecker::check_identifier(ident, self.ctx); } } struct InvalidExpressionVisitor<'a, Ctx> { /// Context used for emitting errors. ctx: &'a Ctx, position: InvalidExpressionPosition, } impl Visitor<'_> for InvalidExpressionVisitor<'_, Ctx> where Ctx: SemanticSyntaxContext, { fn visit_expr(&mut self, expr: &Expr) { match expr { Expr::Named(ast::ExprNamed { range, .. }) => { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::InvalidExpression( InvalidExpressionKind::NamedExpr, self.position, ), *range, ); } Expr::Yield(ast::ExprYield { range, .. }) | Expr::YieldFrom(ast::ExprYieldFrom { range, .. }) => { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::InvalidExpression( InvalidExpressionKind::Yield, self.position, ), *range, ); } Expr::Await(ast::ExprAwait { range, .. }) => { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::InvalidExpression( InvalidExpressionKind::Await, self.position, ), *range, ); } _ => {} } ast::visitor::walk_expr(self, expr); } fn visit_type_param(&mut self, type_param: &ast::TypeParam) { match type_param { ast::TypeParam::TypeVar(ast::TypeParamTypeVar { bound, default, .. }) => { if let Some(expr) = bound { self.position = InvalidExpressionPosition::TypeVarBound; self.visit_expr(expr); } if let Some(expr) = default { self.position = InvalidExpressionPosition::TypeVarDefault; self.visit_expr(expr); } } ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) => { if let Some(expr) = default { self.position = InvalidExpressionPosition::TypeVarTupleDefault; self.visit_expr(expr); } } ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => { if let Some(expr) = default { self.position = InvalidExpressionPosition::ParamSpecDefault; self.visit_expr(expr); } } } } } /// Information needed from a parent visitor to emit semantic syntax errors. /// /// Note that the `in_*_scope` methods should refer to the immediately-enclosing scope. For example, /// `in_function_scope` should return true for this case: /// /// ```python /// def f(): /// x # here /// ``` /// /// but not for this case: /// /// ```python /// def f(): /// class C: /// x # here /// ``` /// /// In contrast, the `in_*_context` methods should traverse parent scopes. For example, /// `in_function_context` should return true for this case: /// /// ```python /// def f(): /// [x # here /// for x in range(3)] /// ``` /// /// but not here: /// /// ```python /// def f(): /// class C: /// x # here, classes break function scopes /// ``` pub trait SemanticSyntaxContext { /// Returns `true` if `__future__`-style type annotations are enabled. fn future_annotations_or_stub(&self) -> bool; /// Returns the nearest invalid context for a `lazy` import statement, if any. /// /// This should return the innermost relevant restriction in order of precedence: /// function, class, then `try`/`except`. fn lazy_import_context(&self) -> Option; /// The target Python version for detecting backwards-incompatible syntax changes. fn python_version(&self) -> PythonVersion; /// Returns the source text under analysis. fn source(&self) -> &str; /// Return the [`TextRange`] at which a name is declared as `global` in the current scope. fn global(&self, name: &str) -> Option; /// Returns `true` if `name` has a binding in an enclosing scope. fn has_nonlocal_binding(&self, name: &str) -> bool; /// Returns `true` if the visitor is currently in an async context, i.e. an async function. fn in_async_context(&self) -> bool; /// Returns `true` if the visitor is currently in a context where the `await` keyword is /// allowed. /// /// Note that this is method is primarily used to report `YieldOutsideFunction` errors for /// `await` outside function scopes, irrespective of their async status. As such, this differs /// from `in_async_context` in two ways: /// /// 1. `await` is allowed in a lambda, despite it not being async /// 2. `await` is allowed in any function, regardless of its async status /// /// In short, only nested class definitions should cause this method to return `false`, for /// example: /// /// ```python /// def f(): /// await 1 # okay, in a function /// class C: /// await 1 # error /// ``` /// /// See the trait-level documentation for more details. fn in_await_allowed_context(&self) -> bool; /// Returns `true` if the visitor is currently in a context where `yield` and `yield from` /// expressions are allowed. /// /// Yield expressions are allowed only in: /// 1. Function definitions /// 2. Lambda expressions /// /// Unlike `await`, yield is not allowed in: /// - Comprehensions (list, set, dict) /// - Generator expressions /// - Class definitions /// /// This method should traverse parent scopes to check if the closest relevant scope /// is a function or lambda, and that no disallowed context (class, comprehension, generator) /// intervenes. For example: /// /// ```python /// def f(): /// yield 1 # okay, in a function /// lambda: (yield 1) # okay, in a lambda /// /// [(yield 1) for x in range(3)] # error, in a comprehension /// ((yield 1) for x in range(3)) # error, in a generator expression /// class C: /// yield 1 # error, in a class within a function /// ``` /// fn in_yield_allowed_context(&self) -> bool; /// Returns `true` if the visitor is currently inside of a synchronous comprehension. /// /// This method is necessary because `in_async_context` only checks for the nearest, enclosing /// function to determine the (a)sync context. Instead, this method will search all enclosing /// scopes until it finds a sync comprehension. As a result, the two methods will typically be /// used together. fn in_sync_comprehension(&self) -> bool; /// Returns `true` if a comprehension introduced at the current position is nested directly /// or indirectly in a class body, without crossing a function or lambda boundary. fn in_class_body_comprehension(&self) -> bool; /// Returns `true` if the visitor is at the top-level module scope. fn in_module_scope(&self) -> bool; /// Returns `true` if the visitor is in a function scope. fn in_function_scope(&self) -> bool; /// Returns `true` if the visitor is within a generator scope. /// /// Note that this refers to an `Expr::Generator` precisely, not to comprehensions more /// generally. fn in_generator_context(&self) -> bool; /// Returns `true` if the source file is a Jupyter notebook. fn in_notebook(&self) -> bool; fn report_semantic_error(&self, error: SemanticSyntaxError); /// Returns `true` if the visitor is inside a `for` or `while` loop. fn in_loop_context(&self) -> bool; /// Returns `true` if `name` is a bound parameter in the current function or lambda scope. fn is_bound_parameter(&self, name: &str) -> bool; } /// Modified version of [`std::str::EscapeDefault`] that does not escape single or double quotes. struct EscapeDefault<'a>(&'a str); impl Display for EscapeDefault<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use std::fmt::Write; for c in self.0.chars() { match c { '\'' | '\"' => f.write_char(c)?, _ => write!(f, "{}", c.escape_default())?, } } Ok(()) } } ruff_python_parser__lexer__tests__assignment.snap000064400000000000000000000003651046102023000334120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ Name 0..10, Equal 11..12, Int 13..15, Plus 16..17, Int 18..19, Minus 19..20, Int 20..21, Newline 21..21, ] ``` ruff_python_parser__lexer__tests__backslash_continuation_at_root.snap000064400000000000000000000007131046102023000375130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..15, Int 15..16, Newline 16..17, If 21..23, True 24..28, Colon 28..29, Newline 29..30, Indent 30..40, Int 40..41, Newline 41..42, Dedent 42..42, Dedent 42..42, Else 42..46, Colon 46..47, Int 53..54, Newline 54..55, ] ``` ruff_python_parser__lexer__tests__backslash_continuation_indentation.snap000064400000000000000000000006761046102023000403700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..13, Int 13..14, Newline 14..15, Int 29..30, Newline 30..31, Int 37..38, Newline 38..39, Dedent 39..39, Else 39..43, Colon 43..44, Newline 44..45, Indent 45..49, Pass 49..53, Newline 53..54, Dedent 54..54, ] ``` ruff_python_parser__lexer__tests__backslash_continuation_mismatch_indentation.snap000064400000000000000000000006251046102023000422470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(&source, Mode::Module)" --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..13, Int 13..14, Newline 14..15, Unknown 15..23, Int 23..24, Newline 24..25, ] ``` ## Errors ``` [ LexicalError { error: IndentationError, location: 15..23, }, ] ``` ruff_python_parser__lexer__tests__bom.snap000064400000000000000000000002531046102023000320130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ Name 3..4, Equal 5..6, Int 7..8, Newline 8..8, ] ``` ruff_python_parser__lexer__tests__bom_with_offset.snap000064400000000000000000000003201046102023000344070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_source_with_offset(source, TextSize::new(7))" --- ## Tokens ``` [ Name 7..8, Plus 9..10, Name 11..12, Newline 12..12, ] ``` ruff_python_parser__lexer__tests__bom_with_offset_edge.snap000064400000000000000000000002621046102023000354000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_source_with_offset(source, TextSize::new(11))" --- ## Tokens ``` [ Name 11..12, Newline 12..12, ] ``` ruff_python_parser__lexer__tests__comment_until_mac_eol.snap000064400000000000000000000003151046102023000355710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: comment_until_eol(MAC_EOL) --- ## Tokens ``` [ Int 0..3, Comment 5..10, Newline 10..11, Int 11..14, Newline 14..14, ] ``` ruff_python_parser__lexer__tests__comment_until_unix_eol.snap000064400000000000000000000003161046102023000360150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: comment_until_eol(UNIX_EOL) --- ## Tokens ``` [ Int 0..3, Comment 5..10, Newline 10..11, Int 11..14, Newline 14..14, ] ``` ruff_python_parser__lexer__tests__comment_until_windows_eol.snap000064400000000000000000000003211046102023000365200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: comment_until_eol(WINDOWS_EOL) --- ## Tokens ``` [ Int 0..3, Comment 5..10, Newline 10..12, Int 12..15, Newline 15..15, ] ``` ruff_python_parser__lexer__tests__dedent_after_whitespace.snap000064400000000000000000000006071046102023000361010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ If 0..2, Name 3..8, Colon 8..9, Newline 9..10, Indent 10..14, If 14..16, Name 17..23, Colon 23..24, Newline 24..25, Indent 25..33, Pass 33..37, Newline 37..38, Dedent 42..42, Name 42..45, Newline 45..46, Dedent 46..46, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_mac_eol.snap000064400000000000000000000007361046102023000365530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_eol(MAC_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..12, If 12..14, Name 15..16, Colon 16..17, Newline 17..18, NonLogicalNewline 18..19, Indent 19..21, Return 21..27, Int 28..30, Newline 30..31, NonLogicalNewline 31..32, Dedent 32..32, Dedent 32..32, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_tabs_mac_eol.snap000064400000000000000000000007431046102023000375620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_tabs_eol(MAC_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..12, If 12..14, Name 15..16, Colon 16..17, Newline 17..18, NonLogicalNewline 18..19, Indent 19..22, Return 22..28, Int 29..31, Newline 31..32, NonLogicalNewline 32..33, Dedent 33..33, Dedent 33..33, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_tabs_unix_eol.snap000064400000000000000000000007441046102023000400060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_tabs_eol(UNIX_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..12, If 12..14, Name 15..16, Colon 16..17, Newline 17..18, NonLogicalNewline 18..19, Indent 19..22, Return 22..28, Int 29..31, Newline 31..32, NonLogicalNewline 32..33, Dedent 33..33, Dedent 33..33, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_tabs_windows_eol.snap000064400000000000000000000007471046102023000405200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_tabs_eol(WINDOWS_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..12, Indent 12..13, If 13..15, Name 16..17, Colon 17..18, Newline 18..20, NonLogicalNewline 20..22, Indent 22..25, Return 25..31, Int 32..34, Newline 34..36, NonLogicalNewline 36..38, Dedent 38..38, Dedent 38..38, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_unix_eol.snap000064400000000000000000000007371046102023000367770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_eol(UNIX_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..12, If 12..14, Name 15..16, Colon 16..17, Newline 17..18, NonLogicalNewline 18..19, Indent 19..21, Return 21..27, Int 28..30, Newline 30..31, NonLogicalNewline 31..32, Dedent 32..32, Dedent 32..32, ] ``` ruff_python_parser__lexer__tests__double_dedent_with_windows_eol.snap000064400000000000000000000007421046102023000375020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: double_dedent_with_eol(WINDOWS_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..12, Indent 12..13, If 13..15, Name 16..17, Colon 17..18, Newline 18..20, NonLogicalNewline 20..22, Indent 22..24, Return 24..30, Int 31..33, Newline 33..35, NonLogicalNewline 35..37, Dedent 37..37, Dedent 37..37, ] ``` ruff_python_parser__lexer__tests__emoji_identifier.snap000064400000000000000000000004361046102023000345460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ Unknown 0..4, ] ``` ## Errors ``` [ LexicalError { error: UnrecognizedToken { tok: '🐦', }, location: 0..4, }, ] ``` ruff_python_parser__lexer__tests__empty_fstrings.snap000064400000000000000000000014371046102023000343200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 2..3 (flags = DOUBLE_QUOTES | F_STRING), String 4..6 (flags = DOUBLE_QUOTES), FStringStart 7..9 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 9..10 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 11..13 (flags = F_STRING), FStringEnd 13..14 (flags = F_STRING), String 15..17, FStringStart 18..22 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 22..25 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringStart 26..30 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 30..33 (flags = TRIPLE_QUOTED_STRING | F_STRING), Newline 33..33, ] ``` ruff_python_parser__lexer__tests__empty_ipython_escape_command.snap000064400000000000000000000010361046102023000371640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ IpyEscapeCommand 0..1, Newline 1..2, IpyEscapeCommand 2..4, Newline 4..5, IpyEscapeCommand 5..6, Newline 6..7, IpyEscapeCommand 7..9, Newline 9..10, IpyEscapeCommand 10..11, Newline 11..12, IpyEscapeCommand 12..14, Newline 14..15, IpyEscapeCommand 15..16, Newline 16..17, IpyEscapeCommand 17..18, Newline 18..19, IpyEscapeCommand 19..20, Newline 20..20, ] ``` ruff_python_parser__lexer__tests__empty_tstrings.snap000064400000000000000000000014371046102023000343360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 2..3 (flags = DOUBLE_QUOTES | T_STRING), String 4..6 (flags = DOUBLE_QUOTES), TStringStart 7..9 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 9..10 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 11..13 (flags = T_STRING), TStringEnd 13..14 (flags = T_STRING), String 15..17, TStringStart 18..22 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 22..25 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringStart 26..30 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 30..33 (flags = TRIPLE_QUOTED_STRING | T_STRING), Newline 33..33, ] ``` ruff_python_parser__lexer__tests__escape_unicode_name.snap000064400000000000000000000002521046102023000352030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ String 0..14 (flags = DOUBLE_QUOTES), Newline 14..14, ] ``` ruff_python_parser__lexer__tests__fstring.snap000064400000000000000000000012121046102023000327060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..9 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 9..10, Name 10..13, Rbrace 13..14, FStringMiddle 14..27 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 27..28, Name 28..31, Rbrace 31..32, FStringMiddle 32..35 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 35..36, Name 36..41, Rbrace 41..42, FStringMiddle 42..44 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 44..45 (flags = DOUBLE_QUOTES | F_STRING), Newline 45..45, ] ``` ruff_python_parser__lexer__tests__fstring_comments.snap000064400000000000000000000011201046102023000346110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..4 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 4..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), Lbrace 21..22, Comment 23..34, NonLogicalNewline 34..35, Name 39..40, NonLogicalNewline 40..41, Rbrace 41..42, FStringMiddle 42..59 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 59..62 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), Newline 62..62, ] ``` ruff_python_parser__lexer__tests__fstring_conversion.snap000064400000000000000000000013641046102023000351630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Name 3..4, Exclamation 4..5, Name 5..6, Rbrace 6..7, FStringMiddle 7..8 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 8..9, Name 9..10, Equal 10..11, Exclamation 11..12, Name 12..13, Rbrace 13..14, FStringMiddle 14..15 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 15..16, Name 16..17, Colon 17..18, FStringMiddle 18..23 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 23..24, FStringMiddle 24..32 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 32..33 (flags = DOUBLE_QUOTES | F_STRING), Newline 33..33, ] ``` ruff_python_parser__lexer__tests__fstring_escape.snap000064400000000000000000000010401046102023000342250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..3 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 3..4, Name 4..5, Colon 5..6, FStringMiddle 6..9 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 9..10, Name 10..11, Rbrace 11..12, Rbrace 12..13, FStringMiddle 13..24 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 24..25 (flags = DOUBLE_QUOTES | F_STRING), Newline 25..25, ] ``` ruff_python_parser__lexer__tests__fstring_escape_braces.snap000064400000000000000000000013561046102023000355560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), FStringMiddle 2..3 (flags = F_STRING), Lbrace 3..4, Name 4..7, Rbrace 7..8, FStringEnd 8..9 (flags = F_STRING), FStringStart 10..12 (flags = F_STRING), FStringMiddle 12..14 (flags = F_STRING), Lbrace 14..15, Name 15..18, Rbrace 18..19, FStringEnd 19..20 (flags = F_STRING), FStringStart 21..23 (flags = F_STRING), FStringMiddle 23..31 (flags = F_STRING), FStringEnd 31..32 (flags = F_STRING), FStringStart 33..35 (flags = F_STRING), FStringMiddle 35..44 (flags = F_STRING), FStringEnd 44..45 (flags = F_STRING), Newline 45..45, ] ``` ruff_python_parser__lexer__tests__fstring_escape_raw.snap000064400000000000000000000012251046102023000351030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..3 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringMiddle 3..4 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), Lbrace 4..5, Name 5..6, Colon 6..7, FStringMiddle 7..10 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), Lbrace 10..11, Name 11..12, Rbrace 12..13, Rbrace 13..14, FStringMiddle 14..25 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 25..26 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), Newline 26..26, ] ``` ruff_python_parser__lexer__tests__fstring_expression_multiline.snap000064400000000000000000000010721046102023000372530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..8 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 8..9, NonLogicalNewline 9..10, Name 14..15, NonLogicalNewline 15..16, Star 24..25, NonLogicalNewline 25..26, Name 38..39, NonLogicalNewline 39..40, Rbrace 40..41, FStringMiddle 41..48 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 48..49 (flags = DOUBLE_QUOTES | F_STRING), Newline 49..49, ] ``` ruff_python_parser__lexer__tests__fstring_multiline.snap000064400000000000000000000022021046102023000347700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..4 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 4..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 21..24 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringStart 25..29 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 29..46 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 46..49 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringStart 50..52 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 52..57 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 57..58, FStringStart 58..62 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 62..80 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), Lbrace 80..81, Name 81..82, Rbrace 82..83, FStringEnd 83..86 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | F_STRING), Rbrace 86..87, FStringMiddle 87..94 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 94..95 (flags = DOUBLE_QUOTES | F_STRING), Newline 95..95, ] ``` ruff_python_parser__lexer__tests__fstring_named_unicode.snap000064400000000000000000000004601046102023000355640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..28 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 28..29 (flags = DOUBLE_QUOTES | F_STRING), Newline 29..29, ] ``` ruff_python_parser__lexer__tests__fstring_named_unicode_raw.snap000064400000000000000000000007741046102023000364450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..3 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringMiddle 3..5 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), Lbrace 5..6, Name 6..12, Rbrace 12..13, FStringMiddle 13..20 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 20..21 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__fstring_nested.snap000064400000000000000000000025471046102023000342640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..6 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 6..7, FStringStart 7..9 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 9..13 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 13..14, Name 14..15, Plus 16..17, FStringStart 18..20 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 20..21, Name 21..24, Rbrace 24..25, FStringEnd 25..26 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 26..27, FStringEnd 27..28 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 28..29, FStringMiddle 29..33 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 33..34 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 35..37 (flags = F_STRING), FStringMiddle 37..41 (flags = F_STRING), Lbrace 41..42, FStringStart 42..44 (flags = F_STRING), FStringMiddle 44..47 (flags = F_STRING), FStringEnd 47..48 (flags = F_STRING), Rbrace 48..49, FStringMiddle 49..55 (flags = F_STRING), Lbrace 55..56, FStringStart 56..58 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 58..65 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 65..66 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 66..67, FStringEnd 67..68 (flags = F_STRING), Newline 68..68, ] ``` ruff_python_parser__lexer__tests__fstring_newline_format_spec.snap000064400000000000000000000025021046102023000370140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ NonLogicalNewline 0..1, FStringStart 1..3 (flags = F_STRING), FStringMiddle 3..5 (flags = F_STRING), Lbrace 5..6, NonLogicalNewline 6..7, Name 11..12, Colon 12..13, FStringMiddle 13..14 (flags = F_STRING), Newline 14..15, Rbrace 15..16, Name 16..18, String 18..19 (flags = UNCLOSED_STRING), Newline 19..20, FStringStart 20..22 (flags = F_STRING), FStringMiddle 22..24 (flags = F_STRING), Lbrace 24..25, NonLogicalNewline 25..26, Name 30..31, Colon 31..32, FStringMiddle 32..33 (flags = F_STRING), Newline 33..34, Indent 34..42, Name 42..43, Newline 43..44, Dedent 44..44, Rbrace 44..45, Name 45..47, String 47..48 (flags = UNCLOSED_STRING), Newline 48..49, ] ``` ## Errors ``` [ LexicalError { error: FStringError( NewlineInFormatSpec, ), location: 13..14, }, LexicalError { error: UnclosedStringError, location: 18..19, }, LexicalError { error: FStringError( NewlineInFormatSpec, ), location: 32..33, }, LexicalError { error: UnclosedStringError, location: 47..48, }, ] ``` ruff_python_parser__lexer__tests__fstring_parentheses.snap000064400000000000000000000027371046102023000353240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Rbrace 3..4, FStringEnd 4..5 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 6..8 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 8..12 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 12..13 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 14..16 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 16..17 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 17..18, Rbrace 18..19, FStringEnd 19..20 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 21..23 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 23..25 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 25..26, Rbrace 26..27, FStringMiddle 27..29 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 29..30 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 31..33 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 33..41 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 41..42 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 43..45 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 45..46 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 46..47, Rbrace 47..48, FStringMiddle 48..56 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 56..57, Rbrace 57..58, FStringMiddle 58..71 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 71..72 (flags = DOUBLE_QUOTES | F_STRING), Newline 72..72, ] ``` ruff_python_parser__lexer__tests__fstring_prefix.snap000064400000000000000000000032031046102023000342650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 2..3 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 4..6 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 6..7 (flags = DOUBLE_QUOTES | F_STRING), FStringStart 8..11 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 11..12 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringStart 13..16 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 16..17 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringStart 18..21 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringEnd 21..22 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringStart 23..26 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringEnd 26..27 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringStart 28..31 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 31..32 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringStart 33..36 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringEnd 36..37 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_LOWERCASE), FStringStart 38..41 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringEnd 41..42 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringStart 43..46 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), FStringEnd 46..47 (flags = DOUBLE_QUOTES | F_STRING | RAW_STRING_UPPERCASE), Newline 47..47, ] ``` ruff_python_parser__lexer__tests__fstring_single_quote_escape_mac_eol.snap000064400000000000000000000004261046102023000404710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: fstring_single_quote_escape_eol(MAC_EOL) --- ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), FStringMiddle 2..19 (flags = F_STRING), FStringEnd 19..20 (flags = F_STRING), Newline 20..20, ] ``` ruff_python_parser__lexer__tests__fstring_single_quote_escape_unix_eol.snap000064400000000000000000000004271046102023000407150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: fstring_single_quote_escape_eol(UNIX_EOL) --- ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), FStringMiddle 2..19 (flags = F_STRING), FStringEnd 19..20 (flags = F_STRING), Newline 20..20, ] ``` ruff_python_parser__lexer__tests__fstring_single_quote_escape_windows_eol.snap000064400000000000000000000004321046102023000414200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: fstring_single_quote_escape_eol(WINDOWS_EOL) --- ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), FStringMiddle 2..20 (flags = F_STRING), FStringEnd 20..21 (flags = F_STRING), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__fstring_with_format_spec.snap000064400000000000000000000027171046102023000363360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Name 3..6, Colon 6..7, Rbrace 7..8, FStringMiddle 8..9 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 9..10, Name 10..11, Equal 11..12, Exclamation 12..13, Name 13..14, Colon 14..15, FStringMiddle 15..18 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 18..19, FStringMiddle 19..20 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 20..21, Name 21..22, Colon 22..23, FStringMiddle 23..24 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 24..25, Name 25..26, Rbrace 26..27, FStringMiddle 27..28 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 28..29, FStringMiddle 29..30 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 30..31, String 31..33, Colon 33..34, FStringMiddle 34..36 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 36..37, Int 37..38, Colon 38..39, Lbrace 39..40, Int 40..41, Rbrace 41..42, Rbrace 42..43, Rbrace 43..44, FStringMiddle 44..45 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 45..46, Name 46..47, Colon 47..48, Lbrace 48..49, Lbrace 49..50, Int 50..51, Rbrace 51..52, Dot 52..53, Name 53..56, Lpar 56..57, Rpar 57..58, Rbrace 58..59, Rbrace 59..60, FStringEnd 60..61 (flags = DOUBLE_QUOTES | F_STRING), Newline 61..61, ] ``` ruff_python_parser__lexer__tests__fstring_with_ipy_escape_command.snap000064400000000000000000000006661046102023000376540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 2..6 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 6..7, Exclamation 7..8, Name 8..11, Rbrace 11..12, FStringMiddle 12..16 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 16..17 (flags = DOUBLE_QUOTES | F_STRING), Newline 17..17, ] ``` ruff_python_parser__lexer__tests__fstring_with_lambda_expression.snap000064400000000000000000000013021046102023000375200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Lambda 3..9, Name 10..11, Colon 11..12, Lbrace 12..13, Name 13..14, Rbrace 14..15, Rbrace 15..16, FStringEnd 16..17 (flags = DOUBLE_QUOTES | F_STRING), Newline 17..18, FStringStart 18..20 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 20..21, Lpar 21..22, Lambda 22..28, Name 29..30, Colon 30..31, Lbrace 31..32, Name 32..33, Rbrace 33..34, Rpar 34..35, Rbrace 35..36, FStringEnd 36..37 (flags = DOUBLE_QUOTES | F_STRING), Newline 37..37, ] ``` ruff_python_parser__lexer__tests__fstring_with_multiline_format_spec.snap000064400000000000000000000017721046102023000404200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..4 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 4..6 (flags = TRIPLE_QUOTED_STRING | F_STRING), Lbrace 6..7, NonLogicalNewline 7..8, Name 12..13, Colon 13..14, FStringMiddle 14..16 (flags = TRIPLE_QUOTED_STRING | F_STRING), Rbrace 16..17, FStringMiddle 17..19 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 19..22 (flags = TRIPLE_QUOTED_STRING | F_STRING), Newline 22..23, FStringStart 23..27 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringMiddle 27..29 (flags = TRIPLE_QUOTED_STRING | F_STRING), Lbrace 29..30, NonLogicalNewline 30..31, Name 35..36, Colon 36..37, FStringMiddle 37..61 (flags = TRIPLE_QUOTED_STRING | F_STRING), Rbrace 61..62, FStringMiddle 62..64 (flags = TRIPLE_QUOTED_STRING | F_STRING), FStringEnd 64..67 (flags = TRIPLE_QUOTED_STRING | F_STRING), Newline 67..68, ] ``` ruff_python_parser__lexer__tests__fstring_with_named_expression.snap000064400000000000000000000017151046102023000373740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 2..3, Name 3..4, Colon 4..5, FStringMiddle 5..8 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 8..9, FStringMiddle 9..10 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 10..11, Lpar 11..12, Name 12..13, ColonEqual 13..15, Int 15..17, Rpar 17..18, Rbrace 18..19, FStringMiddle 19..20 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 20..21, Name 21..22, Comma 22..23, Lbrace 23..24, Name 24..25, ColonEqual 25..27, Int 27..29, Rbrace 29..30, Rbrace 30..31, FStringMiddle 31..32 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 32..33, Lsqb 33..34, Name 34..35, ColonEqual 35..37, Int 37..39, Rsqb 39..40, Rbrace 40..41, FStringEnd 41..42 (flags = DOUBLE_QUOTES | F_STRING), Newline 42..42, ] ``` ruff_python_parser__lexer__tests__fstring_with_nul_char.snap000064400000000000000000000003731046102023000356230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ FStringStart 0..2 (flags = F_STRING), FStringMiddle 2..4 (flags = F_STRING), FStringEnd 4..5 (flags = F_STRING), Newline 5..5, ] ``` ruff_python_parser__lexer__tests__indentation_with_mac_eol.snap000064400000000000000000000005221046102023000362630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: indentation_with_eol(MAC_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..15, Return 15..21, Int 22..24, Newline 24..25, NonLogicalNewline 25..26, Dedent 26..26, ] ``` ruff_python_parser__lexer__tests__indentation_with_unix_eol.snap000064400000000000000000000005231046102023000365070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: indentation_with_eol(UNIX_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..11, Indent 11..15, Return 15..21, Int 22..24, Newline 24..25, NonLogicalNewline 25..26, Dedent 26..26, ] ``` ruff_python_parser__lexer__tests__indentation_with_windows_eol.snap000064400000000000000000000005261046102023000372210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: indentation_with_eol(WINDOWS_EOL) --- ## Tokens ``` [ Def 0..3, Name 4..7, Lpar 7..8, Rpar 8..9, Colon 9..10, Newline 10..12, Indent 12..16, Return 16..22, Int 23..25, Newline 25..27, NonLogicalNewline 27..29, Dedent 29..29, ] ``` ruff_python_parser__lexer__tests__invalid_leading_zero_big.snap000064400000000000000000000005021046102023000362240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ Unknown 0..85, Newline 85..85, ] ``` ## Errors ``` [ LexicalError { error: OtherError( "Invalid decimal integer literal", ), location: 0..85, }, ] ``` ruff_python_parser__lexer__tests__invalid_leading_zero_small.snap000064400000000000000000000004761046102023000366050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ Unknown 0..3, Newline 3..3, ] ``` ## Errors ``` [ LexicalError { error: OtherError( "Invalid decimal integer literal", ), location: 0..3, }, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command.snap000064400000000000000000000012411046102023000357440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ IpyEscapeCommand 0..4, Newline 4..5, IpyEscapeCommand 5..10, Newline 10..11, IpyEscapeCommand 11..24, Newline 24..25, IpyEscapeCommand 25..38, Newline 38..39, IpyEscapeCommand 39..65, Newline 65..66, IpyEscapeCommand 66..103, Newline 103..104, IpyEscapeCommand 104..149, Newline 149..150, IpyEscapeCommand 150..158, Newline 158..159, IpyEscapeCommand 159..167, Newline 167..168, IpyEscapeCommand 168..176, Newline 176..177, IpyEscapeCommand 177..180, Newline 180..180, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_assignment.snap000064400000000000000000000011561046102023000402010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ Name 0..3, Equal 4..5, IpyEscapeCommand 6..10, Newline 10..11, Name 11..14, Equal 15..16, IpyEscapeCommand 17..30, Newline 30..31, Name 31..34, Equal 35..36, IpyEscapeCommand 37..50, Newline 50..51, Name 51..54, Equal 55..56, IpyEscapeCommand 57..85, Newline 85..86, Name 86..89, Equal 90..91, IpyEscapeCommand 92..97, Newline 97..98, Name 98..102, Equal 103..104, IpyEscapeCommand 105..110, Newline 110..110, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_indentation.snap000064400000000000000000000004101046102023000403350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..13, IpyEscapeCommand 13..43, Newline 43..43, Dedent 43..43, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_mac_eol.snap000064400000000000000000000002771046102023000432340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_eol(MAC_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..24, Newline 24..24, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_unix_eol.snap000064400000000000000000000003001046102023000434420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_eol(UNIX_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..24, Newline 24..24, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_windows_eol.snap000064400000000000000000000003031046102023000441540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_eol(WINDOWS_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..25, Newline 25..25, ] ``` ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_with_mac_eol_and_eof.snap000064400000000000000000000003141046102023000457320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_with_eol_and_eof(MAC_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..14, Newline 14..14, ] ``` @PaxHeader00006440000000000000000000000254104610202300007765xustar00172 path=ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_with_unix_eol_and_eof.snap PaxHeaders/0000064400000000000000000000003151046102023000100750ustar00--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_with_eol_and_eof(UNIX_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..14, Newline 14..14, ] ``` @PaxHeader00006440000000000000000000000257104610202300007770xustar00175 path=ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_line_continuation_with_windows_eol_and_eof.snap PaxHeaders/1000064400000000000000000000003201046102023000100720ustar00--- source: crates/ruff_python_parser/src/lexer.rs expression: ipython_escape_command_line_continuation_with_eol_and_eof(WINDOWS_EOL) --- ## Tokens ``` [ IpyEscapeCommand 0..15, Newline 15..15, ] ``` ruff_python_parser__lexer__tests__ipython_help_end_escape_command.snap000064400000000000000000000016241046102023000376070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ IpyEscapeCommand 0..5, Newline 5..6, IpyEscapeCommand 6..15, Newline 15..16, IpyEscapeCommand 16..27, Newline 27..28, IpyEscapeCommand 28..34, Newline 34..35, IpyEscapeCommand 35..42, Newline 42..43, IpyEscapeCommand 43..50, Newline 50..51, IpyEscapeCommand 51..59, Newline 59..60, IpyEscapeCommand 60..68, Newline 68..69, IpyEscapeCommand 69..78, Newline 78..79, IpyEscapeCommand 79..92, Newline 92..93, IpyEscapeCommand 93..99, Newline 99..100, IpyEscapeCommand 100..104, Newline 104..105, IpyEscapeCommand 105..110, Newline 110..111, IpyEscapeCommand 111..117, Newline 117..118, IpyEscapeCommand 118..126, Newline 126..127, IpyEscapeCommand 127..132, Newline 132..132, ] ``` ruff_python_parser__lexer__tests__line_comment_empty.snap000064400000000000000000000002371046102023000351270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ Int 0..5, Comment 7..8, Newline 8..8, ] ``` ruff_python_parser__lexer__tests__line_comment_long.snap000064400000000000000000000002421046102023000347240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ Int 0..5, Comment 7..12, Newline 12..12, ] ``` ruff_python_parser__lexer__tests__line_comment_single_whitespace.snap000064400000000000000000000002371046102023000374660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ Int 0..5, Comment 7..9, Newline 9..9, ] ``` ruff_python_parser__lexer__tests__line_comment_whitespace.snap000064400000000000000000000002421046102023000361210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ Int 0..5, Comment 7..10, Newline 10..10, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_after_newline_mac_eol.snap000064400000000000000000000003671046102023000426630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof_after_newline(MAC_EOL) --- ## Tokens ``` [ Unknown 0..2, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 0..2, }, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_after_newline_unix_eol.snap000064400000000000000000000003701046102023000431000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof_after_newline(UNIX_EOL) --- ## Tokens ``` [ Unknown 0..2, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 0..2, }, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_after_newline_windows_eol.snap000064400000000000000000000003731046102023000436120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof_after_newline(WINDOWS_EOL) --- ## Tokens ``` [ Unknown 0..3, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 0..3, }, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_mac_eol.snap000064400000000000000000000004311046102023000377510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof(MAC_EOL) --- ## Tokens ``` [ Int 0..1, Comma 1..2, Unknown 2..5, Newline 5..5, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 2..5, }, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_unix_eol.snap000064400000000000000000000004321046102023000401750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof(UNIX_EOL) --- ## Tokens ``` [ Int 0..1, Comma 1..2, Unknown 2..5, Newline 5..5, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 2..5, }, ] ``` ruff_python_parser__lexer__tests__line_continuation_at_eof_windows_eol.snap000064400000000000000000000004351046102023000407070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: line_continuation_at_eof(WINDOWS_EOL) --- ## Tokens ``` [ Int 0..1, Comma 1..2, Unknown 2..6, Newline 6..6, ] ``` ## Errors ``` [ LexicalError { error: Eof, location: 2..6, }, ] ``` ruff_python_parser__lexer__tests__logical_newline_line_comment.snap000064400000000000000000000003131046102023000371170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ Comment 0..6, NonLogicalNewline 6..7, Comment 7..13, NonLogicalNewline 13..14, ] ``` ruff_python_parser__lexer__tests__match_softkeyword_in_notebook.snap000064400000000000000000000005611046102023000373620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_jupyter_source(source) --- ## Tokens ``` [ Match 0..5, Name 6..9, Colon 9..10, Newline 10..11, Indent 11..15, Case 15..19, Name 20..23, Colon 23..24, Newline 24..25, Indent 25..33, Pass 33..37, Newline 37..37, Dedent 37..37, Dedent 37..37, ] ``` ruff_python_parser__lexer__tests__multiple_backslash_continuation.snap000064400000000000000000000004301046102023000376730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(&source) --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..13, Int 13..14, Newline 14..15, Int 55..56, Newline 56..57, Dedent 57..57, ] ``` ruff_python_parser__lexer__tests__nested_t_and_fstring.snap000064400000000000000000000026201046102023000354210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..6 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 6..7, FStringStart 7..9 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 9..13 (flags = DOUBLE_QUOTES | F_STRING), Lbrace 13..14, Name 14..15, Plus 16..17, TStringStart 18..20 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 20..21, Name 21..24, Rbrace 24..25, TStringEnd 25..26 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 26..27, FStringEnd 27..28 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 28..29, TStringMiddle 29..33 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 33..34 (flags = DOUBLE_QUOTES | T_STRING), FStringStart 35..37 (flags = F_STRING), FStringMiddle 37..41 (flags = F_STRING), Lbrace 41..42, TStringStart 42..44 (flags = T_STRING), TStringMiddle 44..47 (flags = T_STRING), TStringEnd 47..48 (flags = T_STRING), Exclamation 48..49, Name 49..50, Rbrace 50..51, FStringMiddle 51..57 (flags = F_STRING), Lbrace 57..58, FStringStart 58..60 (flags = DOUBLE_QUOTES | F_STRING), FStringMiddle 60..67 (flags = DOUBLE_QUOTES | F_STRING), FStringEnd 67..68 (flags = DOUBLE_QUOTES | F_STRING), Rbrace 68..69, FStringEnd 69..70 (flags = F_STRING), Newline 70..70, ] ``` ruff_python_parser__lexer__tests__newline_in_brackets_mac_eol.snap000064400000000000000000000013211046102023000367170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: newline_in_brackets_eol(MAC_EOL) --- ## Tokens ``` [ Name 0..1, Equal 2..3, Lsqb 4..5, NonLogicalNewline 5..6, NonLogicalNewline 6..7, Int 11..12, Comma 12..13, Int 13..14, NonLogicalNewline 14..15, Comma 15..16, Lpar 16..17, Int 17..18, Comma 18..19, NonLogicalNewline 19..20, Int 20..21, Comma 21..22, NonLogicalNewline 22..23, Rpar 23..24, Comma 24..25, Lbrace 26..27, NonLogicalNewline 27..28, Int 28..29, Comma 29..30, NonLogicalNewline 30..31, Int 31..32, Comma 32..33, Int 35..36, Rbrace 36..37, Rsqb 37..38, Newline 38..39, ] ``` ruff_python_parser__lexer__tests__newline_in_brackets_unix_eol.snap000064400000000000000000000013221046102023000371430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: newline_in_brackets_eol(UNIX_EOL) --- ## Tokens ``` [ Name 0..1, Equal 2..3, Lsqb 4..5, NonLogicalNewline 5..6, NonLogicalNewline 6..7, Int 11..12, Comma 12..13, Int 13..14, NonLogicalNewline 14..15, Comma 15..16, Lpar 16..17, Int 17..18, Comma 18..19, NonLogicalNewline 19..20, Int 20..21, Comma 21..22, NonLogicalNewline 22..23, Rpar 23..24, Comma 24..25, Lbrace 26..27, NonLogicalNewline 27..28, Int 28..29, Comma 29..30, NonLogicalNewline 30..31, Int 31..32, Comma 32..33, Int 35..36, Rbrace 36..37, Rsqb 37..38, Newline 38..39, ] ``` ruff_python_parser__lexer__tests__newline_in_brackets_windows_eol.snap000064400000000000000000000013251046102023000376550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: newline_in_brackets_eol(WINDOWS_EOL) --- ## Tokens ``` [ Name 0..1, Equal 2..3, Lsqb 4..5, NonLogicalNewline 5..7, NonLogicalNewline 7..9, Int 13..14, Comma 14..15, Int 15..16, NonLogicalNewline 16..18, Comma 18..19, Lpar 19..20, Int 20..21, Comma 21..22, NonLogicalNewline 22..24, Int 24..25, Comma 25..26, NonLogicalNewline 26..28, Rpar 28..29, Comma 29..30, Lbrace 31..32, NonLogicalNewline 32..34, Int 34..35, Comma 35..36, NonLogicalNewline 36..38, Int 38..39, Comma 39..40, Int 43..44, Rbrace 44..45, Rsqb 45..46, Newline 46..48, ] ``` ruff_python_parser__lexer__tests__non_logical_newline_in_string_continuation.snap000064400000000000000000000005751046102023000421200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ Lpar 0..1, NonLogicalNewline 1..2, String 6..9, NonLogicalNewline 9..10, String 14..17, NonLogicalNewline 17..18, NonLogicalNewline 18..19, String 23..26, String 33..36, NonLogicalNewline 36..37, Rpar 37..38, Newline 38..38, ] ``` ruff_python_parser__lexer__tests__numbers.snap000064400000000000000000000005551046102023000327160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ Int 0..4, Int 5..9, Int 10..16, Int 17..18, Int 19..22, Int 23..36, Float 37..40, Float 41..45, Float 46..51, Complex 52..54, Complex 55..59, Int 60..63, Int 64..82, Int 83..117, Newline 117..117, ] ``` ruff_python_parser__lexer__tests__operators.snap000064400000000000000000000003501046102023000332520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ DoubleSlash 0..2, DoubleSlash 2..4, DoubleSlashEqual 4..7, Slash 7..8, Slash 9..10, Newline 10..10, ] ``` ruff_python_parser__lexer__tests__string.snap000064400000000000000000000005671046102023000325540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ String 0..8 (flags = DOUBLE_QUOTES), String 9..17, String 18..26, String 27..33 (flags = DOUBLE_QUOTES), String 34..42, String 43..47, String 48..56 (flags = RAW_STRING_LOWERCASE), String 57..63, String 64..73, Newline 73..73, ] ``` ruff_python_parser__lexer__tests__string_continuation_with_mac_eol.snap000064400000000000000000000002751046102023000400540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: string_continuation_with_eol(MAC_EOL) --- ## Tokens ``` [ String 0..10 (flags = DOUBLE_QUOTES), Newline 10..10, ] ``` ruff_python_parser__lexer__tests__string_continuation_with_unix_eol.snap000064400000000000000000000002761046102023000403000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: string_continuation_with_eol(UNIX_EOL) --- ## Tokens ``` [ String 0..10 (flags = DOUBLE_QUOTES), Newline 10..10, ] ``` ruff_python_parser__lexer__tests__string_continuation_with_windows_eol.snap000064400000000000000000000003011046102023000407740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: string_continuation_with_eol(WINDOWS_EOL) --- ## Tokens ``` [ String 0..11 (flags = DOUBLE_QUOTES), Newline 11..11, ] ``` ruff_python_parser__lexer__tests__tet_too_low_dedent.snap000064400000000000000000000006261046102023000351230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ If 0..2, True 3..7, Colon 7..8, Newline 8..9, Indent 9..13, Pass 13..17, Newline 17..18, Unknown 18..20, Pass 20..24, Newline 24..24, ] ``` ## Errors ``` [ LexicalError { error: IndentationError, location: 18..20, }, ] ``` ruff_python_parser__lexer__tests__triple_quoted_mac_eol.snap000064400000000000000000000003111046102023000355700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: triple_quoted_eol(MAC_EOL) --- ## Tokens ``` [ String 0..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__triple_quoted_unix_eol.snap000064400000000000000000000003121046102023000360140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: triple_quoted_eol(UNIX_EOL) --- ## Tokens ``` [ String 0..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__triple_quoted_windows_eol.snap000064400000000000000000000003151046102023000365260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: triple_quoted_eol(WINDOWS_EOL) --- ## Tokens ``` [ String 0..23 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING), Newline 23..23, ] ``` ruff_python_parser__lexer__tests__tstring.snap000064400000000000000000000012121046102023000327240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..9 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 9..10, Name 10..13, Rbrace 13..14, TStringMiddle 14..27 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 27..28, Name 28..31, Rbrace 31..32, TStringMiddle 32..35 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 35..36, Name 36..41, Rbrace 41..42, TStringMiddle 42..44 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 44..45 (flags = DOUBLE_QUOTES | T_STRING), Newline 45..45, ] ``` ruff_python_parser__lexer__tests__tstring_comments.snap000064400000000000000000000011201046102023000346270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..4 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 4..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), Lbrace 21..22, Comment 23..34, NonLogicalNewline 34..35, Name 39..40, NonLogicalNewline 40..41, Rbrace 41..42, TStringMiddle 42..59 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 59..62 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), Newline 62..62, ] ``` ruff_python_parser__lexer__tests__tstring_conversion.snap000064400000000000000000000013641046102023000352010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 2..3, Name 3..4, Exclamation 4..5, Name 5..6, Rbrace 6..7, TStringMiddle 7..8 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 8..9, Name 9..10, Equal 10..11, Exclamation 11..12, Name 12..13, Rbrace 13..14, TStringMiddle 14..15 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 15..16, Name 16..17, Colon 17..18, TStringMiddle 18..23 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 23..24, TStringMiddle 24..32 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 32..33 (flags = DOUBLE_QUOTES | T_STRING), Newline 33..33, ] ``` ruff_python_parser__lexer__tests__tstring_escape.snap000064400000000000000000000010401046102023000342430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..3 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 3..4, Name 4..5, Colon 5..6, TStringMiddle 6..9 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 9..10, Name 10..11, Rbrace 11..12, Rbrace 12..13, TStringMiddle 13..24 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 24..25 (flags = DOUBLE_QUOTES | T_STRING), Newline 25..25, ] ``` ruff_python_parser__lexer__tests__tstring_escape_braces.snap000064400000000000000000000013561046102023000355740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = T_STRING), TStringMiddle 2..3 (flags = T_STRING), Lbrace 3..4, Name 4..7, Rbrace 7..8, TStringEnd 8..9 (flags = T_STRING), TStringStart 10..12 (flags = T_STRING), TStringMiddle 12..14 (flags = T_STRING), Lbrace 14..15, Name 15..18, Rbrace 18..19, TStringEnd 19..20 (flags = T_STRING), TStringStart 21..23 (flags = T_STRING), TStringMiddle 23..31 (flags = T_STRING), TStringEnd 31..32 (flags = T_STRING), TStringStart 33..35 (flags = T_STRING), TStringMiddle 35..44 (flags = T_STRING), TStringEnd 44..45 (flags = T_STRING), Newline 45..45, ] ``` ruff_python_parser__lexer__tests__tstring_escape_raw.snap000064400000000000000000000012251046102023000351210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..3 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringMiddle 3..4 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), Lbrace 4..5, Name 5..6, Colon 6..7, TStringMiddle 7..10 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), Lbrace 10..11, Name 11..12, Rbrace 12..13, Rbrace 13..14, TStringMiddle 14..25 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 25..26 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), Newline 26..26, ] ``` ruff_python_parser__lexer__tests__tstring_expression_multiline.snap000064400000000000000000000010721046102023000372710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..8 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 8..9, NonLogicalNewline 9..10, Name 14..15, NonLogicalNewline 15..16, Star 24..25, NonLogicalNewline 25..26, Name 38..39, NonLogicalNewline 39..40, Rbrace 40..41, TStringMiddle 41..48 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 48..49 (flags = DOUBLE_QUOTES | T_STRING), Newline 49..49, ] ``` ruff_python_parser__lexer__tests__tstring_multiline.snap000064400000000000000000000022021046102023000350060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..4 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 4..21 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 21..24 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringStart 25..29 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 29..46 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 46..49 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringStart 50..52 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 52..57 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 57..58, TStringStart 58..62 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 62..80 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), Lbrace 80..81, Name 81..82, Rbrace 82..83, TStringEnd 83..86 (flags = DOUBLE_QUOTES | TRIPLE_QUOTED_STRING | T_STRING), Rbrace 86..87, TStringMiddle 87..94 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 94..95 (flags = DOUBLE_QUOTES | T_STRING), Newline 95..95, ] ``` ruff_python_parser__lexer__tests__tstring_named_unicode.snap000064400000000000000000000004601046102023000356020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..28 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 28..29 (flags = DOUBLE_QUOTES | T_STRING), Newline 29..29, ] ``` ruff_python_parser__lexer__tests__tstring_named_unicode_raw.snap000064400000000000000000000007741046102023000364630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..3 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringMiddle 3..5 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), Lbrace 5..6, Name 6..12, Rbrace 12..13, TStringMiddle 13..20 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 20..21 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__tstring_nested.snap000064400000000000000000000025471046102023000343020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..6 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 6..7, TStringStart 7..9 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 9..13 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 13..14, Name 14..15, Plus 16..17, TStringStart 18..20 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 20..21, Name 21..24, Rbrace 24..25, TStringEnd 25..26 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 26..27, TStringEnd 27..28 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 28..29, TStringMiddle 29..33 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 33..34 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 35..37 (flags = T_STRING), TStringMiddle 37..41 (flags = T_STRING), Lbrace 41..42, TStringStart 42..44 (flags = T_STRING), TStringMiddle 44..47 (flags = T_STRING), TStringEnd 47..48 (flags = T_STRING), Rbrace 48..49, TStringMiddle 49..55 (flags = T_STRING), Lbrace 55..56, TStringStart 56..58 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 58..65 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 65..66 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 66..67, TStringEnd 67..68 (flags = T_STRING), Newline 68..68, ] ``` ruff_python_parser__lexer__tests__tstring_newline_format_spec.snap000064400000000000000000000025021046102023000370320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: "lex_invalid(source, Mode::Module)" --- ## Tokens ``` [ NonLogicalNewline 0..1, TStringStart 1..3 (flags = T_STRING), TStringMiddle 3..5 (flags = T_STRING), Lbrace 5..6, NonLogicalNewline 6..7, Name 11..12, Colon 12..13, TStringMiddle 13..14 (flags = T_STRING), Newline 14..15, Rbrace 15..16, Name 16..18, String 18..19 (flags = UNCLOSED_STRING), Newline 19..20, TStringStart 20..22 (flags = T_STRING), TStringMiddle 22..24 (flags = T_STRING), Lbrace 24..25, NonLogicalNewline 25..26, Name 30..31, Colon 31..32, TStringMiddle 32..33 (flags = T_STRING), Newline 33..34, Indent 34..42, Name 42..43, Newline 43..44, Dedent 44..44, Rbrace 44..45, Name 45..47, String 47..48 (flags = UNCLOSED_STRING), Newline 48..49, ] ``` ## Errors ``` [ LexicalError { error: TStringError( NewlineInFormatSpec, ), location: 13..14, }, LexicalError { error: UnclosedStringError, location: 18..19, }, LexicalError { error: TStringError( NewlineInFormatSpec, ), location: 32..33, }, LexicalError { error: UnclosedStringError, location: 47..48, }, ] ``` ruff_python_parser__lexer__tests__tstring_parentheses.snap000064400000000000000000000027371046102023000353420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 2..3, Rbrace 3..4, TStringEnd 4..5 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 6..8 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 8..12 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 12..13 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 14..16 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 16..17 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 17..18, Rbrace 18..19, TStringEnd 19..20 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 21..23 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 23..25 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 25..26, Rbrace 26..27, TStringMiddle 27..29 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 29..30 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 31..33 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 33..41 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 41..42 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 43..45 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 45..46 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 46..47, Rbrace 47..48, TStringMiddle 48..56 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 56..57, Rbrace 57..58, TStringMiddle 58..71 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 71..72 (flags = DOUBLE_QUOTES | T_STRING), Newline 72..72, ] ``` ruff_python_parser__lexer__tests__tstring_prefix.snap000064400000000000000000000032031046102023000343030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 2..3 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 4..6 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 6..7 (flags = DOUBLE_QUOTES | T_STRING), TStringStart 8..11 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 11..12 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringStart 13..16 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 16..17 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringStart 18..21 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringEnd 21..22 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringStart 23..26 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringEnd 26..27 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringStart 28..31 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 31..32 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringStart 33..36 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringEnd 36..37 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_LOWERCASE), TStringStart 38..41 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringEnd 41..42 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringStart 43..46 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), TStringEnd 46..47 (flags = DOUBLE_QUOTES | T_STRING | RAW_STRING_UPPERCASE), Newline 47..47, ] ``` ruff_python_parser__lexer__tests__tstring_single_quote_escape_mac_eol.snap000064400000000000000000000004261046102023000405070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: tstring_single_quote_escape_eol(MAC_EOL) --- ## Tokens ``` [ TStringStart 0..2 (flags = T_STRING), TStringMiddle 2..19 (flags = T_STRING), TStringEnd 19..20 (flags = T_STRING), Newline 20..20, ] ``` ruff_python_parser__lexer__tests__tstring_single_quote_escape_unix_eol.snap000064400000000000000000000004271046102023000407330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: tstring_single_quote_escape_eol(UNIX_EOL) --- ## Tokens ``` [ TStringStart 0..2 (flags = T_STRING), TStringMiddle 2..19 (flags = T_STRING), TStringEnd 19..20 (flags = T_STRING), Newline 20..20, ] ``` ruff_python_parser__lexer__tests__tstring_single_quote_escape_windows_eol.snap000064400000000000000000000004321046102023000414360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: tstring_single_quote_escape_eol(WINDOWS_EOL) --- ## Tokens ``` [ TStringStart 0..2 (flags = T_STRING), TStringMiddle 2..20 (flags = T_STRING), TStringEnd 20..21 (flags = T_STRING), Newline 21..21, ] ``` ruff_python_parser__lexer__tests__tstring_with_format_spec.snap000064400000000000000000000027171046102023000363540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 2..3, Name 3..6, Colon 6..7, Rbrace 7..8, TStringMiddle 8..9 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 9..10, Name 10..11, Equal 11..12, Exclamation 12..13, Name 13..14, Colon 14..15, TStringMiddle 15..18 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 18..19, TStringMiddle 19..20 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 20..21, Name 21..22, Colon 22..23, TStringMiddle 23..24 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 24..25, Name 25..26, Rbrace 26..27, TStringMiddle 27..28 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 28..29, TStringMiddle 29..30 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 30..31, String 31..33, Colon 33..34, TStringMiddle 34..36 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 36..37, Int 37..38, Colon 38..39, Lbrace 39..40, Int 40..41, Rbrace 41..42, Rbrace 42..43, Rbrace 43..44, TStringMiddle 44..45 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 45..46, Name 46..47, Colon 47..48, Lbrace 48..49, Lbrace 49..50, Int 50..51, Rbrace 51..52, Dot 52..53, Name 53..56, Lpar 56..57, Rpar 57..58, Rbrace 58..59, Rbrace 59..60, TStringEnd 60..61 (flags = DOUBLE_QUOTES | T_STRING), Newline 61..61, ] ``` ruff_python_parser__lexer__tests__tstring_with_ipy_escape_command.snap000064400000000000000000000006661046102023000376720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), TStringMiddle 2..6 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 6..7, Exclamation 7..8, Name 8..11, Rbrace 11..12, TStringMiddle 12..16 (flags = DOUBLE_QUOTES | T_STRING), TStringEnd 16..17 (flags = DOUBLE_QUOTES | T_STRING), Newline 17..17, ] ``` ruff_python_parser__lexer__tests__tstring_with_lambda_expression.snap000064400000000000000000000013021046102023000375360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 2..3, Lambda 3..9, Name 10..11, Colon 11..12, Lbrace 12..13, Name 13..14, Rbrace 14..15, Rbrace 15..16, TStringEnd 16..17 (flags = DOUBLE_QUOTES | T_STRING), Newline 17..18, TStringStart 18..20 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 20..21, Lpar 21..22, Lambda 22..28, Name 29..30, Colon 30..31, Lbrace 31..32, Name 32..33, Rbrace 33..34, Rpar 34..35, Rbrace 35..36, TStringEnd 36..37 (flags = DOUBLE_QUOTES | T_STRING), Newline 37..37, ] ``` ruff_python_parser__lexer__tests__tstring_with_multiline_format_spec.snap000064400000000000000000000017721046102023000404360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..4 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 4..6 (flags = TRIPLE_QUOTED_STRING | T_STRING), Lbrace 6..7, NonLogicalNewline 7..8, Name 12..13, Colon 13..14, TStringMiddle 14..16 (flags = TRIPLE_QUOTED_STRING | T_STRING), Rbrace 16..17, TStringMiddle 17..19 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 19..22 (flags = TRIPLE_QUOTED_STRING | T_STRING), Newline 22..23, TStringStart 23..27 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringMiddle 27..29 (flags = TRIPLE_QUOTED_STRING | T_STRING), Lbrace 29..30, NonLogicalNewline 30..31, Name 35..36, Colon 36..37, TStringMiddle 37..61 (flags = TRIPLE_QUOTED_STRING | T_STRING), Rbrace 61..62, TStringMiddle 62..64 (flags = TRIPLE_QUOTED_STRING | T_STRING), TStringEnd 64..67 (flags = TRIPLE_QUOTED_STRING | T_STRING), Newline 67..68, ] ``` ruff_python_parser__lexer__tests__tstring_with_named_expression.snap000064400000000000000000000017151046102023000374120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 2..3, Name 3..4, Colon 4..5, TStringMiddle 5..8 (flags = DOUBLE_QUOTES | T_STRING), Rbrace 8..9, TStringMiddle 9..10 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 10..11, Lpar 11..12, Name 12..13, ColonEqual 13..15, Int 15..17, Rpar 17..18, Rbrace 18..19, TStringMiddle 19..20 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 20..21, Name 21..22, Comma 22..23, Lbrace 23..24, Name 24..25, ColonEqual 25..27, Int 27..29, Rbrace 29..30, Rbrace 30..31, TStringMiddle 31..32 (flags = DOUBLE_QUOTES | T_STRING), Lbrace 32..33, Lsqb 33..34, Name 34..35, ColonEqual 35..37, Int 37..39, Rsqb 39..40, Rbrace 40..41, TStringEnd 41..42 (flags = DOUBLE_QUOTES | T_STRING), Newline 42..42, ] ``` ruff_python_parser__lexer__tests__tstring_with_nul_char.snap000064400000000000000000000003731046102023000356410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/lexer.rs expression: lex_source(source) --- ## Tokens ``` [ TStringStart 0..2 (flags = T_STRING), TStringMiddle 2..4 (flags = T_STRING), TStringEnd 4..5 (flags = T_STRING), Newline 5..5, ] ``` ruff_python_parser__string__tests__backspace_alias.snap000064400000000000000000000020441046102023000345120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..15, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..15, node_index: NodeIndex(None), value: "\u{8}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__bell_alias.snap000064400000000000000000000020411046102023000335110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..9, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..9, node_index: NodeIndex(None), value: "\u{7}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__carriage_return_alias.snap000064400000000000000000000020411046102023000357470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..21, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..21, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..21, node_index: NodeIndex(None), value: "\r", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap000064400000000000000000000020451046102023000427430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..45, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..45, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..45, node_index: NodeIndex(None), value: "\u{89}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__delete_alias.snap000064400000000000000000000020451046102023000340410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..12, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..12, node_index: NodeIndex(None), value: "\u{7f}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__dont_panic_on_8_in_octal_escape.snap000064400000000000000000000025311046102023000376570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..16, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("bold"), ctx: Store, }, ), ], value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 7..16, value: StringLiteralValue { inner: Single( StringLiteral { range: 7..16, node_index: NodeIndex(None), value: "\u{3}8[1m", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__double_quoted_byte.snap000064400000000000000000000263221046102023000353100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..738, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..738, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..738, node_index: NodeIndex(None), 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, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__escape_alias.snap000064400000000000000000000020451046102023000340370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..12, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..12, node_index: NodeIndex(None), value: "\u{1b}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__escape_char_in_byte_literal.snap000064400000000000000000000027231046102023000371130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..13, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..13, node_index: NodeIndex(None), value: [ 111, 109, 107, 109, 111, 107, 92, 88, 97, 97, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__escape_octet.snap000064400000000000000000000024041046102023000340630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..14, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..14, node_index: NodeIndex(None), value: [ 35, 97, 4, 83, 52, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__form_feed_alias.snap000064400000000000000000000020441046102023000345240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..15, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..15, node_index: NodeIndex(None), value: "\u{c}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_constant_range.snap000064400000000000000000000107641046102023000361760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..22, value: FStringValue { inner: Single( FString( FString { range: 0..22, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..5, node_index: NodeIndex(None), value: "aaa", }, ), Interpolation( InterpolatedElement { range: 5..10, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("bbb"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 10..13, node_index: NodeIndex(None), value: "ccc", }, ), Interpolation( InterpolatedElement { range: 13..18, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("ddd"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 18..21, node_index: NodeIndex(None), value: "eee", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_escaped_character.snap000064400000000000000000000051541046102023000366060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..8, value: FStringValue { inner: Single( FString( FString { range: 0..8, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..4, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 4..7, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_escaped_newline.snap000064400000000000000000000051541046102023000363130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..8, value: FStringValue { inner: Single( FString( FString { range: 0..8, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..4, node_index: NodeIndex(None), value: "\n", }, ), Interpolation( InterpolatedElement { range: 4..7, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_line_continuation.snap000064400000000000000000000053261046102023000367100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..9, value: FStringValue { inner: Single( FString( FString { range: 0..9, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 3..5, node_index: NodeIndex(None), value: "\\\n", }, ), Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap000064400000000000000000000051231046102023000406730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..10, value: FStringValue { inner: Single( FString( FString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap000064400000000000000000000115501046102023000417160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..38, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..38, value: FStringValue { inner: Single( FString( FString { range: 0..38, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..6, node_index: NodeIndex(None), value: "mix ", }, ), Interpolation( InterpolatedElement { range: 6..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 7..11, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 13..28, node_index: NodeIndex(None), value: " with text and ", }, ), Interpolation( InterpolatedElement { range: 28..37, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 29..35, id: Name("second"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "second", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap000064400000000000000000000071321046102023000412530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..14, value: FStringValue { inner: Single( FString( FString { range: 0..14, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 9..12, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 9..12, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__fstring_unescaped_newline.snap000064400000000000000000000051561046102023000366600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..11, value: FStringValue { inner: Single( FString( FString { range: 0..11, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 4..5, node_index: NodeIndex(None), value: "\n", }, ), Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__hts_alias.snap000064400000000000000000000020421046102023000333720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..9, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..9, node_index: NodeIndex(None), value: "\u{88}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__invalid_byte_literal_error.snap000064400000000000000000000002451046102023000370240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: error --- ParseError { error: Lexical( InvalidByteLiteral, ), location: 6..10, } ruff_python_parser__string__tests__invalid_unicode_literal.snap000064400000000000000000000002361046102023000362760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: error --- ParseError { error: Lexical( UnicodeError, ), location: 4..6, } ruff_python_parser__string__tests__invalid_unicode_name_error.snap000064400000000000000000000002371046102023000367740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: error --- ParseError { error: Lexical( UnicodeError, ), location: 4..11, } ruff_python_parser__string__tests__missing_unicode_lbrace_error.snap000064400000000000000000000002461046102023000373270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: error --- ParseError { error: Lexical( MissingUnicodeLbrace, ), location: 3..3, } ruff_python_parser__string__tests__missing_unicode_rbrace_error.snap000064400000000000000000000002461046102023000373350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: error --- ParseError { error: Lexical( MissingUnicodeRbrace, ), location: 9..9, } ruff_python_parser__string__tests__parse_empty_fstring.snap000064400000000000000000000021631046102023000355130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..3, value: FStringValue { inner: Single( FString( FString { range: 0..3, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_empty_tstring.snap000064400000000000000000000020031046102023000355220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..3, value: TStringValue { inner: Single( TString { range: 0..3, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_f_string_concat_1.snap000064400000000000000000000046341046102023000362100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..17, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 9..17, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 11..16, node_index: NodeIndex(None), value: "world", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_f_string_concat_2.snap000064400000000000000000000046341046102023000362110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..17, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 9..17, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 11..16, node_index: NodeIndex(None), value: "world", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_f_string_concat_3.snap000064400000000000000000000112251046102023000362040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..22, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 9..22, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 11..16, node_index: NodeIndex(None), value: "world", }, ), Interpolation( InterpolatedElement { range: 16..21, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 17..20, value: StringLiteralValue { inner: Single( StringLiteral { range: 17..20, node_index: NodeIndex(None), value: "!", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_f_string_concat_4.snap000064400000000000000000000125331046102023000362100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..31, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..31, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 9..22, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 11..16, node_index: NodeIndex(None), value: "world", }, ), Interpolation( InterpolatedElement { range: 16..21, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 17..20, value: StringLiteralValue { inner: Single( StringLiteral { range: 17..20, node_index: NodeIndex(None), value: "!", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 23..31, node_index: NodeIndex(None), value: "again!", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_f_t_string_concat_1_error.snap000064400000000000000000000003221046102023000377320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..18, } ruff_python_parser__string__tests__parse_f_t_string_concat_2_error.snap000064400000000000000000000003221046102023000377330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..22, } ruff_python_parser__string__tests__parse_fstring.snap000064400000000000000000000072501046102023000342770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..18, value: FStringValue { inner: Single( FString( FString { range: 0..18, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..5, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("a"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Interpolation( InterpolatedElement { range: 5..10, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("b"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 10..17, node_index: NodeIndex(None), value: "{foo}", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_equals.snap000064400000000000000000000073271046102023000356560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..13, value: FStringValue { inner: Single( FString( FString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 3..11, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3..5, value: Int( 42, ), }, ), ops: [ Eq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..11, value: Int( 42, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap000064400000000000000000000162371046102023000431530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..16, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..16, value: FStringValue { inner: Single( FString( FString { range: 0..16, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..15, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..14, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..14, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 8..13, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 8..10, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 11..13, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "", }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_nested_spec.snap000064400000000000000000000100641046102023000366500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..15, value: FStringValue { inner: Single( FString( FString { range: 0..15, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..14, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 8..12, id: Name("spec"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap000064400000000000000000000125751046102023000402470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..13, value: FStringValue { inner: Single( FString( FString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..11, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 8..10, value: StringLiteralValue { inner: Single( StringLiteral { range: 8..10, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_not_equals.snap000064400000000000000000000073261046102023000365350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..11, value: FStringValue { inner: Single( FString( FString { range: 0..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..10, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 3..9, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3..4, value: Int( 1, ), }, ), ops: [ NotEq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 2, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap000064400000000000000000000063301046102023000375310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..13, value: FStringValue { inner: Single( FString( FString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..11, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 7..11, node_index: NodeIndex(None), value: "spec", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap000064400000000000000000000051201046102023000403130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..10, value: FStringValue { inner: Single( FString( FString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " =", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap000064400000000000000000000051201046102023000411730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..10, value: FStringValue { inner: Single( FString( FString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: "= ", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_fstring_yield_expr.snap000064400000000000000000000042131046102023000365170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..10, value: FStringValue { inner: Single( FString( FString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Yield( ExprYield { node_index: NodeIndex(None), range: 3..8, value: None, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_string_concat.snap000064400000000000000000000037251046102023000354630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..16, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..16, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 9..16, node_index: NodeIndex(None), value: "world", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "Hello world", }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap000064400000000000000000000020551046102023000411460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..20, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..20, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..20, node_index: NodeIndex(None), value: "Hello, world!", flags: StringLiteralFlags { quote_style: Single, prefix: Unicode, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_t_string_concat_1_error.snap000064400000000000000000000003221046102023000374250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..17, } ruff_python_parser__string__tests__parse_t_string_concat_2_error.snap000064400000000000000000000003221046102023000374260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..17, } ruff_python_parser__string__tests__parse_t_string_concat_3_error.snap000064400000000000000000000003221046102023000374270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..22, } ruff_python_parser__string__tests__parse_t_string_concat_4_error.snap000064400000000000000000000003221046102023000374300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..31, } ruff_python_parser__string__tests__parse_tstring.snap000064400000000000000000000066201046102023000343150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..18, value: TStringValue { inner: Single( TString { range: 0..18, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..5, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("a"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Interpolation( InterpolatedElement { range: 5..10, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("b"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 10..17, node_index: NodeIndex(None), value: "{foo}", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_equals.snap000064400000000000000000000067131046102023000356720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..13, value: TStringValue { inner: Single( TString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 3..11, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3..5, value: Int( 42, ), }, ), ops: [ Eq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..11, value: Int( 42, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_nested_concatenation_string_spec.snap000064400000000000000000000154231046102023000431650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..16, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..16, value: TStringValue { inner: Single( TString { range: 0..16, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..15, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..14, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..14, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 8..13, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 8..10, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 11..13, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "", }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_nested_spec.snap000064400000000000000000000074341046102023000366750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..15, value: TStringValue { inner: Single( TString { range: 0..15, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..14, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 8..12, id: Name("spec"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_nested_string_spec.snap000064400000000000000000000120611046102023000402530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..13, value: TStringValue { inner: Single( TString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..11, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 8..10, value: StringLiteralValue { inner: Single( StringLiteral { range: 8..10, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_not_equals.snap000064400000000000000000000067121046102023000365510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..11, value: TStringValue { inner: Single( TString { range: 0..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..10, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 3..9, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3..4, value: Int( 1, ), }, ), ops: [ NotEq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 2, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_not_nested_spec.snap000064400000000000000000000057501046102023000375540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..13, value: TStringValue { inner: Single( TString { range: 0..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 7..11, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 7..11, node_index: NodeIndex(None), value: "spec", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_self_doc_prec_space.snap000064400000000000000000000046001046102023000403330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..10, value: TStringValue { inner: Single( TString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " =", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_self_doc_trailing_space.snap000064400000000000000000000046001046102023000412130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..10, value: TStringValue { inner: Single( TString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: "= ", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_tstring_yield_expr.snap000064400000000000000000000037271046102023000365460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..10, value: TStringValue { inner: Single( TString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Yield( ExprYield { node_index: NodeIndex(None), range: 3..8, value: None, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap000064400000000000000000000046371046102023000365370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..18, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..9, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 10..18, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 12..17, node_index: NodeIndex(None), value: "world", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap000064400000000000000000000061401046102023000365270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..22, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 0..9, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 10..18, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 12..17, node_index: NodeIndex(None), value: "world", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 19..22, node_index: NodeIndex(None), value: "!", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_u_string_concat_1.snap000064400000000000000000000037271046102023000362310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..17, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 0..8, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 9..17, node_index: NodeIndex(None), value: "world", flags: StringLiteralFlags { quote_style: Single, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ], value: "Hello world", }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_u_string_concat_2.snap000064400000000000000000000037301046102023000362240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..17, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 0..9, node_index: NodeIndex(None), value: "Hello ", flags: StringLiteralFlags { quote_style: Single, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 10..17, node_index: NodeIndex(None), value: "world", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "Hello world", }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__parse_u_t_string_concat_1_error.snap000064400000000000000000000003221046102023000377510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..18, } ruff_python_parser__string__tests__parse_u_t_string_concat_2_error.snap000064400000000000000000000003221046102023000377520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- ParseError { error: OtherError( "Cannot mix t-string literals with string or bytes literals", ), location: 0..22, } ruff_python_parser__string__tests__raw_byte_literal_1.snap000064400000000000000000000024741046102023000352040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..8, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..8, node_index: NodeIndex(None), value: [ 92, 120, 49, 122, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__raw_byte_literal_2.snap000064400000000000000000000023521046102023000352000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..6, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..6, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..6, node_index: NodeIndex(None), value: [ 92, 92, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__raw_fstring.snap000064400000000000000000000044631046102023000337610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..7, value: FStringValue { inner: Single( FString( FString { range: 0..7, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 3..6, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__raw_tstring.snap000064400000000000000000000041631046102023000337740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..7, value: TStringValue { inner: Single( TString { range: 0..7, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 3..6, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__single_quoted_byte.snap000064400000000000000000000263221046102023000353170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..738, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..738, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..738, node_index: NodeIndex(None), 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, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__string_parser_escaped_mac_eol.snap000064400000000000000000000020551046102023000374540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..18, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..18, node_index: NodeIndex(None), value: "text more text", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__string_parser_escaped_unix_eol.snap000064400000000000000000000020551046102023000376770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..18, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..18, node_index: NodeIndex(None), value: "text more text", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__string_parser_escaped_windows_eol.snap000064400000000000000000000020551046102023000404060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..19, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..19, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..19, node_index: NodeIndex(None), value: "text more text", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap000064400000000000000000000044651046102023000367230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..11, value: FStringValue { inner: Single( FString( FString { range: 0..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), ] ruff_python_parser__string__tests__triple_quoted_raw_tstring.snap000064400000000000000000000041651046102023000367360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..11, value: TStringValue { inner: Single( TString { range: 0..11, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_constant_range.snap000064400000000000000000000102441046102023000362050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..22, value: TStringValue { inner: Single( TString { range: 0..22, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..5, node_index: NodeIndex(None), value: "aaa", }, ), Interpolation( InterpolatedElement { range: 5..10, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("bbb"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 10..13, node_index: NodeIndex(None), value: "ccc", }, ), Interpolation( InterpolatedElement { range: 13..18, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("ddd"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 18..21, node_index: NodeIndex(None), value: "eee", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_escaped_character.snap000064400000000000000000000046301046102023000366220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..8, value: TStringValue { inner: Single( TString { range: 0..8, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..4, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 4..7, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_escaped_newline.snap000064400000000000000000000046301046102023000363270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..8, value: TStringValue { inner: Single( TString { range: 0..8, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..4, node_index: NodeIndex(None), value: "\n", }, ), Interpolation( InterpolatedElement { range: 4..7, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_line_continuation.snap000064400000000000000000000047721046102023000367320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..9, value: TStringValue { inner: Single( TString { range: 0..9, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 3..5, node_index: NodeIndex(None), value: "\\\n", }, ), Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_parse_self_documenting_base.snap000064400000000000000000000046031046102023000407130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..10, value: TStringValue { inner: Single( TString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_parse_self_documenting_base_more.snap000064400000000000000000000110041046102023000417260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..38, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..38, value: TStringValue { inner: Single( TString { range: 0..38, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..6, node_index: NodeIndex(None), value: "mix ", }, ), Interpolation( InterpolatedElement { range: 6..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 7..11, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 13..28, node_index: NodeIndex(None), value: " with text and ", }, ), Interpolation( InterpolatedElement { range: 28..37, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 29..35, id: Name("second"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "second", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_parse_self_documenting_format.snap000064400000000000000000000065221046102023000412730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..14, value: TStringValue { inner: Single( TString { range: 0..14, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("user"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "user", trailing: "=", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 9..12, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 9..12, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ] ruff_python_parser__string__tests__tstring_unescaped_newline.snap000064400000000000000000000046321046102023000366740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/src/snapshots--- source: crates/ruff_python_parser/src/string.rs expression: suite --- [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: TString( ExprTString { node_index: NodeIndex(None), range: 0..11, value: TStringValue { inner: Single( TString { range: 0..11, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 4..5, node_index: NodeIndex(None), value: "\n", }, ), Interpolation( InterpolatedElement { range: 5..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ] ast_serialize-0.13.1/crates/ruff_python_parser/src/string.rs000064400000000000000000001177051046102023000212220ustar00//! Parsing of string literals, bytes literals, and implicit string concatenation. use bstr::ByteSlice; use std::fmt; use ruff_python_ast::token::TokenKind; use ruff_python_ast::{self as ast, AnyStringFlags, AtomicNodeIndex, Expr, StringFlags}; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::error::{LexicalError, LexicalErrorType}; #[derive(Debug)] pub(crate) enum StringType { Str(ast::StringLiteral), Bytes(ast::BytesLiteral), FString(ast::FString), TString(ast::TString), } impl Ranged for StringType { fn range(&self) -> TextRange { match self { Self::Str(node) => node.range(), Self::Bytes(node) => node.range(), Self::FString(node) => node.range(), Self::TString(node) => node.range(), } } } impl From for Expr { fn from(string: StringType) -> Self { match string { StringType::Str(node) => Expr::from(node), StringType::Bytes(node) => Expr::from(node), StringType::FString(node) => Expr::from(node), StringType::TString(node) => Expr::from(node), } } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum InterpolatedStringKind { FString, TString, } impl InterpolatedStringKind { #[inline] pub(crate) const fn start_token(self) -> TokenKind { match self { InterpolatedStringKind::FString => TokenKind::FStringStart, InterpolatedStringKind::TString => TokenKind::TStringStart, } } #[inline] pub(crate) const fn middle_token(self) -> TokenKind { match self { InterpolatedStringKind::FString => TokenKind::FStringMiddle, InterpolatedStringKind::TString => TokenKind::TStringMiddle, } } #[inline] pub(crate) const fn end_token(self) -> TokenKind { match self { InterpolatedStringKind::FString => TokenKind::FStringEnd, InterpolatedStringKind::TString => TokenKind::TStringEnd, } } } impl fmt::Display for InterpolatedStringKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InterpolatedStringKind::FString => f.write_str("f-string"), InterpolatedStringKind::TString => f.write_str("t-string"), } } } enum EscapedChar { Literal(char), Escape(char), } struct StringParser<'src> { /// The raw content of the string e.g., the `foo` part in `"foo"`. source: &'src str, /// Current position of the parser in the source. cursor: usize, /// Flags that can be used to query information about the string. flags: AnyStringFlags, /// The location of the first character in the source from the start of the file. offset: TextSize, /// The range of the string literal. range: TextRange, } impl<'src> StringParser<'src> { fn new(source: &'src str, flags: AnyStringFlags, offset: TextSize, range: TextRange) -> Self { Self { source, cursor: 0, flags, offset, range, } } #[inline] fn skip_bytes(&mut self, bytes: usize) -> &str { let skipped_str = &self.source[self.cursor..self.cursor + bytes]; self.cursor += bytes; skipped_str } /// Returns the current position of the parser considering the offset. #[inline] fn position(&self) -> TextSize { self.compute_position(self.cursor) } /// Computes the position of the cursor considering the offset. #[inline] fn compute_position(&self, cursor: usize) -> TextSize { self.offset + TextSize::try_from(cursor).unwrap() } /// Returns the next byte in the string, if there is one. /// /// # Panics /// /// When the next byte is a part of a multi-byte character. #[inline] fn next_byte(&mut self) -> Option { self.source.as_bytes()[self.cursor..].first().map(|&byte| { self.cursor += 1; byte }) } #[inline] fn next_char(&mut self) -> Option { self.source[self.cursor..].chars().next().inspect(|c| { self.cursor += c.len_utf8(); }) } #[inline] fn peek_byte(&self) -> Option { self.source.as_bytes()[self.cursor..].first().copied() } fn parse_unicode_literal(&mut self, literal_number: usize) -> Result { let mut p: u32 = 0u32; for i in 1..=literal_number { let start = self.position(); match self.next_char() { Some(c) => match c.to_digit(16) { Some(d) => p += d << ((literal_number - i) * 4), None => { return Err(LexicalError::new( LexicalErrorType::UnicodeError, TextRange::at(start, TextSize::try_from(c.len_utf8()).unwrap()), )); } }, None => { return Err(LexicalError::new( LexicalErrorType::UnicodeError, TextRange::empty(self.position()), )); } } } match p { 0xD800..=0xDFFF => Ok(std::char::REPLACEMENT_CHARACTER), _ => std::char::from_u32(p).ok_or(LexicalError::new( LexicalErrorType::UnicodeError, TextRange::empty(self.position()), )), } } fn parse_octet(&mut self, o: u8) -> char { let mut radix_bytes = [o, 0, 0]; let mut len = 1; while len < 3 { let Some(b'0'..=b'7') = self.peek_byte() else { break; }; radix_bytes[len] = self.next_byte().unwrap(); len += 1; } // OK because radix_bytes is always going to be in the ASCII range. let radix_str = std::str::from_utf8(&radix_bytes[..len]).expect("ASCII bytes"); let value = u32::from_str_radix(radix_str, 8).unwrap(); char::from_u32(value).unwrap() } fn parse_unicode_name(&mut self) -> Result { let start_pos = self.position(); let Some('{') = self.next_char() else { return Err(LexicalError::new( LexicalErrorType::MissingUnicodeLbrace, TextRange::empty(start_pos), )); }; let start_pos = self.position(); let Some(close_idx) = self.source[self.cursor..].find('}') else { return Err(LexicalError::new( LexicalErrorType::MissingUnicodeRbrace, TextRange::empty(self.compute_position(self.source.len())), )); }; let name_and_ending = self.skip_bytes(close_idx + 1); let name = &name_and_ending[..name_and_ending.len() - 1]; unicode_names2::character(name).ok_or_else(|| { LexicalError::new( LexicalErrorType::UnicodeError, // The cursor is right after the `}` character, so we subtract 1 to get the correct // range of the unicode name. TextRange::new( start_pos, self.compute_position(self.cursor - '}'.len_utf8()), ), ) }) } /// Parse an escaped character, returning the new character. fn parse_escaped_char(&mut self) -> Result, LexicalError> { let Some(first_char) = self.next_char() else { // TODO: check when this error case happens return Err(LexicalError::new( LexicalErrorType::StringError, TextRange::empty(self.position()), )); }; let new_char = match first_char { '\\' => '\\', '\'' => '\'', '\"' => '"', 'a' => '\x07', 'b' => '\x08', 'f' => '\x0c', 'n' => '\n', 'r' => '\r', 't' => '\t', 'v' => '\x0b', o @ '0'..='7' => self.parse_octet(o as u8), 'x' => self.parse_unicode_literal(2)?, 'u' if !self.flags.is_byte_string() => self.parse_unicode_literal(4)?, 'U' if !self.flags.is_byte_string() => self.parse_unicode_literal(8)?, 'N' if !self.flags.is_byte_string() => self.parse_unicode_name()?, // Special cases where the escape sequence is not a single character '\n' => return Ok(None), '\r' => { if self.peek_byte() == Some(b'\n') { self.next_byte(); } return Ok(None); } _ => return Ok(Some(EscapedChar::Escape(first_char))), }; Ok(Some(EscapedChar::Literal(new_char))) } fn parse_interpolated_string_middle( mut self, ) -> Result { // Fast-path: if the f-string or t-string doesn't contain any escape sequences, return the literal. let Some(mut index) = memchr::memchr3(b'{', b'}', b'\\', self.source.as_bytes()) else { return Ok(ast::InterpolatedStringLiteralElement { value: self.source.into(), range: self.range, node_index: AtomicNodeIndex::NONE, }); }; let mut value = String::with_capacity(self.source.len()); loop { // Add the characters before the escape sequence (or curly brace) to the string. let before_with_slash_or_brace = self.skip_bytes(index + 1); let before = &before_with_slash_or_brace[..before_with_slash_or_brace.len() - 1]; value.push_str(before); // Add the escaped character to the string. match self.source.as_bytes()[self.cursor - 1] { // If there are any curly braces inside a `F/TStringMiddle` token, // then they were escaped (i.e. `{{` or `}}`). This means that // the raw source contains a doubled brace, but the literal value only // contains one brace. brace @ (b'{' | b'}') => { if self.peek_byte() == Some(brace) { self.next_byte(); } value.push(char::from(brace)); } // We can encounter a `\` as the last character in a `F/TStringMiddle` // token which is valid in this context. For example, // // ```python // f"\{foo} \{bar:\}" // # ^ ^^ ^ // ``` // // Here, the `F/TStringMiddle` token content will be "\" and " \" // which is invalid if we look at the content in isolation: // // ```python // "\" // ``` // // However, the content is syntactically valid in the context of // the f/t-string because it's a substring of the entire f/t-string. // This is still an invalid escape sequence, but we don't want to // raise a syntax error as is done by the CPython parser. It might // be supported in the future, refer to point 3: https://peps.python.org/pep-0701/#rejected-ideas b'\\' => { if !self.flags.is_raw_string() && self.peek_byte().is_some() { if let Some(brace @ (b'{' | b'}')) = self.peek_byte() && self.source.as_bytes().get(self.cursor + 1).copied() == Some(brace) { // Leave the doubled brace for the next iteration to collapse. value.push('\\'); } else { match self.parse_escaped_char()? { None => {} Some(EscapedChar::Literal(c)) => value.push(c), Some(EscapedChar::Escape(c)) => { value.push('\\'); value.push(c); } } } } else { value.push('\\'); } } ch => { unreachable!("Expected '{{', '}}', or '\\' but got {:?}", ch); } } let Some(next_index) = memchr::memchr3(b'{', b'}', b'\\', &self.source.as_bytes()[self.cursor..]) else { // Add the rest of the string to the value. let rest = &self.source[self.cursor..]; value.push_str(rest); break; }; index = next_index; } Ok(ast::InterpolatedStringLiteralElement { value: value.into_boxed_str(), range: self.range, node_index: AtomicNodeIndex::NONE, }) } fn parse_bytes(mut self) -> Result { if let Some(index) = self.source.as_bytes().find_non_ascii_byte() { let ch = self.source.chars().nth(index).unwrap(); return Err(LexicalError::new( LexicalErrorType::InvalidByteLiteral, TextRange::at( self.compute_position(index), TextSize::try_from(ch.len_utf8()).unwrap(), ), )); } if self.flags.is_raw_string() { // For raw strings, no escaping is necessary. return Ok(StringType::Bytes(ast::BytesLiteral { value: self.source.as_bytes().into(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })); } let Some(mut escape) = memchr::memchr(b'\\', self.source.as_bytes()) else { // If the string doesn't contain any escape sequences, return the owned string. return Ok(StringType::Bytes(ast::BytesLiteral { value: self.source.as_bytes().into(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })); }; // If the string contains escape sequences, we need to parse them. let mut value = Vec::with_capacity(self.source.len()); loop { // Add the characters before the escape sequence to the string. let before_with_slash = self.skip_bytes(escape + 1); let before = &before_with_slash[..before_with_slash.len() - 1]; value.extend_from_slice(before.as_bytes()); // Add the escaped character to the string. match self.parse_escaped_char()? { None => {} Some(EscapedChar::Literal(c)) => value.push(c as u8), Some(EscapedChar::Escape(c)) => { value.push(b'\\'); value.push(c as u8); } } let Some(next_escape) = memchr::memchr(b'\\', &self.source.as_bytes()[self.cursor..]) else { // Add the rest of the string to the value. let rest = &self.source[self.cursor..]; value.extend_from_slice(rest.as_bytes()); break; }; // Update the position of the next escape sequence. escape = next_escape; } Ok(StringType::Bytes(ast::BytesLiteral { value: value.into_boxed_slice(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })) } fn parse_string(mut self) -> Result { if self.flags.is_raw_string() { // For raw strings, no escaping is necessary. return Ok(StringType::Str(ast::StringLiteral { value: self.source.into(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })); } let Some(mut escape) = memchr::memchr(b'\\', self.source.as_bytes()) else { // If the string doesn't contain any escape sequences, return the owned string. return Ok(StringType::Str(ast::StringLiteral { value: self.source.into(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })); }; // If the string contains escape sequences, we need to parse them. let mut value = String::with_capacity(self.source.len()); loop { // Add the characters before the escape sequence to the string. let before_with_slash = self.skip_bytes(escape + 1); let before = &before_with_slash[..before_with_slash.len() - 1]; value.push_str(before); // Add the escaped character to the string. match self.parse_escaped_char()? { None => {} Some(EscapedChar::Literal(c)) => value.push(c), Some(EscapedChar::Escape(c)) => { value.push('\\'); value.push(c); } } let Some(next_escape) = self.source[self.cursor..].find('\\') else { // Add the rest of the string to the value. let rest = &self.source[self.cursor..]; value.push_str(rest); break; }; // Update the position of the next escape sequence. escape = next_escape; } Ok(StringType::Str(ast::StringLiteral { value: value.into_boxed_str(), range: self.range, flags: self.flags.into(), node_index: AtomicNodeIndex::NONE, })) } fn parse(self) -> Result { if self.flags.is_byte_string() { self.parse_bytes() } else { self.parse_string() } } } pub(crate) fn parse_string_literal( source: &str, flags: AnyStringFlags, range: TextRange, ) -> Result { StringParser::new(source, flags, range.start() + flags.opener_len(), range).parse() } pub(crate) fn parse_interpolated_string_literal_element( source: &str, flags: AnyStringFlags, range: TextRange, ) -> Result { StringParser::new(source, flags, range.start(), range).parse_interpolated_string_middle() } #[cfg(test)] mod tests { use ruff_python_ast::Suite; use crate::error::LexicalErrorType; use crate::{ InterpolatedStringErrorType, Mode, ParseError, ParseErrorType, ParseOptions, Parsed, parse, parse_module, }; const WINDOWS_EOL: &str = "\r\n"; const MAC_EOL: &str = "\r"; const UNIX_EOL: &str = "\n"; fn parse_suite(source: &str) -> Result { parse_module(source).map(Parsed::into_suite) } fn parse_suite_with_recursion_limit( source: &str, max_recursion_depth: u16, ) -> Result { parse( source, ParseOptions::from(Mode::Module).with_max_recursion_depth(max_recursion_depth), ) .map(|parsed| parsed.try_into_module().unwrap().into_suite()) } fn nested_format_spec(prefix: char, depth: usize) -> String { let mut replacement_field = String::from("{spec}"); for _ in 0..depth { replacement_field = format!("{{foo:{replacement_field}}}"); } format!(r#"{prefix}"{replacement_field}""#) } fn string_parser_escaped_eol(eol: &str) -> Suite { let source = format!(r"'text \{eol}more text'"); parse_suite(&source).unwrap() } #[test] fn test_string_parser_escaped_unix_eol() { let suite = string_parser_escaped_eol(UNIX_EOL); insta::assert_debug_snapshot!(suite); } #[test] fn test_string_parser_escaped_mac_eol() { let suite = string_parser_escaped_eol(MAC_EOL); insta::assert_debug_snapshot!(suite); } #[test] fn test_string_parser_escaped_windows_eol() { let suite = string_parser_escaped_eol(WINDOWS_EOL); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring() { let source = r#"f"{a}{ b }{{foo}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_nested_spec() { let source = r#"f"{foo:{spec}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_nested_spec_recursion_limit() { assert!(parse_suite_with_recursion_limit(r#"f"{foo:{spec}}""#, 8).is_ok()); let err = parse_suite_with_recursion_limit(&nested_format_spec('f', 200), 8).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn test_parse_fstring_not_nested_spec() { let source = r#"f"{foo:spec}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_empty_fstring() { let source = r#"f"""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_parse_self_documenting_base() { let source = r#"f"{user=}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_parse_self_documenting_base_more() { let source = r#"f"mix {user=} with text and {second=}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_parse_self_documenting_format() { let source = r#"f"{user=:>10}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } fn parse_fstring_error(source: &str) -> InterpolatedStringErrorType { parse_suite(source) .map_err(|e| match e.error { ParseErrorType::Lexical(LexicalErrorType::FStringError(e)) => e, ParseErrorType::FStringError(e) => e, e => unreachable!("Expected FStringError: {:?}", e), }) .expect_err("Expected error") } #[test] fn test_parse_invalid_fstring() { use InterpolatedStringErrorType::{InvalidConversionFlag, LambdaWithoutParentheses}; assert_eq!(parse_fstring_error(r#"f"{5!x}""#), InvalidConversionFlag); assert_eq!( parse_fstring_error("f'{lambda x:{x}}'"), LambdaWithoutParentheses ); // NOTE: The parser produces the `LambdaWithoutParentheses` for this case, but // since the parser only return the first error to maintain compatibility with // the rest of the codebase, this test case fails. The `LambdaWithoutParentheses` // error appears after the unexpected `FStringMiddle` token, which is between the // `:` and the `{`. // assert_eq!(parse_fstring_error("f'{lambda x: {x}}'"), LambdaWithoutParentheses); assert!(parse_suite(r#"f"{class}""#).is_err()); } #[test] fn test_parse_fstring_not_equals() { let source = r#"f"{1 != 2}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_equals() { let source = r#"f"{42 == 42}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_self_doc_prec_space() { let source = r#"f"{x =}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_self_doc_trailing_space() { let source = r#"f"{x= }""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_yield_expr() { let source = r#"f"{yield}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring() { let source = r#"t"{a}{ b }{{foo}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_nested_spec() { let source = r#"t"{foo:{spec}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_nested_spec_recursion_limit() { assert!(parse_suite_with_recursion_limit(r#"t"{foo:{spec}}""#, 8).is_ok()); let err = parse_suite_with_recursion_limit(&nested_format_spec('t', 200), 8).unwrap_err(); assert!(matches!(err.error, ParseErrorType::RecursionLimitExceeded)); } #[test] fn test_parse_tstring_not_nested_spec() { let source = r#"t"{foo:spec}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_empty_tstring() { let source = r#"t"""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_parse_self_documenting_base() { let source = r#"t"{user=}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_parse_self_documenting_base_more() { let source = r#"t"mix {user=} with text and {second=}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_parse_self_documenting_format() { let source = r#"t"{user=:>10}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } fn parse_tstring_error(source: &str) -> InterpolatedStringErrorType { parse_suite(source) .map_err(|e| match e.error { ParseErrorType::Lexical(LexicalErrorType::TStringError(e)) => e, ParseErrorType::TStringError(e) => e, e => unreachable!("Expected TStringError: {:?}", e), }) .expect_err("Expected error") } #[test] fn test_parse_invalid_tstring() { use InterpolatedStringErrorType::{InvalidConversionFlag, LambdaWithoutParentheses}; assert_eq!(parse_tstring_error(r#"t"{5!x}""#), InvalidConversionFlag); assert_eq!( parse_tstring_error("t'{lambda x:{x}}'"), LambdaWithoutParentheses ); // NOTE: The parser produces the `LambdaWithoutParentheses` for this case, but // since the parser only return the first error to maintain compatibility with // the rest of the codebase, this test case fails. The `LambdaWithoutParentheses` // error appears after the unexpected `tStringMiddle` token, which is between the // `:` and the `{`. // assert_eq!(parse_tstring_error("f'{lambda x: {x}}'"), LambdaWithoutParentheses); assert!(parse_suite(r#"t"{class}""#).is_err()); } #[test] fn test_parse_tstring_not_equals() { let source = r#"t"{1 != 2}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_equals() { let source = r#"t"{42 == 42}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_self_doc_prec_space() { let source = r#"t"{x =}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_self_doc_trailing_space() { let source = r#"t"{x= }""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_yield_expr() { let source = r#"t"{yield}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_string_concat() { let source = "'Hello ' 'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_string_concat_1() { let source = "'Hello ' u'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_string_concat_2() { let source = "u'Hello ' 'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_string_concat_1() { let source = "'Hello ' f'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_string_concat_2() { let source = "'Hello ' f'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_string_concat_3() { let source = "'Hello ' f'world{\"!\"}'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_string_concat_4() { let source = "'Hello ' f'world{\"!\"}' 'again!'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_f_string_concat_1() { let source = "u'Hello ' f'world'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_f_string_concat_2() { let source = "u'Hello ' f'world' '!'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_t_string_concat_1_error() { let source = "'Hello ' t'world'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_t_string_concat_2_error() { let source = "'Hello ' t'world'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_t_string_concat_3_error() { let source = "'Hello ' t'world{\"!\"}'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_t_string_concat_4_error() { let source = "'Hello ' t'world{\"!\"}' 'again!'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_t_string_concat_1_error() { let source = "u'Hello ' t'world'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_u_t_string_concat_2_error() { let source = "u'Hello ' t'world' '!'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_t_string_concat_1_error() { let source = "f'Hello ' t'world'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_f_t_string_concat_2_error() { let source = "f'Hello ' t'world' '!'"; let suite = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_string_triple_quotes_with_kind() { let source = "u'''Hello, world!'''"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] 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 suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] 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 suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_escape_char_in_byte_literal() { // backslash does not escape let source = r#"b"omkmok\Xaa""#; // spell-checker:ignore omkmok let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_raw_byte_literal_1() { let source = r"rb'\x1z'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_raw_byte_literal_2() { let source = r"rb'\\'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_escape_octet() { let source = r"b'\43a\4\1234'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_escaped_newline() { let source = r#"f"\n{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_constant_range() { let source = r#"f"aaa{bbb}ccc{ddd}eee""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_unescaped_newline() { let source = r#"f""" {x}""""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_escaped_character() { let source = r#"f"\\{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_raw_fstring() { let source = r#"rf"{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_triple_quoted_raw_fstring() { let source = r#"rf"""{x}""""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_fstring_line_continuation() { let source = r#"rf"\ {x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_nested_string_spec() { let source = r#"f"{foo:{''}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_fstring_nested_concatenation_string_spec() { let source = r#"f"{foo:{'' ''}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_escaped_newline() { let source = r#"t"\n{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_constant_range() { let source = r#"t"aaa{bbb}ccc{ddd}eee""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_unescaped_newline() { let source = r#"t""" {x}""""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_escaped_character() { let source = r#"t"\\{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_raw_tstring() { let source = r#"rt"{x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_triple_quoted_raw_tstring() { let source = r#"rt"""{x}""""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_tstring_line_continuation() { let source = r#"rt"\ {x}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_nested_string_spec() { let source = r#"t"{foo:{''}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_parse_tstring_nested_concatenation_string_spec() { let source = r#"t"{foo:{'' ''}}""#; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } /// #[test] fn test_dont_panic_on_8_in_octal_escape() { let source = r"bold = '\038[1m'"; let suite = parse_suite(source).unwrap(); insta::assert_debug_snapshot!(suite); } #[test] fn test_invalid_unicode_literal() { let source = r"'\x1ó34'"; let error = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_missing_unicode_lbrace_error() { let source = r"'\N '"; let error = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_missing_unicode_rbrace_error() { let source = r"'\N{SPACE'"; let error = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_invalid_unicode_name_error() { let source = r"'\N{INVALID}'"; let error = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(error); } #[test] fn test_invalid_byte_literal_error() { let source = r"b'123a𝐁c'"; let error = parse_suite(source).unwrap_err(); insta::assert_debug_snapshot!(error); } macro_rules! test_aliases_parse { ($($name:ident: $alias:expr,)*) => { $( #[test] fn $name() { let source = format!(r#""\N{{{0}}}""#, $alias); let suite = parse_suite(&source).unwrap(); insta::assert_debug_snapshot!(suite); } )* } } test_aliases_parse! { test_backspace_alias: "BACKSPACE", test_bell_alias: "BEL", test_carriage_return_alias: "CARRIAGE RETURN", test_delete_alias: "DELETE", test_escape_alias: "ESCAPE", test_form_feed_alias: "FORM FEED", test_hts_alias: "HTS", test_character_tabulation_with_justification_alias: "CHARACTER TABULATION WITH JUSTIFICATION", } } ast_serialize-0.13.1/crates/ruff_python_parser/src/token_set.rs000064400000000000000000000023731046102023000217010ustar00use ruff_python_ast::token::TokenKind; /// A bit-set of `TokenKind`s #[derive(Clone, Copy)] pub(crate) struct TokenSet(u128); impl TokenSet { pub(crate) const fn new(kinds: [TokenKind; N]) -> TokenSet { let mut res = 0u128; let mut i = 0usize; while i < N { let kind = kinds[i]; res |= mask(kind); i += 1; } TokenSet(res) } pub(crate) const fn union(self, other: TokenSet) -> TokenSet { TokenSet(self.0 | other.0) } pub(crate) const fn remove(self, kind: TokenKind) -> TokenSet { TokenSet(self.0 & !mask(kind)) } pub(crate) const fn contains(&self, kind: TokenKind) -> bool { self.0 & mask(kind) != 0 } } const fn mask(kind: TokenKind) -> u128 { 1u128 << (kind as usize) } impl From<[TokenKind; N]> for TokenSet { fn from(kinds: [TokenKind; N]) -> Self { TokenSet::new(kinds) } } #[test] fn token_set_works_for_tokens() { use ruff_python_ast::token::TokenKind::*; let mut ts = TokenSet::new([EndOfFile, Name]); assert!(ts.contains(EndOfFile)); assert!(ts.contains(Name)); assert!(!ts.contains(Plus)); ts = ts.remove(Name); assert!(!ts.contains(Name)); } ast_serialize-0.13.1/crates/ruff_python_parser/src/token_source.rs000064400000000000000000000221661046102023000224100ustar00use ruff_python_ast::token::{Token, TokenFlags, TokenKind}; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::Mode; use crate::error::LexicalError; use crate::lexer::{Lexer, LexerCheckpoint}; use crate::string::InterpolatedStringKind; /// Token source for the parser that skips over any trivia tokens. #[derive(Debug)] pub(crate) struct TokenSource<'src> { /// The underlying source for the tokens. lexer: Lexer<'src>, /// A vector containing all the tokens emitted by the lexer. This is returned when the parser /// is finished consuming all the tokens. Note that unlike the emitted tokens, this vector /// holds both the trivia and non-trivia tokens. tokens: Vec, } impl<'src> TokenSource<'src> { /// Create a new token source for the given lexer. fn new(lexer: Lexer<'src>, source: &str, start_offset: TextSize) -> Self { TokenSource { lexer, tokens: allocate_tokens_vec(&source[start_offset.to_usize()..]), } } /// Create a new token source from the given source code which starts at the given offset. pub(crate) fn from_source(source: &'src str, mode: Mode, start_offset: TextSize) -> Self { let lexer = Lexer::new(source, mode, start_offset); let mut source = TokenSource::new(lexer, source, start_offset); // Initialize the token source so that the current token is set correctly. source.do_bump(); source } /// Returns the kind of the current token. pub(crate) const fn current_kind(&self) -> TokenKind { self.lexer.current_kind() } /// Returns the range of the current token. pub(crate) const fn current_range(&self) -> TextRange { self.lexer.current_range() } /// Returns the current parenthesis, bracket, and brace nesting level. #[inline] pub(crate) const fn nesting(&self) -> u32 { self.lexer.nesting() } /// Returns the flags for the current token. pub(crate) const fn current_flags(&self) -> TokenFlags { self.lexer.current_flags() } /// Calls the underlying [`re_lex_logical_token`] method on the lexer with the new lexer /// position and updates the token vector accordingly. /// /// [`re_lex_logical_token`]: Lexer::re_lex_logical_token pub(crate) fn re_lex_logical_token(&mut self) { let mut non_logical_newline = None; #[cfg(debug_assertions)] let last_non_trivia_end_before = { self.tokens .iter() .rev() .find(|tok| !tok.kind().is_trivia()) .map(ruff_text_size::Ranged::end) }; for (index, token) in self.tokens.iter().enumerate().rev() { match token.kind() { TokenKind::NonLogicalNewline => { non_logical_newline = Some((index, token.start())); } TokenKind::Comment => continue, _ => break, } } if !self .lexer .re_lex_logical_token(non_logical_newline.map(|(_, start)| start)) { return; } let non_logical_line_index = non_logical_newline .expect( "`re_lex_logical_token` should only return `true` if `non_logical_line` is `Some`", ) .0; // Trim the already bumped logical line token (and comments coming after it) as it might now have become a logical line token self.tokens.truncate(non_logical_line_index); #[cfg(debug_assertions)] { let last_non_trivia_end_now = { self.tokens .iter() .rev() .find(|tok| !tok.kind().is_trivia()) .map(ruff_text_size::Ranged::end) }; assert_eq!(last_non_trivia_end_before, last_non_trivia_end_now); } // Ensure `current` is positioned at a non-trivia token. if self.current_kind().is_trivia() { self.bump(self.current_kind()); } } pub(crate) fn re_lex_string_token_in_interpolation_element( &mut self, kind: InterpolatedStringKind, ) { self.lexer .re_lex_string_token_in_interpolation_element(kind); } pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) { self.lexer.re_lex_raw_string_in_format_spec(); } /// Returns the next non-trivia token without consuming it. /// /// Use [`peek2`] to get the next two tokens. /// /// [`peek2`]: TokenSource::peek2 pub(crate) fn peek(&mut self) -> TokenKind { let checkpoint = self.lexer.checkpoint(); let next = self.next_non_trivia_token(); self.lexer.rewind(checkpoint); next } /// Returns the next two non-trivia tokens without consuming it. /// /// Use [`peek`] to only get the next token. /// /// [`peek`]: TokenSource::peek pub(crate) fn peek2(&mut self) -> (TokenKind, TokenKind) { let checkpoint = self.lexer.checkpoint(); let first = self.next_non_trivia_token(); let second = self.next_non_trivia_token(); self.lexer.rewind(checkpoint); (first, second) } /// Bumps the token source to the next non-trivia token. /// /// It pushes the given kind to the token vector with the current token range. pub(crate) fn bump(&mut self, kind: TokenKind) { self.tokens .push(Token::new(kind, self.current_range(), self.current_flags())); self.do_bump(); } /// Bumps the token source to the next non-trivia token without adding the current token to the /// token vector. It does add the trivia tokens to the token vector. fn do_bump(&mut self) { loop { let kind = self.lexer.next_token(); if kind.is_trivia() { self.tokens .push(Token::new(kind, self.current_range(), self.current_flags())); continue; } break; } } /// Returns the next non-trivia token without adding it to the token vector. fn next_non_trivia_token(&mut self) -> TokenKind { loop { let kind = self.lexer.next_token(); if kind.is_trivia() { continue; } break kind; } } /// Creates a checkpoint to which the token source can later return to using [`Self::rewind`]. pub(crate) fn checkpoint(&self) -> TokenSourceCheckpoint { TokenSourceCheckpoint { lexer_checkpoint: self.lexer.checkpoint(), tokens_position: self.tokens.len(), } } /// Restore the token source to the given checkpoint. pub(crate) fn rewind(&mut self, checkpoint: TokenSourceCheckpoint) { let TokenSourceCheckpoint { lexer_checkpoint, tokens_position, } = checkpoint; self.lexer.rewind(lexer_checkpoint); self.tokens.truncate(tokens_position); } /// Returns a slice of [`Token`] that are within the given `range`. pub(crate) fn in_range(&self, range: TextRange) -> &[Token] { let start = self .tokens .iter() .rposition(|tok| tok.start() == range.start()); let end = self.tokens.iter().rposition(|tok| tok.end() == range.end()); let (Some(start), Some(end)) = (start, end) else { return &self.tokens; }; &self.tokens[start..=end] } /// Consumes the token source, returning the collected tokens, comment ranges, and any errors /// encountered during lexing. The token collection includes both the trivia and non-trivia /// tokens. pub(crate) fn finish(mut self) -> (Vec, Vec) { assert_eq!( self.current_kind(), TokenKind::EndOfFile, "TokenSource was not fully consumed" ); // The `EndOfFile` token shouldn't be included in the token stream, it's mainly to signal // the parser to stop. This isn't in `do_bump` because it only needs to be done once. if let Some(last) = self.tokens.pop() { assert_eq!(last.kind(), TokenKind::EndOfFile); } self.tokens.shrink_to_fit(); (self.tokens, self.lexer.finish()) } } pub(crate) struct TokenSourceCheckpoint { lexer_checkpoint: LexerCheckpoint, tokens_position: usize, } /// Allocates a token buffer with a capacity intended to skip early grows. fn allocate_tokens_vec(contents: &str) -> Vec { // In sampled ruff-ecosystem projects, about three quarters of Python files contain at least // one token per eight source bytes. Intentionally underestimate the final token count to avoid // over-reserving for token-sparse files. const BYTES_PER_PREALLOCATED_TOKEN: usize = 8; const MIN_INITIAL_CAPACITY: usize = 128; let capacity_hint = contents.len() / BYTES_PER_PREALLOCATED_TOKEN; if capacity_hint < MIN_INITIAL_CAPACITY { return Vec::new(); } // Stay on a power-of-two bucket so that later geometric growth does not preserve an // arbitrary capacity offset. Vec::with_capacity(1 << capacity_hint.ilog2()) } ast_serialize-0.13.1/crates/ruff_python_parser/src/typing.rs000064400000000000000000000060011046102023000212100ustar00//! This module takes care of parsing a type annotation. use ruff_python_ast::relocate::relocate_expr; use ruff_python_ast::{Expr, ExprStringLiteral, ModExpression, StringLiteral}; use ruff_text_size::Ranged; use crate::{ParseError, Parsed, parse_expression, parse_string_annotation}; type AnnotationParseResult = Result; #[derive(Debug)] pub struct ParsedAnnotation { parsed: Parsed, kind: AnnotationKind, } impl ParsedAnnotation { pub fn parsed(&self) -> &Parsed { &self.parsed } pub fn expression(&self) -> &Expr { self.parsed.expr() } pub fn kind(&self) -> AnnotationKind { self.kind } } #[derive(Copy, Clone, Debug)] pub enum AnnotationKind { /// The annotation is defined as part a simple string literal, /// e.g. `x: "List[int]" = []`. Annotations within simple literals /// can be accurately located. For example, we can underline specific /// expressions within the annotation and apply automatic fixes, which is /// not possible for complex string literals. Simple, /// The annotation is defined as part of a complex string literal, such as /// a literal containing an implicit concatenation or escaped characters, /// e.g. `x: "List" "[int]" = []`. These are comparatively rare, but valid. Complex, } impl AnnotationKind { /// Returns `true` if the annotation kind is simple. pub const fn is_simple(self) -> bool { matches!(self, AnnotationKind::Simple) } } /// Parses the given string expression node as a type annotation. The given `source` is the entire /// source code. pub fn parse_type_annotation( string_expr: &ExprStringLiteral, source: &str, ) -> AnnotationParseResult { if let Some(string_literal) = string_expr.as_single_part_string() { // Compare the raw contents (without quotes) of the expression with the parsed contents // contained in the string literal. if &source[string_literal.content_range()] == string_literal.as_str() { parse_simple_type_annotation(string_literal, source) } else { // The raw contents of the string doesn't match the parsed content. This could be the // case for annotations that contain escaped quotes. parse_complex_type_annotation(string_expr) } } else { // String is implicitly concatenated. parse_complex_type_annotation(string_expr) } } fn parse_simple_type_annotation( string_literal: &StringLiteral, source: &str, ) -> AnnotationParseResult { Ok(ParsedAnnotation { parsed: parse_string_annotation(source, string_literal)?, kind: AnnotationKind::Simple, }) } fn parse_complex_type_annotation(string_expr: &ExprStringLiteral) -> AnnotationParseResult { let mut parsed = parse_expression(string_expr.value.to_str())?; relocate_expr(parsed.expr_mut(), string_expr.range()); Ok(ParsedAnnotation { parsed, kind: AnnotationKind::Complex, }) } ast_serialize-0.13.1/crates/ruff_python_parser/tests/fixtures.rs000064400000000000000000000605111046102023000221300ustar00use std::cell::RefCell; use std::cmp::Ordering; use std::fmt::{Formatter, Write}; use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; use datatest_stable::Utf8Path; use itertools::Itertools; use ruff_python_ast::token::{Token, Tokens}; use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::source_order::{SourceOrderVisitor, TraversalSignal, walk_module}; use ruff_python_ast::{self as ast, AnyNodeRef, Mod, PythonVersion}; use ruff_python_parser::semantic_errors::{ LazyImportContext, SemanticSyntaxChecker, SemanticSyntaxContext, SemanticSyntaxError, }; use ruff_python_parser::{Mode, ParseErrorType, ParseOptions, Parsed, parse_unchecked}; use ruff_source_file::{LineIndex, OneIndexed, SourceCode}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; #[expect(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] fn valid_syntax(path: &Utf8Path, content: String) -> datatest_stable::Result<()> { test_valid_syntax(path, &content, "./resources/valid"); Ok(()) } #[expect(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] fn invalid_syntax(path: &Utf8Path, content: String) -> datatest_stable::Result<()> { test_invalid_syntax(path, &content, "./resources/invalid"); Ok(()) } #[expect(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] fn inline_ok(path: &Utf8Path, content: String) -> datatest_stable::Result<()> { test_valid_syntax(path, &content, "./resources/inline/ok"); Ok(()) } #[expect(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] fn inline_err(path: &Utf8Path, content: String) -> datatest_stable::Result<()> { test_invalid_syntax(path, &content, "./resources/inline/err"); Ok(()) } datatest_stable::harness! { { test = valid_syntax, root = "./resources/valid", pattern = r"\.pyi?$" }, { test = inline_ok, root = "./resources/inline/ok", pattern = r"\.pyi?$" }, { test = invalid_syntax, root = "./resources/invalid", pattern = r"\.pyi?$" }, { test = inline_err, root="./resources/inline/err", pattern = r"\.pyi?$" } } fn snapshot_input_file_for_test(root: &str, test_name: &str) -> String { format!( "crates/ruff_python_parser/{}/{}", root.trim_start_matches("./"), test_name ) } /// Asserts that the parser generates no syntax errors for a valid program. /// Snapshots the AST. fn test_valid_syntax(input_path: &Utf8Path, source: &str, root: &str) { let test_name = input_path.strip_prefix(root).unwrap_or(input_path).as_str(); let snapshot_input_file = snapshot_input_file_for_test(root, test_name); let options = extract_options(source).unwrap_or_else(|| { ParseOptions::from(Mode::Module).with_target_version(PythonVersion::latest_preview()) }); let parsed = parse_unchecked(source, options.clone()); if parsed.has_syntax_errors() { let line_index = LineIndex::from_source_text(source); let source_code = SourceCode::new(source, &line_index); let mut message = "\ Expected no syntax errors for a valid program \ but the parser generated the following errors:\n" .to_string(); for error in parsed.errors() { writeln!( &mut message, "{}\n", CodeFrame { range: error.location, error, source_code: &source_code, } ) .unwrap(); } for error in parsed.unsupported_syntax_errors() { writeln!( &mut message, "{}\n", CodeFrame { range: error.range, error: &ParseErrorType::OtherError(error.to_string()), source_code: &source_code, } ) .unwrap(); } panic!("{input_path:?}: {message}"); } validate_tokens(parsed.tokens(), source.text_len()); validate_ast(&parsed, source.text_len()); let mut output = String::new(); writeln!(&mut output, "## AST").unwrap(); writeln!(&mut output, "\n```\n{:#?}\n```", parsed.syntax()).unwrap(); let parsed = parsed.try_into_module().expect("Parsed with Mode::Module"); let mut visitor = SemanticSyntaxCheckerVisitor::new(source).with_python_version(options.target_version()); for stmt in parsed.suite() { visitor.visit_stmt(stmt); } let semantic_syntax_errors = visitor.into_diagnostics(); if !semantic_syntax_errors.is_empty() { let mut message = "Expected no semantic syntax errors for a valid program:\n".to_string(); let line_index = LineIndex::from_source_text(source); let source_code = SourceCode::new(source, &line_index); for error in semantic_syntax_errors { writeln!( &mut message, "{}\n", CodeFrame { range: error.range, error: &ParseErrorType::OtherError(error.to_string()), source_code: &source_code, } ) .unwrap(); } panic!("{input_path:?}: {message}"); } insta::with_settings!({ omit_expression => true, input_file => snapshot_input_file, prepend_module_to_snapshot => false, snapshot_suffix => test_name }, { insta::assert_snapshot!(output); }); } /// Assert that the parser generates at least one syntax error for the given input file. /// Snapshots the AST and the error messages. fn test_invalid_syntax(input_path: &Utf8Path, source: &str, root: &str) { let test_name = input_path.strip_prefix(root).unwrap_or(input_path).as_str(); let snapshot_input_file = snapshot_input_file_for_test(root, test_name); let options = extract_options(source).unwrap_or_else(|| { ParseOptions::from(Mode::Module).with_target_version(PythonVersion::PY314) }); let parsed = parse_unchecked(source, options.clone()); validate_tokens(parsed.tokens(), source.text_len()); validate_ast(&parsed, source.text_len()); let mut output = String::new(); writeln!(&mut output, "## AST").unwrap(); writeln!(&mut output, "\n```\n{:#?}\n```", parsed.syntax()).unwrap(); let line_index = LineIndex::from_source_text(source); let source_code = SourceCode::new(source, &line_index); if !parsed.errors().is_empty() { writeln!(&mut output, "## Errors\n").unwrap(); } for error in parsed.errors() { writeln!( &mut output, "{}\n", CodeFrame { range: error.location, error, source_code: &source_code, } ) .unwrap(); } if !parsed.unsupported_syntax_errors().is_empty() { writeln!(&mut output, "## Unsupported Syntax Errors\n").unwrap(); } for error in parsed.unsupported_syntax_errors() { writeln!( &mut output, "{}\n", CodeFrame { range: error.range, error: &ParseErrorType::OtherError(error.to_string()), source_code: &source_code, } ) .unwrap(); } let parsed = parsed.try_into_module().expect("Parsed with Mode::Module"); let mut visitor = SemanticSyntaxCheckerVisitor::new(source).with_python_version(options.target_version()); for stmt in parsed.suite() { visitor.visit_stmt(stmt); } let semantic_syntax_errors = visitor.into_diagnostics(); assert!( parsed.has_syntax_errors() || !semantic_syntax_errors.is_empty(), "Expected parser to generate at least one syntax error \ for a program containing syntax errors." ); if !semantic_syntax_errors.is_empty() { writeln!(&mut output, "## Semantic Syntax Errors\n").unwrap(); } for error in semantic_syntax_errors { writeln!( &mut output, "{}\n", CodeFrame { range: error.range, error: &ParseErrorType::OtherError(error.to_string()), source_code: &source_code, } ) .unwrap(); } insta::with_settings!({ omit_expression => true, input_file => snapshot_input_file, prepend_module_to_snapshot => false, snapshot_suffix => test_name }, { insta::assert_snapshot!(output); }); } /// Copy of [`ParseOptions`] for deriving [`Deserialize`] with serde as a dev-dependency. #[derive(serde::Deserialize)] #[serde(rename_all = "kebab-case")] struct JsonParseOptions { #[serde(default)] mode: JsonMode, #[serde(default)] target_version: PythonVersion, } /// Copy of [`Mode`] for deserialization. #[derive(Default, serde::Deserialize)] #[serde(rename_all = "kebab-case")] enum JsonMode { #[default] Module, Expression, ParenthesizedExpression, Ipython, } impl From for ParseOptions { fn from(value: JsonParseOptions) -> Self { let mode = match value.mode { JsonMode::Module => Mode::Module, JsonMode::Expression => Mode::Expression, JsonMode::ParenthesizedExpression => Mode::ParenthesizedExpression, JsonMode::Ipython => Mode::Ipython, }; Self::from(mode).with_target_version(value.target_version) } } /// Extract [`ParseOptions`] from an initial pragma line, if present. /// /// For example, /// /// ```python /// # parse_options: { "target-version": "3.10" } /// def f(): ... fn extract_options(source: &str) -> Option { let header = source.lines().next()?; let (_label, options) = header.split_once("# parse_options: ")?; let options: Option = serde_json::from_str(options.trim()).ok(); options.map(ParseOptions::from) } // Test that is intentionally ignored by default. // Use it for quickly debugging a parser issue. #[test] #[ignore] #[expect(clippy::print_stdout)] fn parser_quick_test() { let source = "\ f'{' f'{foo!r' "; let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module)); println!("AST:\n----\n{:#?}", parsed.syntax()); println!("Tokens:\n-------\n{:#?}", parsed.tokens()); if parsed.has_invalid_syntax() { println!("Errors:\n-------"); let line_index = LineIndex::from_source_text(source); let source_code = SourceCode::new(source, &line_index); for error in parsed.errors() { // Sometimes the code frame doesn't show the error message, so we print // the message as well. println!("Syntax Error: {error}"); println!( "{}\n", CodeFrame { range: error.location, error, source_code: &source_code, } ); } println!(); } } struct CodeFrame<'a> { range: TextRange, error: &'a ParseErrorType, source_code: &'a SourceCode<'a, 'a>, } impl std::fmt::Display for CodeFrame<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { // Copied and modified from ruff_linter/src/message/text.rs let content_start_index = self.source_code.line_index(self.range.start()); let mut start_index = content_start_index.saturating_sub(2); // Trim leading empty lines. while start_index < content_start_index { if !self.source_code.line_text(start_index).trim().is_empty() { break; } start_index = start_index.saturating_add(1); } let content_end_index = self.source_code.line_index(self.range.end()); let mut end_index = content_end_index .saturating_add(2) .min(OneIndexed::from_zero_indexed(self.source_code.line_count())); // Trim trailing empty lines. while end_index > content_end_index { if !self.source_code.line_text(end_index).trim().is_empty() { break; } end_index = end_index.saturating_sub(1); } let start_offset = self.source_code.line_start(start_index); let end_offset = self.source_code.line_end(end_index); let annotation_range = self.range - start_offset; let source = self .source_code .slice(TextRange::new(start_offset, end_offset)); let label = format!("Syntax Error: {error}", error = self.error); let span = usize::from(annotation_range.start())..usize::from(annotation_range.end()); let annotation = AnnotationKind::Primary.span(span).label(&label); let snippet = Snippet::source(source) .line_start(start_index.get()) .annotation(annotation) .fold(false); let message = Group::with_level(Level::ERROR).element(snippet); let renderer = Renderer::plain().cut_indicator("…"); let rendered = renderer.render(&[message]); writeln!(f, "{rendered}") } } /// Verifies that: /// * the ranges are strictly increasing when loop the tokens in insertion order /// * all ranges are within the length of the source code fn validate_tokens(tokens: &[Token], source_length: TextSize) { let mut previous: Option<&Token> = None; for token in tokens { assert!( token.end() <= source_length, "Token range exceeds the source code length. Token: {token:#?}", ); if let Some(previous) = previous { assert_eq!( previous.range().ordering(token.range()), Ordering::Less, "Token ranges are not in increasing order Previous token: {previous:#?} Current token: {token:#?} Tokens: {tokens:#?} ", ); } previous = Some(token); } } /// Verifies that: /// * the range of the parent node fully encloses all its child nodes /// * the ranges are strictly increasing when traversing the nodes in pre-order. /// * all ranges are within the length of the source code. fn validate_ast(parsed: &Parsed, source_len: TextSize) { walk_module( &mut ValidateAstVisitor::new(parsed.tokens(), source_len), parsed.syntax(), ); } #[derive(Debug)] struct ValidateAstVisitor<'a> { tokens: std::iter::Peekable>, parents: Vec>, previous: Option>, source_length: TextSize, } impl<'a> ValidateAstVisitor<'a> { fn new(tokens: &'a Tokens, source_length: TextSize) -> Self { Self { tokens: tokens.iter().peekable(), parents: Vec::new(), previous: None, source_length, } } } impl ValidateAstVisitor<'_> { /// Check that the node's start doesn't fall within a token. /// Called in `enter_node` before visiting children. fn assert_start_boundary(&mut self, node: AnyNodeRef<'_>) { // Skip tokens that end at or before the node starts. self.tokens .peeking_take_while(|t| t.end() <= node.start()) .last(); if let Some(next) = self.tokens.peek() { // At this point, next_token.end() > node.start() assert!( next.start() >= node.start(), "\ The start of the node falls within a token. Node: {node:#?} Token: {next:#?} Root: {root:#?}", root = self.parents.first() ); } } /// Check that the node's end doesn't fall within a token. /// Called in `leave_node` after visiting children, so all tokens /// within the node have been consumed. fn assert_end_boundary(&mut self, node: AnyNodeRef<'_>) { // Skip tokens that end at or before the node ends. self.tokens .peeking_take_while(|t| t.end() <= node.end()) .last(); if let Some(next) = self.tokens.peek() { // At this point, `next_token.end() > node.end()` assert!( next.start() >= node.end(), "\ The end of the node falls within a token. Node: {node:#?} Token: {next:#?} Root: {root:#?}", root = self.parents.first() ); } } } impl<'ast> SourceOrderVisitor<'ast> for ValidateAstVisitor<'ast> { fn enter_node(&mut self, node: AnyNodeRef<'ast>) -> TraversalSignal { assert!( node.end() <= self.source_length, "The range of the node exceeds the length of the source code. Node: {node:#?}", ); if let Some(previous) = self.previous { assert_ne!( previous.range().ordering(node.range()), Ordering::Greater, "\ The ranges of the nodes are not strictly increasing when traversing the AST in pre-order. Previous node: {previous:#?} Current node: {node:#?} Root: {root:#?}", root = self.parents.first() ); } if let Some(parent) = self.parents.last() { assert!( parent.range().contains_range(node.range()), "\ The range of the parent node does not fully enclose the range of the child node. Parent node: {parent:#?} Child node: {node:#?} Root: {root:#?}", root = self.parents.first() ); } self.assert_start_boundary(node); self.parents.push(node); TraversalSignal::Traverse } fn leave_node(&mut self, node: AnyNodeRef<'ast>) { self.assert_end_boundary(node); self.parents.pop().expect("Expected tree to be balanced"); self.previous = Some(node); } } enum Scope { Module, Function { is_async: bool }, Comprehension { is_async: bool }, Class, } struct SemanticSyntaxCheckerVisitor<'a> { checker: SemanticSyntaxChecker, diagnostics: RefCell>, python_version: PythonVersion, source: &'a str, scopes: Vec, in_try: bool, } impl<'a> SemanticSyntaxCheckerVisitor<'a> { fn new(source: &'a str) -> Self { Self { checker: SemanticSyntaxChecker::new(), diagnostics: RefCell::default(), python_version: PythonVersion::default(), source, scopes: vec![Scope::Module], in_try: false, } } #[must_use] fn with_python_version(mut self, python_version: PythonVersion) -> Self { self.python_version = python_version; self } fn into_diagnostics(self) -> Vec { self.diagnostics.into_inner() } fn with_semantic_checker(&mut self, f: impl FnOnce(&mut SemanticSyntaxChecker, &Self)) { let mut checker = std::mem::take(&mut self.checker); f(&mut checker, self); self.checker = checker; } } impl SemanticSyntaxContext for SemanticSyntaxCheckerVisitor<'_> { fn future_annotations_or_stub(&self) -> bool { false } fn lazy_import_context(&self) -> Option { match self.scopes.last() { Some(Scope::Function { .. }) => return Some(LazyImportContext::Function), Some(Scope::Class) => return Some(LazyImportContext::Class), Some(Scope::Module | Scope::Comprehension { .. }) | None => {} } if self.in_try { return Some(LazyImportContext::TryExceptBlocks); } None } fn python_version(&self) -> PythonVersion { self.python_version } fn report_semantic_error(&self, error: SemanticSyntaxError) { self.diagnostics.borrow_mut().push(error); } fn source(&self) -> &str { self.source } fn global(&self, _name: &str) -> Option { None } fn has_nonlocal_binding(&self, _name: &str) -> bool { true } fn in_async_context(&self) -> bool { if let Some(scope) = self.scopes.iter().next_back() { match scope { Scope::Class | Scope::Module => false, Scope::Comprehension { is_async } => *is_async, Scope::Function { is_async } => *is_async, } } else { false } } fn in_sync_comprehension(&self) -> bool { for scope in &self.scopes { if let Scope::Comprehension { is_async: false } = scope { return true; } } false } fn in_class_body_comprehension(&self) -> bool { for scope in self.scopes.iter().rev() { match scope { Scope::Comprehension { .. } => {} Scope::Class => return true, Scope::Module | Scope::Function { .. } => return false, } } false } fn in_module_scope(&self) -> bool { self.scopes.len() == 1 } fn in_function_scope(&self) -> bool { true } fn in_notebook(&self) -> bool { false } fn in_await_allowed_context(&self) -> bool { true } fn in_yield_allowed_context(&self) -> bool { true } fn in_generator_context(&self) -> bool { true } fn in_loop_context(&self) -> bool { true } fn is_bound_parameter(&self, _name: &str) -> bool { false } } impl Visitor<'_> for SemanticSyntaxCheckerVisitor<'_> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { self.with_semantic_checker(|semantic, context| semantic.visit_stmt(stmt, context)); match stmt { ast::Stmt::ClassDef(ast::StmtClassDef { arguments, body, decorator_list, type_params, .. }) => { for decorator in decorator_list { self.visit_decorator(decorator); } if let Some(type_params) = type_params { self.visit_type_params(type_params); } if let Some(arguments) = arguments { self.visit_arguments(arguments); } self.scopes.push(Scope::Class); self.visit_body(body); self.scopes.pop().unwrap(); } ast::Stmt::FunctionDef(ast::StmtFunctionDef { is_async, .. }) => { self.scopes.push(Scope::Function { is_async: *is_async, }); ast::visitor::walk_stmt(self, stmt); self.scopes.pop().unwrap(); } ast::Stmt::Try(_) => { let was_in_try = std::mem::replace(&mut self.in_try, true); ast::visitor::walk_stmt(self, stmt); self.in_try = was_in_try; } _ => { ast::visitor::walk_stmt(self, stmt); } } } fn visit_expr(&mut self, expr: &ast::Expr) { self.with_semantic_checker(|semantic, context| semantic.visit_expr(expr, context)); match expr { ast::Expr::Lambda(_) => { self.scopes.push(Scope::Function { is_async: false }); ast::visitor::walk_expr(self, expr); self.scopes.pop().unwrap(); } ast::Expr::ListComp(ast::ExprListComp { elt, generators, .. }) | ast::Expr::SetComp(ast::ExprSetComp { elt, generators, .. }) | ast::Expr::Generator(ast::ExprGenerator { elt, generators, .. }) => { for comprehension in generators { self.visit_comprehension(comprehension); } self.scopes.push(Scope::Comprehension { is_async: generators.iter().any(|generator| generator.is_async), }); self.visit_expr(elt); self.scopes.pop().unwrap(); } ast::Expr::DictComp(ast::ExprDictComp { key, value, generators, .. }) => { for comprehension in generators { self.visit_comprehension(comprehension); } self.scopes.push(Scope::Comprehension { is_async: generators.iter().any(|generator| generator.is_async), }); if let Some(key) = key { self.visit_expr(key); } self.visit_expr(value); self.scopes.pop().unwrap(); } _ => { ast::visitor::walk_expr(self, expr); } } } } ast_serialize-0.13.1/crates/ruff_python_parser/tests/generate_inline_tests.rs000064400000000000000000000217711046102023000246360ustar00//! This module takes specially formatted comments from `ruff_python_parser` code //! and turns them into test fixtures. The code is derived from `rust-analyzer` //! and `biome`. //! //! References: //! - //! - use std::collections::HashMap; use std::fmt; use std::fs; use std::ops::{AddAssign, Deref, DerefMut}; use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; fn project_root() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../") .canonicalize() .unwrap() } #[test] fn generate_inline_tests() -> Result<()> { let parser_dir = project_root().join("crates/ruff_python_parser/src/"); let tests = TestCollection::try_from(parser_dir.as_path())?; let mut test_files = TestFiles::default(); test_files += install_tests(&tests.ok, "crates/ruff_python_parser/resources/inline/ok")?; test_files += install_tests(&tests.err, "crates/ruff_python_parser/resources/inline/err")?; if !test_files.is_empty() { anyhow::bail!("{test_files}"); } Ok(()) } #[derive(Debug, Default)] struct TestFiles { unreferenced: Vec, updated: Vec, } impl TestFiles { fn is_empty(&self) -> bool { self.unreferenced.is_empty() && self.updated.is_empty() } } impl AddAssign for TestFiles { fn add_assign(&mut self, other: TestFiles) { self.unreferenced.extend(other.unreferenced); self.updated.extend(other.updated); } } impl fmt::Display for TestFiles { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_empty() { writeln!(f, "No unreferenced or updated test files found") } else { let root_dir = project_root(); if !self.unreferenced.is_empty() { writeln!( f, "Unreferenced test files found for which no comment exists:", )?; for path in &self.unreferenced { writeln!(f, " {}", path.strip_prefix(&root_dir).unwrap().display())?; } writeln!(f, "Please delete these files manually")?; } if !self.updated.is_empty() { if !self.unreferenced.is_empty() { writeln!(f)?; } writeln!( f, "Following files were not up-to date and has been updated:", )?; for path in &self.updated { writeln!(f, " {}", path.strip_prefix(&root_dir).unwrap().display())?; } writeln!( f, "Re-run the tests with `cargo test` to update the test snapshots" )?; if std::env::var("CI").is_ok() { writeln!( f, "NOTE: Run the tests locally and commit the updated files" )?; } } Ok(()) } } } fn install_tests(tests: &HashMap, target_dir: &str) -> Result { let root_dir = project_root(); let tests_dir = root_dir.join(target_dir); if !tests_dir.is_dir() { fs::create_dir_all(&tests_dir)?; } // Test kind is irrelevant for existing test cases. let existing = existing_tests(&tests_dir)?; let mut updated_files = vec![]; // Sort so `TestFiles` reports generated files that need updating deterministically. let mut sorted_tests = tests.iter().collect::>(); sorted_tests.sort_unstable_by_key(|(name, _)| *name); for (name, test) in sorted_tests { let path = match existing.get(name) { Some(path) => path.clone(), None => tests_dir.join(name).with_extension("py"), }; match fs::read_to_string(&path) { Ok(old_contents) if old_contents == test.contents => continue, _ => {} } fs::write(&path, &test.contents) .with_context(|| format!("Failed to write to {:?}", path.display()))?; updated_files.push(path); } let mut unreferenced = existing .into_iter() .filter(|(name, _)| !tests.contains_key(name)) .map(|(_, path)| path) .collect::>(); unreferenced.sort_unstable(); Ok(TestFiles { unreferenced, updated: updated_files, }) } #[derive(Default, Debug)] struct TestCollection { ok: HashMap, err: HashMap, } impl TryFrom<&Path> for TestCollection { type Error = anyhow::Error; fn try_from(path: &Path) -> Result { let mut tests = TestCollection::default(); for entry in walkdir::WalkDir::new(path) { let entry = entry?; if !entry.file_type().is_file() { continue; } if entry.path().extension().unwrap_or_default() != "rs" { continue; } let text = fs::read_to_string(entry.path())?; for test in collect_tests(&text) { if test.is_ok() { if let Some(old_test) = tests.ok.insert(test.name.clone(), test) { anyhow::bail!( "Duplicate test found: {name:?} (search '// test_ok {name}' for the location)\n", name = old_test.name ); } } else if let Some(old_test) = tests.err.insert(test.name.clone(), test) { anyhow::bail!( "Duplicate test found: {name:?} (search '// test_err {name}' for the location)\n", name = old_test.name ); } } } Ok(tests) } } #[derive(Debug, Clone, Copy)] enum TestKind { Ok, Err, } /// A test of the following form: /// /// ```text /// // (test_ok|test_err) name /// // /// ``` #[derive(Debug)] struct Test { name: String, contents: String, kind: TestKind, } impl Test { const fn is_ok(&self) -> bool { matches!(self.kind, TestKind::Ok) } } /// Collect the tests from the given source text. fn collect_tests(text: &str) -> Vec { let mut tests = Vec::new(); for comment_block in extract_comment_blocks(text) { let first_line = &comment_block[0]; let (kind, name) = match first_line.split_once(' ') { Some(("test_ok", suffix)) => (TestKind::Ok, suffix), Some(("test_err", suffix)) => (TestKind::Err, suffix), _ => continue, }; let text: String = comment_block[1..] .iter() .cloned() .chain([String::new()]) .collect::>() .join("\n"); assert!(!text.trim().is_empty() && text.ends_with('\n')); tests.push(Test { name: name.to_string(), contents: text, kind, }); } tests } #[derive(Debug, Default)] struct CommentBlock(Vec); impl Deref for CommentBlock { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for CommentBlock { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } /// Extract the comment blocks from the given source text. /// /// A comment block is a sequence of lines that start with `// ` and are separated /// by an empty line. An empty comment line (`//`) is also part of the block. fn extract_comment_blocks(text: &str) -> Vec { const COMMENT_PREFIX: &str = "// "; const COMMENT_PREFIX_LEN: usize = COMMENT_PREFIX.len(); let mut comment_blocks = Vec::new(); let mut block = CommentBlock::default(); for line in text.lines().map(str::trim_start) { if line == "//" { block.push(String::new()); continue; } if line.starts_with(COMMENT_PREFIX) { block.push(line[COMMENT_PREFIX_LEN..].to_string()); } else { if !block.is_empty() { comment_blocks.push(std::mem::take(&mut block)); } } } if !block.is_empty() { comment_blocks.push(block); } comment_blocks } /// Returns the existing tests in the given directory. fn existing_tests(dir: &Path) -> Result> { let mut tests = HashMap::new(); for file in fs::read_dir(dir)? { let path = file?.path(); if path.extension().unwrap_or_default() != "py" { continue; } let name = path .file_stem() .map(|x| x.to_string_lossy().to_string()) .unwrap(); if let Some(old) = tests.insert(name, path) { anyhow::bail!("Multiple test file exists for {old:?}"); } } Ok(tests) } invalid_syntax@ann_assign_stmt_invalid_annotation.py.snap000064400000000000000000000170301046102023000353700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_invalid_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..63, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..11, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), annotation: Starred( ExprStarred { node_index: NodeIndex(None), range: 3..7, value: Name( ExprName { node_index: NodeIndex(None), range: 4..7, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 1, ), }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 12..26, target: Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("x"), ctx: Store, }, ), annotation: Yield( ExprYield { node_index: NodeIndex(None), range: 15..22, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("a"), ctx: Load, }, ), ), }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 1, ), }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 27..46, target: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Store, }, ), annotation: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 30..42, value: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("b"), ctx: Load, }, ), }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 1, ), }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 47..51, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("y"), ctx: Load, }, ), value: None, simple: true, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 55..62, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 55..58, id: Name("int"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x: *int = 1 | ^^^^ Syntax Error: Starred expression cannot be used here 2 | x: yield a = 1 3 | x: yield from b = 1 | | 1 | x: *int = 1 2 | x: yield a = 1 | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | x: yield from b = 1 4 | x: y := int = 1 | | 1 | x: *int = 1 2 | x: yield a = 1 3 | x: yield from b = 1 | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | x: y := int = 1 | | 2 | x: yield a = 1 3 | x: yield from b = 1 4 | x: y := int = 1 | ^^ Syntax Error: Expected a statement ## Semantic Syntax Errors | 1 | x: *int = 1 2 | x: yield a = 1 | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 3 | x: yield from b = 1 4 | x: y := int = 1 | | 1 | x: *int = 1 2 | x: yield a = 1 3 | x: yield from b = 1 | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 4 | x: y := int = 1 | invalid_syntax@ann_assign_stmt_invalid_target.py.snap000064400000000000000000000531311046102023000345060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_invalid_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..170, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..18, target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..5, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..5, node_index: NodeIndex(None), value: "abc", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 7..10, id: Name("str"), ctx: Load, }, ), value: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 13..18, value: StringLiteralValue { inner: Single( StringLiteral { range: 13..18, node_index: NodeIndex(None), value: "def", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 19..37, target: Call( ExprCall { node_index: NodeIndex(None), range: 19..25, func: Name( ExprName { node_index: NodeIndex(None), range: 19..23, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 23..25, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 27..30, id: Name("str"), ctx: Load, }, ), value: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 33..37, value: StringLiteralValue { inner: Single( StringLiteral { range: 33..37, node_index: NodeIndex(None), value: "no", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 38..52, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 38..40, value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 42..45, id: Name("int"), ctx: Load, }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 48..52, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 48..49, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 72..83, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 72..74, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("x"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("int"), ctx: Load, }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 1, ), }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 84..100, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 84..88, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 84..85, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 90..93, id: Name("int"), ctx: Load, }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 96..100, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 96..97, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 99..100, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 101..119, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 101..107, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 109..112, id: Name("int"), ctx: Load, }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 115..119, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 138..150, target: List( ExprList { node_index: NodeIndex(None), range: 138..141, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("x"), ctx: Store, }, ), ], ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 143..146, id: Name("int"), ctx: Load, }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 1, ), }, ), ), simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 151..169, target: List( ExprList { node_index: NodeIndex(None), range: 151..157, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 152..153, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("y"), ctx: Store, }, ), ], ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 159..162, id: Name("int"), ctx: Load, }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 165..169, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 165..166, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 168..169, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), simple: false, }, ), ], }, ) ``` ## Errors | 1 | "abc": str = "def" | ^^^^^ Syntax Error: Invalid annotated assignment target 2 | call(): str = "no" 3 | *x: int = 1, 2 | | 1 | "abc": str = "def" 2 | call(): str = "no" | ^^^^^^ Syntax Error: Invalid annotated assignment target 3 | *x: int = 1, 2 4 | # Tuple assignment | | 1 | "abc": str = "def" 2 | call(): str = "no" 3 | *x: int = 1, 2 | ^^ Syntax Error: Invalid annotated assignment target 4 | # Tuple assignment 5 | x,: int = 1 | | 3 | *x: int = 1, 2 4 | # Tuple assignment 5 | x,: int = 1 | ^^ Syntax Error: Only single target (not tuple) can be annotated 6 | x, y: int = 1, 2 7 | (x, y): int = 1, 2 | | 4 | # Tuple assignment 5 | x,: int = 1 6 | x, y: int = 1, 2 | ^^^^ Syntax Error: Only single target (not tuple) can be annotated 7 | (x, y): int = 1, 2 8 | # List assignment | | 5 | x,: int = 1 6 | x, y: int = 1, 2 7 | (x, y): int = 1, 2 | ^^^^^^ Syntax Error: Only single target (not tuple) can be annotated 8 | # List assignment 9 | [x]: int = 1 | | 7 | (x, y): int = 1, 2 8 | # List assignment 9 | [x]: int = 1 | ^^^ Syntax Error: Only single target (not list) can be annotated 10 | [x, y]: int = 1, 2 | | 8 | # List assignment 9 | [x]: int = 1 10 | [x, y]: int = 1, 2 | ^^^^^^ Syntax Error: Only single target (not list) can be annotated invalid_syntax@ann_assign_stmt_invalid_value.py.snap000064400000000000000000000246341046102023000343420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_invalid_value.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..65, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..17, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("Any"), ctx: Load, }, ), value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 9..17, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 10..17, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("b"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 18..28, target: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 21..24, id: Name("Any"), ctx: Load, }, ), value: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Load, }, ), ), simple: true, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..33, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 34..64, target: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 37..41, id: Name("list"), ctx: Load, }, ), value: Some( List( ExprList { node_index: NodeIndex(None), range: 44..64, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 48..54, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 49..54, left: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 56..63, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 57..63, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("b"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, }, ), ), simple: true, }, ), ], }, ) ``` ## Errors | 1 | x: Any = *a and b | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 2 | x: Any = x := 1 3 | x: list = [x, *a | b, *a or b] | | 1 | x: Any = *a and b 2 | x: Any = x := 1 | ^^ Syntax Error: Expected a statement 3 | x: list = [x, *a | b, *a or b] | | 1 | x: Any = *a and b 2 | x: Any = x := 1 3 | x: list = [x, *a | b, *a or b] | ^^^^^^ Syntax Error: Boolean expression cannot be used here invalid_syntax@ann_assign_stmt_missing_rhs.py.snap000064400000000000000000000022661046102023000340420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_missing_rhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..9, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..8, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("int"), ctx: Load, }, ), value: None, simple: true, }, ), ], }, ) ``` ## Errors | 1 | x: int = | ^ Syntax Error: Expected an expression invalid_syntax@ann_assign_stmt_type_alias_annotation.py.snap000064400000000000000000000075331046102023000361030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ann_assign_stmt_type_alias_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..37, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..7, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("type"), ctx: Load, }, ), value: None, simple: true, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 8..15, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("X"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("int"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..28, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 16..28, parameters: None, body: Name( ExprName { node_index: NodeIndex(None), range: 24..28, id: Name("type"), ctx: Load, }, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 29..36, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("X"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 33..36, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | a: type X = int | ^ Syntax Error: Simple statements must be separated by newlines or semicolons 2 | lambda: type X = int | | 1 | a: type X = int 2 | lambda: type X = int | ^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@args_unparenthesized_generator.py.snap000064400000000000000000000445751046102023000345510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/args_unparenthesized_generator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..28, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..28, func: Name( ExprName { node_index: NodeIndex(None), range: 0..3, id: Name("sum"), ctx: Load, }, ), arguments: Arguments { range: 3..28, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 4..24, elt: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 6..24, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 15..24, func: Name( ExprName { node_index: NodeIndex(None), range: 15..20, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 20..24, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..23, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..27, value: Int( 5, ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 29..64, value: Call( ExprCall { node_index: NodeIndex(None), range: 29..64, func: Name( ExprName { node_index: NodeIndex(None), range: 29..34, id: Name("total"), ctx: Load, }, ), arguments: Arguments { range: 34..64, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 35..36, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 2, ), }, ), Generator( ExprGenerator { node_index: NodeIndex(None), range: 41..60, elt: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 43..60, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 52..60, func: Name( ExprName { node_index: NodeIndex(None), range: 52..57, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 57..60, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 58..59, value: Int( 5, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 6, ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 65..91, value: Call( ExprCall { node_index: NodeIndex(None), range: 65..91, func: Name( ExprName { node_index: NodeIndex(None), range: 65..68, id: Name("sum"), ctx: Load, }, ), arguments: Arguments { range: 68..91, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 69..89, elt: Name( ExprName { node_index: NodeIndex(None), range: 69..70, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 71..89, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 80..89, func: Name( ExprName { node_index: NodeIndex(None), range: 80..85, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 85..89, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..88, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | sum(x for x in range(10), 5) | ^^^^^^^^^^^^^^^^^^^^ Syntax Error: Unparenthesized generator expression cannot be used here 2 | total(1, 2, x for x in range(5), 6) 3 | sum(x for x in range(10),) | | 1 | sum(x for x in range(10), 5) 2 | total(1, 2, x for x in range(5), 6) | ^^^^^^^^^^^^^^^^^^^ Syntax Error: Unparenthesized generator expression cannot be used here 3 | sum(x for x in range(10),) | | 1 | sum(x for x in range(10), 5) 2 | total(1, 2, x for x in range(5), 6) 3 | sum(x for x in range(10),) | ^^^^^^^^^^^^^^^^^^^^ Syntax Error: Unparenthesized generator expression cannot be used here invalid_syntax@assert_empty_msg.py.snap000064400000000000000000000015201046102023000316230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assert_empty_msg.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Assert( StmtAssert { node_index: NodeIndex(None), range: 0..9, test: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), msg: None, }, ), ], }, ) ``` ## Errors | 1 | assert x, | ^ Syntax Error: Expected an expression invalid_syntax@assert_empty_test.py.snap000064400000000000000000000015141046102023000320170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assert_empty_test.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..7, body: [ Assert( StmtAssert { node_index: NodeIndex(None), range: 0..6, test: Name( ExprName { node_index: NodeIndex(None), range: 6..6, id: Name(""), ctx: Invalid, }, ), msg: None, }, ), ], }, ) ``` ## Errors | 1 | assert | ^ Syntax Error: Expected an expression invalid_syntax@assert_invalid_msg_expr.py.snap000064400000000000000000000130431046102023000331540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assert_invalid_msg_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..83, body: [ Assert( StmtAssert { node_index: NodeIndex(None), range: 0..16, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 7..12, value: false, }, ), msg: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 14..16, value: Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 17..30, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 24..29, value: false, }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 31..39, test: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("x"), ctx: Load, }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 40..61, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 47..52, value: false, }, ), msg: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 54..61, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 62..77, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 69..74, value: false, }, ), msg: Some( Name( ExprName { node_index: NodeIndex(None), range: 76..77, id: Name("x"), ctx: Load, }, ), ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 81..82, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | assert False, *x | ^^ Syntax Error: Starred expression cannot be used here 2 | assert False, assert x 3 | assert False, yield x | | 1 | assert False, *x 2 | assert False, assert x | ^^^^^^ Syntax Error: Expected an expression 3 | assert False, yield x 4 | assert False, x := 1 | | 1 | assert False, *x 2 | assert False, assert x 3 | assert False, yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | assert False, x := 1 | | 2 | assert False, assert x 3 | assert False, yield x 4 | assert False, x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@assert_invalid_test_expr.py.snap000064400000000000000000000111551046102023000333470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assert_invalid_test_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..55, body: [ Assert( StmtAssert { node_index: NodeIndex(None), range: 0..9, test: Starred( ExprStarred { node_index: NodeIndex(None), range: 7..9, value: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 10..23, test: Name( ExprName { node_index: NodeIndex(None), range: 17..23, id: Name("assert"), ctx: Load, }, ), msg: None, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 24..25, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 26..40, test: Yield( ExprYield { node_index: NodeIndex(None), range: 33..40, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Load, }, ), ), }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 41..49, test: Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("x"), ctx: Load, }, ), msg: None, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..54, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | assert *x | ^^ Syntax Error: Starred expression cannot be used here 2 | assert assert x 3 | assert yield x | | 1 | assert *x 2 | assert assert x | ^^^^^^ Syntax Error: Expected an identifier, but found a keyword `assert` that cannot be used here 3 | assert yield x 4 | assert x := 1 | | 1 | assert *x 2 | assert assert x | ^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | assert yield x 4 | assert x := 1 | | 1 | assert *x 2 | assert assert x 3 | assert yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | assert x := 1 | | 2 | assert assert x 3 | assert yield x 4 | assert x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@assign_stmt_invalid_target.py.snap000064400000000000000000000261031046102023000336510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..58, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..5, targets: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 0..1, value: Int( 1, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 6..15, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Store, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 1, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 14..15, value: Int( 2, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 16..33, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Store, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 1, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("y"), ctx: Store, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 2, ), }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("z"), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 34..57, targets: [ List( ExprList { node_index: NodeIndex(None), range: 34..44, elts: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 35..38, value: StringLiteralValue { inner: Single( StringLiteral { range: 35..38, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 40..43, value: StringLiteralValue { inner: Single( StringLiteral { range: 40..43, node_index: NodeIndex(None), value: "b", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 47..57, elts: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 48..51, value: StringLiteralValue { inner: Single( StringLiteral { range: 48..51, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 53..56, value: StringLiteralValue { inner: Single( StringLiteral { range: 53..56, node_index: NodeIndex(None), value: "b", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | 1 = 1 | ^ Syntax Error: Invalid assignment target 2 | x = 1 = 2 3 | x = 1 = y = 2 = z | | 1 | 1 = 1 2 | x = 1 = 2 | ^ Syntax Error: Invalid assignment target 3 | x = 1 = y = 2 = z 4 | ["a", "b"] = ["a", "b"] | | 1 | 1 = 1 2 | x = 1 = 2 3 | x = 1 = y = 2 = z | ^ Syntax Error: Invalid assignment target 4 | ["a", "b"] = ["a", "b"] | | 1 | 1 = 1 2 | x = 1 = 2 3 | x = 1 = y = 2 = z | ^ Syntax Error: Invalid assignment target 4 | ["a", "b"] = ["a", "b"] | | 2 | x = 1 = 2 3 | x = 1 = y = 2 = z 4 | ["a", "b"] = ["a", "b"] | ^^^ Syntax Error: Invalid assignment target | 2 | x = 1 = 2 3 | x = 1 = y = 2 = z 4 | ["a", "b"] = ["a", "b"] | ^^^ Syntax Error: Invalid assignment target invalid_syntax@assign_stmt_invalid_value_expr.py.snap000064400000000000000000000347121046102023000345420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..90, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..15, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 4..15, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 5..13, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 6..13, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("b"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 16..34, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 20..34, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..23, value: Int( 42, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 25..33, value: Yield( ExprYield { node_index: NodeIndex(None), range: 26..33, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 35..58, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("x"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 39..58, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 40..42, value: Int( 42, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 44..57, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 45..57, value: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 59..78, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("x"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 63..78, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 64..76, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 65..76, parameters: Some( Parameters { range: 72..73, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 72..73, node_index: NodeIndex(None), parameter: Parameter { range: 72..73, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 72..73, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 79..84, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 88..89, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x = (*a and b,) | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 2 | x = (42, *yield x) 3 | x = (42, *yield from x) | | 1 | x = (*a and b,) 2 | x = (42, *yield x) | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | x = (42, *yield from x) 4 | x = (*lambda x: x,) | | 1 | x = (*a and b,) 2 | x = (42, *yield x) 3 | x = (42, *yield from x) | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | x = (*lambda x: x,) 5 | x = x := 1 | | 2 | x = (42, *yield x) 3 | x = (42, *yield from x) 4 | x = (*lambda x: x,) | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 5 | x = x := 1 | | 3 | x = (42, *yield from x) 4 | x = (*lambda x: x,) 5 | x = x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@assign_stmt_keyword_target.py.snap000064400000000000000000000127341046102023000337140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_keyword_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..42, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..12, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 4..8, id: Name("pass"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("c"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..18, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 13..18, left: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("b"), ctx: Load, }, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 19..35, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("b"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 27..31, id: Name("pass"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("c"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 36..41, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 36..41, left: Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("b"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | a = pass = c | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here 2 | a + b 3 | a = b = pass = c | | 1 | a = pass = c 2 | a + b 3 | a = b = pass = c | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here 4 | a + b | invalid_syntax@assign_stmt_missing_rhs.py.snap000064400000000000000000000165541046102023000332130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_missing_rhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..38, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..3, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 4..9, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4..9, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 1, ), }, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 10..17, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("y"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 17..17, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..23, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 18..23, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 22..23, value: Int( 2, ), }, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 24..31, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 27..27, id: Name(""), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 30..31, id: Name("y"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..37, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 32..37, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 3, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..37, value: Int( 3, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x = | ^ Syntax Error: Expected an expression 2 | 1 + 1 3 | x = y = 4 | 2 + 2 | | 1 | x = 2 | 1 + 1 3 | x = y = | ^ Syntax Error: Expected an expression 4 | 2 + 2 5 | x = = y 6 | 3 + 3 | | 3 | x = y = 4 | 2 + 2 5 | x = = y | ^ Syntax Error: Expected an expression 6 | 3 + 3 | invalid_syntax@assign_stmt_starred_expr_value.py.snap000064400000000000000000000175361046102023000345650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_starred_expr_value.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..45, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..9, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("_"), ctx: Store, }, ), ], value: Starred( ExprStarred { node_index: NodeIndex(None), range: 4..9, value: List( ExprList { node_index: NodeIndex(None), range: 5..9, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..8, value: Int( 42, ), }, ), ], ctx: Load, }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 10..19, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("_"), ctx: Store, }, ), ], value: Starred( ExprStarred { node_index: NodeIndex(None), range: 14..19, value: Set( ExprSet { node_index: NodeIndex(None), range: 15..19, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..18, value: Int( 42, ), }, ), ], }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 20..31, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("_"), ctx: Store, }, ), ], value: Starred( ExprStarred { node_index: NodeIndex(None), range: 24..31, value: Call( ExprCall { node_index: NodeIndex(None), range: 25..31, func: Name( ExprName { node_index: NodeIndex(None), range: 25..29, id: Name("list"), ctx: Load, }, ), arguments: Arguments { range: 29..31, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 32..44, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("_"), ctx: Store, }, ), ], value: Starred( ExprStarred { node_index: NodeIndex(None), range: 36..44, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 38..43, left: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("p"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("q"), ctx: Load, }, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | _ = *[42] | ^^^^^ Syntax Error: Starred expression cannot be used here 2 | _ = *{42} 3 | _ = *list() | | 1 | _ = *[42] 2 | _ = *{42} | ^^^^^ Syntax Error: Starred expression cannot be used here 3 | _ = *list() 4 | _ = *(p + q) | | 1 | _ = *[42] 2 | _ = *{42} 3 | _ = *list() | ^^^^^^^ Syntax Error: Starred expression cannot be used here 4 | _ = *(p + q) | | 2 | _ = *{42} 3 | _ = *list() 4 | _ = *(p + q) | ^^^^^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@async_unexpected_token.py.snap000064400000000000000000000167451046102023000330160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/async_unexpected_token.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..116, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 6..20, decorator_list: [], name: Identifier { id: Name("Foo"), range: 12..15, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 27..42, test: Name( ExprName { node_index: NodeIndex(None), range: 33..37, id: Name("test"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 39..42, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 39..42, }, ), }, ), ], orelse: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 49..54, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 1, ), }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 61..81, is_async: true, decorator_list: [], name: Identifier { id: Name("foo"), range: 71..74, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 74..76, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 78..81, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 78..81, }, ), }, ), ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 88..115, subject: Name( ExprName { node_index: NodeIndex(None), range: 94..98, id: Name("test"), ctx: Load, }, ), cases: [ MatchCase { range: 104..115, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 109..110, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 112..115, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 112..115, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | async class Foo: ... | ^^^^^ Syntax Error: Expected `def`, `with` or `for` to follow `async`, found `class` 2 | async while test: ... 3 | async x = 1 | | 1 | async class Foo: ... 2 | async while test: ... | ^^^^^ Syntax Error: Expected `def`, `with` or `for` to follow `async`, found `while` 3 | async x = 1 4 | async async def foo(): ... | | 1 | async class Foo: ... 2 | async while test: ... 3 | async x = 1 | ^ Syntax Error: Expected `def`, `with` or `for` to follow `async`, found name 4 | async async def foo(): ... 5 | async match test: | | 2 | async while test: ... 3 | async x = 1 4 | async async def foo(): ... | ^^^^^ Syntax Error: Expected `def`, `with` or `for` to follow `async`, found `async` 5 | async match test: 6 | case _: ... | | 3 | async x = 1 4 | async async def foo(): ... 5 | async match test: | ^^^^^ Syntax Error: Expected `def`, `with` or `for` to follow `async`, found `match` 6 | case _: ... | invalid_syntax@aug_assign_stmt_invalid_target.py.snap000064400000000000000000000203111046102023000345000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/aug_assign_stmt_invalid_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..59, body: [ AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 0..6, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 0..1, value: Int( 1, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 7..17, target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 7..10, value: StringLiteralValue { inner: Single( StringLiteral { range: 7..10, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), op: Add, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 14..17, value: StringLiteralValue { inner: Single( StringLiteral { range: 14..17, node_index: NodeIndex(None), value: "b", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 18..25, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 18..20, value: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 26..30, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..35, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 34..35, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 36..45, target: Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("x"), ctx: Store, }, ), op: Add, value: Name( ExprName { node_index: NodeIndex(None), range: 41..45, id: Name("pass"), ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 46..58, target: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 47..52, left: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("y"), ctx: Load, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | 1 += 1 | ^ Syntax Error: Invalid augmented assignment target 2 | "a" += "b" 3 | *x += 1 | | 1 | 1 += 1 2 | "a" += "b" | ^^^ Syntax Error: Invalid augmented assignment target 3 | *x += 1 4 | pass += 1 | | 1 | 1 += 1 2 | "a" += "b" 3 | *x += 1 | ^^ Syntax Error: Invalid augmented assignment target 4 | pass += 1 5 | x += pass | | 2 | "a" += "b" 3 | *x += 1 4 | pass += 1 | ^^ Syntax Error: Expected a statement 5 | x += pass 6 | (x + y) += 1 | | 3 | *x += 1 4 | pass += 1 5 | x += pass | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here 6 | (x + y) += 1 | | 4 | pass += 1 5 | x += pass 6 | (x + y) += 1 | ^^^^^ Syntax Error: Invalid augmented assignment target invalid_syntax@aug_assign_stmt_invalid_value.py.snap000064400000000000000000000246541046102023000343440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/aug_assign_stmt_invalid_value.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..77, body: [ AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 0..13, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), op: Add, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 5..13, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 6..13, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("b"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 14..27, target: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Store, }, ), op: Add, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 19..27, value: Yield( ExprYield { node_index: NodeIndex(None), range: 20..27, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 28..46, target: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("x"), ctx: Store, }, ), op: Add, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 33..46, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 34..46, value: Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 47..64, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), op: Add, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 52..64, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 53..64, parameters: Some( Parameters { range: 60..61, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 60..61, node_index: NodeIndex(None), parameter: Parameter { range: 60..61, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 60..61, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 65..71, target: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Store, }, ), op: Add, value: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("y"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 75..76, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x += *a and b | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 2 | x += *yield x 3 | x += *yield from x | | 1 | x += *a and b 2 | x += *yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | x += *yield from x 4 | x += *lambda x: x | | 1 | x += *a and b 2 | x += *yield x 3 | x += *yield from x | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | x += *lambda x: x 5 | x += y := 1 | | 2 | x += *yield x 3 | x += *yield from x 4 | x += *lambda x: x | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 5 | x += y := 1 | | 3 | x += *yield from x 4 | x += *lambda x: x 5 | x += y := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@aug_assign_stmt_missing_rhs.py.snap000064400000000000000000000111241046102023000340330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/aug_assign_stmt_missing_rhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..27, body: [ AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 0..4, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), op: Add, value: Name( ExprName { node_index: NodeIndex(None), range: 4..4, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 11..17, target: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("x"), ctx: Store, }, ), op: Add, value: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("y"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..26, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 21..26, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x += | ^ Syntax Error: Expected an expression 2 | 1 + 1 3 | x += y += 4 | 2 + 2 | | 1 | x += 2 | 1 + 1 3 | x += y += | ^^ Syntax Error: Expected a statement 4 | 2 + 2 | | 1 | x += 2 | 1 + 1 3 | x += y += | ^ Syntax Error: Expected a statement 4 | 2 + 2 | invalid_syntax@backslash_continuation_indentation_error.py.snap000064400000000000000000000044101046102023000365710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/backslash_continuation_indentation_error.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..29, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..28, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 13..14, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..28, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 2, ), }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if True: 2 | 1 3 | / \ 4 | | 2 | |____^ Syntax Error: Unexpected indentation invalid_syntax@case_expect_indented_block.py.snap000064400000000000000000000070741046102023000335570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/case_expect_indented_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..43, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..42, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 19..26, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 24..25, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), guard: None, body: [], }, MatchCase { range: 31..42, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 36..37, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..37, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 39..42, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 39..42, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match subject: 2 | case 1: 3 | case 2: ... | ^^^^ Syntax Error: Expected an indented block after `case` block invalid_syntax@class_def_empty_body.py.snap000064400000000000000000000052321046102023000324200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/class_def_empty_body.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..10, decorator_list: [], name: Identifier { id: Name("Foo"), range: 6..9, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 11..23, decorator_list: [], name: Identifier { id: Name("Foo"), range: 17..20, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 20..22, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 24..30, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..30, value: Int( 42, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | class Foo: 2 | class Foo(): | ^^^^^ Syntax Error: Expected an indented block after `class` definition 3 | x = 42 | | 1 | class Foo: 2 | class Foo(): 3 | x = 42 | ^ Syntax Error: Expected an indented block after `class` definition invalid_syntax@class_def_missing_name.py.snap000064400000000000000000000125101046102023000327130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/class_def_missing_name.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..11, decorator_list: [], name: Identifier { id: Name(""), range: 5..5, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 8..11, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 8..11, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 12..25, decorator_list: [], name: Identifier { id: Name(""), range: 17..17, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 18..20, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 22..25, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 22..25, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 26..52, decorator_list: [], name: Identifier { id: Name(""), range: 31..31, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 32..47, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 33..46, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("metaclass"), range: 33..42, node_index: NodeIndex(None), }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("ABC"), ctx: Load, }, ), }, ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | class : ... | ^ Syntax Error: Expected an identifier 2 | class (): ... 3 | class (metaclass=ABC): ... | | 1 | class : ... 2 | class (): ... | ^ Syntax Error: Expected an identifier 3 | class (metaclass=ABC): ... | | 1 | class : ... 2 | class (): ... 3 | class (metaclass=ABC): ... | ^ Syntax Error: Expected an identifier invalid_syntax@class_def_unclosed_type_param_list.py.snap000064400000000000000000000112321046102023000353320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/class_def_unclosed_type_param_list.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..33, decorator_list: [], name: Identifier { id: Name("Foo"), range: 6..9, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 9..17, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 10..12, name: Identifier { id: Name("T1"), range: 10..12, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 14..17, name: Identifier { id: Name("T2"), range: 15..17, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 17..23, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("b"), ctx: Load, }, ), ], keywords: [], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 29..33, }, ), ], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 34..40, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..40, value: Int( 10, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | class Foo[T1, *T2(a, b): | ^ Syntax Error: Expected `]`, found `(` 2 | pass 3 | x = 10 | invalid_syntax@class_def_unparenthesized_generator_argument.py.snap000064400000000000000000000101211046102023000374160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/class_def_unparenthesized_generator_argument.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..39, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..38, decorator_list: [], name: Identifier { id: Name("Foo"), range: 6..9, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 9..33, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 10..32, elt: Name( ExprName { node_index: NodeIndex(None), range: 10..14, id: Name("base"), ctx: Load, }, ), generators: [ Comprehension { range: 15..32, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 19..23, id: Name("base"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 27..32, id: Name("bases"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 35..38, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 35..38, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | class Foo(base for base in bases): ... | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Unparenthesized generator expression cannot be used here invalid_syntax@class_type_params_py311.py.snap000064400000000000000000000210471046102023000327120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/class_type_params_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..113, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 44..95, decorator_list: [], name: Identifier { id: Name("Foo"), range: 50..53, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 53..90, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 54..69, name: Identifier { id: Name("S"), range: 54..55, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 57..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 58..61, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 63..68, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 71..79, name: Identifier { id: Name("T"), range: 71..72, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 74..79, id: Name("float"), ctx: Load, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 81..84, name: Identifier { id: Name("Ts"), range: 82..84, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 86..89, name: Identifier { id: Name("P"), range: 88..89, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 92..95, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 92..95, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 96..112, decorator_list: [], name: Identifier { id: Name("Foo"), range: 102..105, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 105..107, node_index: NodeIndex(None), type_params: [], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 109..112, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | class Foo[S: (str, bytes), T: float, *Ts, **P]: ... 3 | class Foo[]: ... | ^ Syntax Error: Type parameter list cannot be empty ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | class Foo[S: (str, bytes), T: float, *Ts, **P]: ... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Cannot use type parameter lists on Python 3.11 (syntax was added in Python 3.12) 3 | class Foo[]: ... | | 1 | # parse_options: {"target-version": "3.11"} 2 | class Foo[S: (str, bytes), T: float, *Ts, **P]: ... 3 | class Foo[]: ... | ^^ Syntax Error: Cannot use type parameter lists on Python 3.11 (syntax was added in Python 3.12) invalid_syntax@clause_expect_indented_block.py.snap000064400000000000000000000036301046102023000341120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/clause_expect_indented_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..171, body: [ If( StmtIf { node_index: NodeIndex(None), range: 53..61, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 56..60, value: true, }, ), body: [], elif_else_clauses: [], }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 62..66, }, ), If( StmtIf { node_index: NodeIndex(None), range: 162..170, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 165..169, value: true, }, ), body: [], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | # Here, the error is highlighted at the `pass` token 2 | if True: 3 | pass | ^^^^ Syntax Error: Expected an indented block after `if` statement 4 | # The parser is at the end of the program, so let's highlight 5 | # at the newline token after `:` | | 4 | # The parser is at the end of the program, so let's highlight 5 | # at the newline token after `:` 6 | if True: | ^ Syntax Error: Expected an indented block after `if` statement invalid_syntax@clause_expect_single_statement.py.snap000064400000000000000000000031731046102023000345150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/clause_expect_single_statement.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..23, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..8, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 9..22, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 12..16, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 18..22, }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if True: if True: pass | ^^ Syntax Error: Expected a simple statement invalid_syntax@comma_separated_missing_comma.py.snap000064400000000000000000000053271046102023000343000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/comma_separated_missing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..15, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..14, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..14, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 12..13, value: Int( 1, ), }, ), ], keywords: [ Keyword { range: 5..8, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(**x := 1) | ^^ Syntax Error: Expected `,`, found `:=` | 1 | call(**x := 1) | ^ Syntax Error: Positional argument cannot follow keyword argument unpacking invalid_syntax@comma_separated_missing_comma_between_elements.py.snap000064400000000000000000000043551046102023000377050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/comma_separated_missing_comma_between_elements.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..91, value: List( ExprList { node_index: NodeIndex(None), range: 83..91, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 84..85, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 87..88, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # The comma between the first two elements is expected in `parse_list_expression`. 2 | [0, 1 2] | ^ Syntax Error: Expected `,`, found int invalid_syntax@comma_separated_missing_element_between_commas.py.snap000064400000000000000000000042331046102023000377000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/comma_separated_missing_element_between_commas.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..12, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: List( ExprList { node_index: NodeIndex(None), range: 0..11, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1..2, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | [0, 1, , 2] | ^ Syntax Error: Expected an expression or a ']' invalid_syntax@comma_separated_missing_first_element.py.snap000064400000000000000000000035641046102023000360450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/comma_separated_missing_first_element.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..9, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..9, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(= 1) | ^ Syntax Error: Expected an expression or a ')' invalid_syntax@comprehension_missing_for_after_async.py.snap000064400000000000000000000057411046102023000360750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/comprehension_missing_for_after_async.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: Name( ExprName { node_index: NodeIndex(None), range: 1..6, id: Name("async"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..27, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 8..27, elt: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 11..26, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 22..26, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: true, }, ], parenthesized: true, }, ), }, ), ], }, ) ``` ## Errors | 1 | (async) | ^^^^^ Syntax Error: Expected an identifier, but found a keyword `async` that cannot be used here 2 | (x async x in iter) | | 1 | (async) 2 | (x async x in iter) | ^ Syntax Error: Expected `for`, found name invalid_syntax@debug_shadow_class.py.snap000064400000000000000000000072471046102023000320720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_class.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..82, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..20, decorator_list: [], name: Identifier { id: Name("__debug__"), range: 6..15, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 35..58, decorator_list: [], name: Identifier { id: Name("C"), range: 41..42, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 42..53, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 43..52, name: Identifier { id: Name("__debug__"), range: 43..52, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 55..58, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 55..58, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | class __debug__: ... # class name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 2 | class C[__debug__]: ... # type parameter name | | 1 | class __debug__: ... # class name 2 | class C[__debug__]: ... # type parameter name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_function.py.snap000064400000000000000000000230441046102023000326030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_function.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..170, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..20, is_async: false, decorator_list: [], name: Identifier { id: Name("__debug__"), range: 4..13, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 13..15, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 38..61, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 42..43, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 43..54, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 44..53, name: Identifier { id: Name("__debug__"), range: 44..53, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 54..56, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 85..106, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 89..90, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 90..101, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 91..100, node_index: NodeIndex(None), parameter: Parameter { range: 91..100, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 91..100, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 103..106, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 103..106, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 125..144, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 125..144, parameters: Some( Parameters { range: 132..141, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 132..141, node_index: NodeIndex(None), parameter: Parameter { range: 132..141, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 132..141, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..144, value: Int( 0, ), }, ), }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | def __debug__(): ... # function name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 2 | def f[__debug__](): ... # type parameter name 3 | def f(__debug__): ... # parameter name | | 1 | def __debug__(): ... # function name 2 | def f[__debug__](): ... # type parameter name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 3 | def f(__debug__): ... # parameter name 4 | lambda __debug__: 0 # lambda parameter name | | 1 | def __debug__(): ... # function name 2 | def f[__debug__](): ... # type parameter name 3 | def f(__debug__): ... # parameter name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 4 | lambda __debug__: 0 # lambda parameter name | | 2 | def f[__debug__](): ... # type parameter name 3 | def f(__debug__): ... # parameter name 4 | lambda __debug__: 0 # lambda parameter name | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_import.py.snap000064400000000000000000000115721046102023000322730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_import.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..100, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..16, names: [ Alias { range: 7..16, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 7..16, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 17..42, names: [ Alias { range: 24..42, node_index: NodeIndex(None), name: Identifier { id: Name("debug"), range: 24..29, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("__debug__"), range: 33..42, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 43..66, module: Some( Identifier { id: Name("x"), range: 48..49, node_index: NodeIndex(None), }, ), names: [ Alias { range: 57..66, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 57..66, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 67..99, module: Some( Identifier { id: Name("x"), range: 72..73, node_index: NodeIndex(None), }, ), names: [ Alias { range: 81..99, node_index: NodeIndex(None), name: Identifier { id: Name("debug"), range: 81..86, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("__debug__"), range: 90..99, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | import __debug__ | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 2 | import debug as __debug__ 3 | from x import __debug__ | | 1 | import __debug__ 2 | import debug as __debug__ | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 3 | from x import __debug__ 4 | from x import debug as __debug__ | | 1 | import __debug__ 2 | import debug as __debug__ 3 | from x import __debug__ | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 4 | from x import debug as __debug__ | | 2 | import debug as __debug__ 3 | from x import __debug__ 4 | from x import debug as __debug__ | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_match.py.snap000064400000000000000000000047721046102023000320610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_match.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..33, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..32, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..32, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 18..27, pattern: None, name: Some( Identifier { id: Name("__debug__"), range: 18..27, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match x: 2 | case __debug__: ... | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_try.py.snap000064400000000000000000000062441046102023000315770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_try.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..44, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..43, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5..8, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5..8, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 9..43, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 16..25, id: Name("Exception"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("__debug__"), range: 29..38, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 40..43, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 40..43, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | try: ... 2 | except Exception as __debug__: ... | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_type_alias.py.snap000064400000000000000000000075661046102023000331230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_type_alias.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..95, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..26, name: Name( ExprName { node_index: NodeIndex(None), range: 5..14, id: Name("__debug__"), ctx: Store, }, ), type_params: None, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 17..26, value: Name( ExprName { node_index: NodeIndex(None), range: 17..21, id: Name("list"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 22..25, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 67..94, name: Name( ExprName { node_index: NodeIndex(None), range: 72..77, id: Name("Debug"), ctx: Store, }, ), type_params: Some( TypeParams { range: 77..88, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 78..87, name: Identifier { id: Name("__debug__"), range: 78..87, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 91..94, id: Name("str"), ctx: Load, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | type __debug__ = list[int] # visited as an Expr but still flagged | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 2 | type Debug[__debug__] = str | | 1 | type __debug__ = list[int] # visited as an Expr but still flagged 2 | type Debug[__debug__] = str | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@debug_shadow_with.py.snap000064400000000000000000000106511046102023000317310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_with.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..39, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..38, is_async: false, items: [ WithItem { range: 5..33, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 5..20, func: Name( ExprName { node_index: NodeIndex(None), range: 5..9, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 9..20, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 10..19, value: StringLiteralValue { inner: Single( StringLiteral { range: 10..19, node_index: NodeIndex(None), value: "foo.txt", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 24..33, id: Name("__debug__"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 35..38, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 35..38, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | with open("foo.txt") as __debug__: ... | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@decorator_await_expression_py38.py.snap000064400000000000000000000107211046102023000345520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_await_expression_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..96, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..95, is_async: true, decorator_list: [], name: Identifier { id: Name("foo"), range: 55..58, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 58..60, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 66..95, is_async: false, decorator_list: [ Decorator { range: 66..76, node_index: NodeIndex(None), expression: Await( ExprAwait { node_index: NodeIndex(None), range: 67..76, value: Name( ExprName { node_index: NodeIndex(None), range: 73..76, id: Name("bar"), ctx: Load, }, ), }, ), }, ], name: Identifier { id: Name("baz"), range: 85..88, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 88..90, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 92..95, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 92..95, }, ), }, ), ], }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.8" } 2 | async def foo(): 3 | @await bar | ^^^^^^^^^ Syntax Error: Cannot use `await` expression outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9) 4 | def baz(): ... | invalid_syntax@decorator_dict_literal_py38.py.snap000064400000000000000000000074741046102023000336400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_dict_literal_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..68, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..67, is_async: false, decorator_list: [ Decorator { range: 45..52, node_index: NodeIndex(None), expression: Dict( ExprDict { node_index: NodeIndex(None), range: 46..52, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..48, value: Int( 3, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 50..51, value: Int( 3, ), }, ), }, ], }, ), }, ], name: Identifier { id: Name("bar"), range: 57..60, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 60..62, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 64..67, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 64..67, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.8" } 2 | @{3: 3} | ^^^^^^ Syntax Error: Cannot use a dict literal outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9) 3 | def bar(): ... | invalid_syntax@decorator_expression_py38.py.snap000064400000000000000000000120561046102023000333700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_expression_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..89, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..88, is_async: false, decorator_list: [ Decorator { range: 45..72, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..72, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..64, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 46..56, value: Name( ExprName { node_index: NodeIndex(None), range: 46..53, id: Name("buttons"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 0, ), }, ), ctx: Load, }, ), attr: Identifier { id: Name("clicked"), range: 57..64, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("connect"), range: 65..72, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("spam"), range: 77..81, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 81..83, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 85..88, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 85..88, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.8" } 2 | @buttons[0].clicked.connect | ^^^^^^^^^^ Syntax Error: Cannot use subscript expression outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9) 3 | def spam(): ... | invalid_syntax@decorator_float_literal_py38.py.snap000064400000000000000000000051021046102023000340040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_float_literal_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..66, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..65, is_async: false, decorator_list: [ Decorator { range: 45..50, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 46..50, value: Float( 3.14, ), }, ), }, ], name: Identifier { id: Name("bar"), range: 55..58, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 58..60, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 62..65, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 62..65, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.8" } 2 | @3.14 | ^^^^ Syntax Error: Cannot use a float literal outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9) 3 | def bar(): ... | invalid_syntax@decorator_invalid_expression.py.snap000064400000000000000000000155351046102023000342200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_invalid_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..56, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..55, is_async: false, decorator_list: [ Decorator { range: 0..3, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 1..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, Decorator { range: 4..9, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 6..8, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, Decorator { range: 10..17, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 13..15, value: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, Decorator { range: 18..26, node_index: NodeIndex(None), expression: Yield( ExprYield { node_index: NodeIndex(None), range: 19..26, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Load, }, ), ), }, ), }, Decorator { range: 27..40, node_index: NodeIndex(None), expression: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 28..40, value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Load, }, ), }, ), }, ], name: Identifier { id: Name("foo"), range: 45..48, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 48..50, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 52..55, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 52..55, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | @*x | ^^ Syntax Error: Starred expression cannot be used here 2 | @(*x) 3 | @((*x)) | | 1 | @*x 2 | @(*x) | ^^ Syntax Error: Starred expression cannot be used here 3 | @((*x)) 4 | @yield x | | 1 | @*x 2 | @(*x) 3 | @((*x)) | ^^ Syntax Error: Starred expression cannot be used here 4 | @yield x 5 | @yield from x | | 2 | @(*x) 3 | @((*x)) 4 | @yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | @yield from x 6 | def foo(): ... | | 3 | @((*x)) 4 | @yield x 5 | @yield from x | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 6 | def foo(): ... | invalid_syntax@decorator_missing_expression.py.snap000064400000000000000000000223401046102023000342330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_missing_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..70, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..15, is_async: false, decorator_list: [ Decorator { range: 0..1, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1..1, id: Name(""), ctx: Invalid, }, ), }, ], name: Identifier { id: Name("foo"), range: 5..8, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 8..10, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 12..15, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 12..15, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 16..32, is_async: false, decorator_list: [ Decorator { range: 16..17, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 17..17, id: Name(""), ctx: Invalid, }, ), }, ], name: Identifier { id: Name("foo"), range: 22..25, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 25..27, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 33..50, is_async: false, decorator_list: [ Decorator { range: 33..35, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 34..35, left: Name( ExprName { node_index: NodeIndex(None), range: 34..34, id: Name(""), ctx: Invalid, }, ), op: MatMult, right: Name( ExprName { node_index: NodeIndex(None), range: 35..35, id: Name(""), ctx: Invalid, }, ), }, ), }, ], name: Identifier { id: Name("foo"), range: 40..43, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 43..45, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 47..50, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 47..50, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 51..69, decorator_list: [ Decorator { range: 51..56, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 52..56, id: Name("test"), ctx: Load, }, ), }, Decorator { range: 57..58, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 58..58, id: Name(""), ctx: Invalid, }, ), }, ], name: Identifier { id: Name("Test"), range: 65..69, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [], }, ), ], }, ) ``` ## Errors | 1 | @def foo(): ... | ^^^ Syntax Error: Expected an identifier 2 | @ 3 | def foo(): ... | | 1 | @def foo(): ... 2 | @ | ^ Syntax Error: Expected an expression 3 | def foo(): ... 4 | @@ 5 | def foo(): ... | | 2 | @ 3 | def foo(): ... 4 | @@ | ^ Syntax Error: Expected an expression 5 | def foo(): ... 6 | @test | | 2 | @ 3 | def foo(): ... 4 | @@ | ^ Syntax Error: Expected an expression 5 | def foo(): ... 6 | @test 7 | @ | | 5 | def foo(): ... 6 | @test 7 | @ | ^ Syntax Error: Expected an expression 8 | class Test | | 6 | @test 7 | @ 8 | class Test | ^ Syntax Error: Expected `:`, found newline invalid_syntax@decorator_missing_newline.py.snap000064400000000000000000000143551046102023000335040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_missing_newline.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..60, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..17, is_async: false, decorator_list: [ Decorator { range: 0..2, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), }, ], name: Identifier { id: Name("foo"), range: 7..10, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 10..12, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 14..17, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 14..17, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 18..41, is_async: true, decorator_list: [ Decorator { range: 18..20, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("x"), ctx: Load, }, ), }, ], name: Identifier { id: Name("foo"), range: 31..34, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 34..36, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 38..41, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 38..41, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 42..59, decorator_list: [ Decorator { range: 42..44, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("x"), ctx: Load, }, ), }, ], name: Identifier { id: Name("Foo"), range: 51..54, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 56..59, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 56..59, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | @x def foo(): ... | ^^^ Syntax Error: Expected newline, found `def` 2 | @x async def foo(): ... 3 | @x class Foo: ... | | 1 | @x def foo(): ... 2 | @x async def foo(): ... | ^^^^^ Syntax Error: Expected newline, found `async` 3 | @x class Foo: ... | | 1 | @x def foo(): ... 2 | @x async def foo(): ... 3 | @x class Foo: ... | ^^^^^ Syntax Error: Expected newline, found `class` invalid_syntax@decorator_named_expression_py37.py.snap000064400000000000000000000165051046102023000345360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_named_expression_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..84, is_async: false, decorator_list: [ Decorator { range: 45..69, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 46..69, func: Named( ExprNamed { node_index: NodeIndex(None), range: 47..63, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 52..63, parameters: Some( Parameters { range: 59..60, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 59..60, node_index: NodeIndex(None), parameter: Parameter { range: 59..60, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 59..60, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), }, ), }, ), arguments: Arguments { range: 64..69, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 65..68, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ], name: Identifier { id: Name("bar"), range: 74..77, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 77..79, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.7" } 2 | @(x := lambda x: x)(foo) | ^^^^^^^^^^^^^^^^ Syntax Error: Cannot use named assignment expression (`:=`) on Python 3.7 (syntax was added in Python 3.8) 3 | def bar(): ... | | 1 | # parse_options: { "target-version": "3.7" } 2 | @(x := lambda x: x)(foo) | ^^^^^^^^^^^^^^^^ Syntax Error: Cannot use assignment expression outside function call arguments in a decorator on Python 3.7 (syntax was added in Python 3.9) 3 | def bar(): ... | invalid_syntax@decorator_non_toplevel_call_expression_py38.py.snap000064400000000000000000000115231046102023000371450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_non_toplevel_call_expression_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..72, is_async: false, decorator_list: [ Decorator { range: 45..57, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 46..57, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..55, value: Call( ExprCall { node_index: NodeIndex(None), range: 46..51, func: Name( ExprName { node_index: NodeIndex(None), range: 46..49, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 49..51, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("bar"), range: 52..55, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 55..57, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ], name: Identifier { id: Name("baz"), range: 62..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..72, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 69..72, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.8" } 2 | @foo().bar() | ^^^^^ Syntax Error: Cannot use a call expression in a decorator on Python 3.8 unless it is the top-level expression or it occurs in the argument list of a top-level call expression (relaxed decorator syntax was added in Python 3.9) 3 | def baz(): ... | invalid_syntax@decorator_unexpected_token.py.snap000064400000000000000000000133011046102023000336440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/decorator_unexpected_token.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..34, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..4, is_async: false, decorator_list: [ Decorator { range: 0..4, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1..4, id: Name("foo"), ctx: Load, }, ), }, ], name: Identifier { id: Name(""), range: 4..4, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 4..4, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), With( StmtWith { node_index: NodeIndex(None), range: 5..22, is_async: true, items: [ WithItem { range: 16..17, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..27, is_async: false, decorator_list: [ Decorator { range: 23..27, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 24..27, id: Name("foo"), ctx: Load, }, ), }, ], name: Identifier { id: Name(""), range: 27..27, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 27..27, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 28..33, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | @foo 2 | async with x: ... | ^^^^^ Syntax Error: Expected class, function definition or async function definition after decorator 3 | @foo 4 | x = 1 | | 2 | async with x: ... 3 | @foo 4 | x = 1 | ^ Syntax Error: Expected class, function definition or async function definition after decorator ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/invalid_syntax@del_debug_py39.py.snap000064400000000000000000000017751046102023000311270ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/del_debug_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 43..56, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 47..56, id: Name("__debug__"), ctx: Del, }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.9"} 2 | del __debug__ | ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.9 (syntax was removed in 3.9) invalid_syntax@del_incomplete_target.py.snap000064400000000000000000000120171046102023000325720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/del_incomplete_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..9, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Del, }, ), Attribute( ExprAttribute { node_index: NodeIndex(None), range: 7..9, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("y"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 9..9, node_index: NodeIndex(None), }, ctx: Del, }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..11, value: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("z"), ctx: Load, }, ), }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 12..24, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Del, }, ), Subscript( ExprSubscript { node_index: NodeIndex(None), range: 19..23, value: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("y"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 22..23, lower: Some( Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("z"), ctx: Load, }, ), ), upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 23..23, id: Name(""), ctx: Invalid, }, ), ), step: None, }, ), ctx: Del, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | del x, y. | ^ Syntax Error: Expected an identifier 2 | z 3 | del x, y[ 4 | z | | 3 | del x, y[ 4 | z | ^ Syntax Error: unexpected EOF while parsing ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/invalid_syntax@del_stmt_empty.py.snap000064400000000000000000000010621046102023000313470ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/del_stmt_empty.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..4, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..3, targets: [], }, ), ], }, ) ``` ## Errors | 1 | del | ^ Syntax Error: Delete statement must have at least one target invalid_syntax@different_match_pattern_bindings.py.snap000064400000000000000000002235551046102023000350100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/different_match_pattern_bindings.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..347, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..346, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..32, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 18..27, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 18..21, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 19..20, pattern: None, name: Some( Identifier { id: Name("a"), range: 19..20, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 24..27, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 25..26, pattern: None, name: Some( Identifier { id: Name("b"), range: 25..26, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, MatchCase { range: 37..55, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 42..50, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 42..45, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 43..44, pattern: None, name: Some( Identifier { id: Name("a"), range: 43..44, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 48..50, patterns: [], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 52..55, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 52..55, }, ), }, ), ], }, MatchCase { range: 60..83, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 65..78, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 65..71, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 66..67, pattern: None, name: Some( Identifier { id: Name("x"), range: 66..67, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 69..70, pattern: None, name: Some( Identifier { id: Name("y"), range: 69..70, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 74..78, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 75..76, pattern: None, name: Some( Identifier { id: Name("x"), range: 75..76, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 80..83, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 80..83, }, ), }, ), ], }, MatchCase { range: 88..113, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 93..108, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 93..99, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 94..95, pattern: None, name: Some( Identifier { id: Name("a"), range: 94..95, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 97..98, pattern: None, name: None, }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 102..108, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 103..104, pattern: None, name: Some( Identifier { id: Name("a"), range: 103..104, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 106..107, pattern: None, name: Some( Identifier { id: Name("b"), range: 106..107, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 110..113, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 110..113, }, ), }, ), ], }, MatchCase { range: 118..140, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 123..135, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 124..125, pattern: None, name: Some( Identifier { id: Name("x"), range: 124..125, node_index: NodeIndex(None), }, ), }, ), MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 128..133, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 128..129, pattern: None, name: Some( Identifier { id: Name("y"), range: 128..129, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 132..133, pattern: None, name: Some( Identifier { id: Name("z"), range: 132..133, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 137..140, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 137..140, }, ), }, ), ], }, MatchCase { range: 145..170, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 150..165, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 150..153, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 151..152, pattern: None, name: Some( Identifier { id: Name("a"), range: 151..152, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 156..159, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 157..158, pattern: None, name: Some( Identifier { id: Name("b"), range: 157..158, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 162..165, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 163..164, pattern: None, name: Some( Identifier { id: Name("c"), range: 163..164, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 167..170, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 167..170, }, ), }, ), ], }, MatchCase { range: 175..193, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 180..188, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 180..182, patterns: [], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 185..188, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 186..187, pattern: None, name: Some( Identifier { id: Name("a"), range: 186..187, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 190..193, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 190..193, }, ), }, ), ], }, MatchCase { range: 198..220, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 203..215, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 203..206, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 204..205, pattern: None, name: Some( Identifier { id: Name("a"), range: 204..205, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 209..215, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 210..214, cls: Name( ExprName { node_index: NodeIndex(None), range: 210..211, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 211..214, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 212..213, pattern: None, name: Some( Identifier { id: Name("x"), range: 212..213, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 217..220, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 217..220, }, ), }, ), ], }, MatchCase { range: 225..246, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 230..241, patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 231..240, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 231..234, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 232..233, pattern: None, name: Some( Identifier { id: Name("a"), range: 232..233, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 237..240, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 238..239, pattern: None, name: Some( Identifier { id: Name("b"), range: 238..239, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 243..246, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 243..246, }, ), }, ), ], }, MatchCase { range: 251..276, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 256..271, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 256..262, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 257..261, cls: Name( ExprName { node_index: NodeIndex(None), range: 257..258, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 258..261, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 259..260, pattern: None, name: Some( Identifier { id: Name("a"), range: 259..260, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 265..271, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 266..270, cls: Name( ExprName { node_index: NodeIndex(None), range: 266..267, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 267..270, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 268..269, pattern: None, name: Some( Identifier { id: Name("b"), range: 268..269, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 273..276, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 273..276, }, ), }, ), ], }, MatchCase { range: 281..312, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 286..307, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 286..295, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 287..294, cls: Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 288..294, node_index: NodeIndex(None), patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 289..293, cls: Name( ExprName { node_index: NodeIndex(None), range: 289..290, id: Name("D"), ctx: Load, }, ), arguments: PatternArguments { range: 290..293, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 291..292, pattern: None, name: Some( Identifier { id: Name("a"), range: 291..292, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], keywords: [], }, }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 298..307, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 299..306, cls: Name( ExprName { node_index: NodeIndex(None), range: 299..300, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 300..306, node_index: NodeIndex(None), patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 301..305, cls: Name( ExprName { node_index: NodeIndex(None), range: 301..302, id: Name("D"), ctx: Load, }, ), arguments: PatternArguments { range: 302..305, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 303..304, pattern: None, name: Some( Identifier { id: Name("b"), range: 303..304, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], keywords: [], }, }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 309..312, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 309..312, }, ), }, ), ], }, MatchCase { range: 317..346, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 322..341, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 322..330, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 323..329, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 324..325, pattern: None, name: Some( Identifier { id: Name("a"), range: 324..325, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 327..328, pattern: None, name: Some( Identifier { id: Name("b"), range: 327..328, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 333..341, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 334..340, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 335..336, pattern: None, name: Some( Identifier { id: Name("c"), range: 335..336, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 338..339, pattern: None, name: Some( Identifier { id: Name("d"), range: 338..339, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 343..346, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 343..346, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match x: 2 | case [a] | [b]: ... | ^^^^^^^^^ Syntax Error: alternative patterns bind different names 3 | case [a] | []: ... 4 | case (x, y) | (x,): ... | | 1 | match x: 2 | case [a] | [b]: ... 3 | case [a] | []: ... | ^^^^^^^^ Syntax Error: alternative patterns bind different names 4 | case (x, y) | (x,): ... 5 | case [a, _] | [a, b]: ... | | 2 | case [a] | [b]: ... 3 | case [a] | []: ... 4 | case (x, y) | (x,): ... | ^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 5 | case [a, _] | [a, b]: ... 6 | case (x, (y | z)): ... | | 3 | case [a] | []: ... 4 | case (x, y) | (x,): ... 5 | case [a, _] | [a, b]: ... | ^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 6 | case (x, (y | z)): ... 7 | case [a] | [b] | [c]: ... | | 4 | case (x, y) | (x,): ... 5 | case [a, _] | [a, b]: ... 6 | case (x, (y | z)): ... | ^^^^^ Syntax Error: alternative patterns bind different names 7 | case [a] | [b] | [c]: ... 8 | case [] | [a]: ... | | 5 | case [a, _] | [a, b]: ... 6 | case (x, (y | z)): ... 7 | case [a] | [b] | [c]: ... | ^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 8 | case [] | [a]: ... 9 | case [a] | [C(x)]: ... | | 6 | case (x, (y | z)): ... 7 | case [a] | [b] | [c]: ... 8 | case [] | [a]: ... | ^^^^^^^^ Syntax Error: alternative patterns bind different names 9 | case [a] | [C(x)]: ... 10 | case [[a] | [b]]: ... | | 7 | case [a] | [b] | [c]: ... 8 | case [] | [a]: ... 9 | case [a] | [C(x)]: ... | ^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 10 | case [[a] | [b]]: ... 11 | case [C(a)] | [C(b)]: ... | | 8 | case [] | [a]: ... 9 | case [a] | [C(x)]: ... 10 | case [[a] | [b]]: ... | ^^^^^^^^^ Syntax Error: alternative patterns bind different names 11 | case [C(a)] | [C(b)]: ... 12 | case [C(D(a))] | [C(D(b))]: ... | | 9 | case [a] | [C(x)]: ... 10 | case [[a] | [b]]: ... 11 | case [C(a)] | [C(b)]: ... | ^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 12 | case [C(D(a))] | [C(D(b))]: ... 13 | case [(a, b)] | [(c, d)]: ... | | 10 | case [[a] | [b]]: ... 11 | case [C(a)] | [C(b)]: ... 12 | case [C(D(a))] | [C(D(b))]: ... | ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 13 | case [(a, b)] | [(c, d)]: ... | | 11 | case [C(a)] | [C(b)]: ... 12 | case [C(D(a))] | [C(D(b))]: ... 13 | case [(a, b)] | [(c, d)]: ... | ^^^^^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names invalid_syntax@dotted_name_multiple_dots.py.snap000064400000000000000000000055161046102023000334760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/dotted_name_multiple_dots.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..25, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..11, names: [ Alias { range: 7..11, node_index: NodeIndex(None), name: Identifier { id: Name("a..b"), range: 7..11, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 12..20, names: [ Alias { range: 19..20, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 19..20, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..24, value: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("b"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | import a..b | ^ Syntax Error: Expected an identifier 2 | import a...b | | 1 | import a..b 2 | import a...b | ^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 1 | import a..b 2 | import a...b | ^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@duplicate_match_class_attr.py.snap000064400000000000000000001540521046102023000336140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/duplicate_match_class_attr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..231, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..230, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..38, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 18..33, cls: Name( ExprName { node_index: NodeIndex(None), range: 18..23, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 23..33, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 24..27, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 24..25, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 26..27, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..27, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 29..32, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 29..30, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 31..32, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 31..32, value: Int( 2, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 35..38, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 35..38, }, ), }, ), ], }, MatchCase { range: 43..70, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 48..65, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 49..64, cls: Name( ExprName { node_index: NodeIndex(None), range: 49..54, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 54..64, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 55..58, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 55..56, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 57..58, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 60..63, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 60..61, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 62..63, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 2, ), }, ), }, ), }, ], }, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 67..70, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 67..70, }, ), }, ), ], }, MatchCase { range: 75..113, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 80..108, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 81..84, value: StringLiteralValue { inner: Single( StringLiteral { range: 81..84, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 89..92, value: StringLiteralValue { inner: Single( StringLiteral { range: 89..92, node_index: NodeIndex(None), value: "y", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 86..87, pattern: None, name: Some( Identifier { id: Name("x"), range: 86..87, node_index: NodeIndex(None), }, ), }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 94..107, cls: Name( ExprName { node_index: NodeIndex(None), range: 94..97, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 97..107, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 98..101, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 98..99, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 100..101, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..101, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 103..106, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 103..104, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 105..106, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 2, ), }, ), }, ), }, ], }, }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 110..113, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 110..113, }, ), }, ), ], }, MatchCase { range: 118..162, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 123..157, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 124..126, keys: [], patterns: [], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 128..156, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 129..132, value: StringLiteralValue { inner: Single( StringLiteral { range: 129..132, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 137..140, value: StringLiteralValue { inner: Single( StringLiteral { range: 137..140, node_index: NodeIndex(None), value: "y", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 134..135, pattern: None, name: Some( Identifier { id: Name("x"), range: 134..135, node_index: NodeIndex(None), }, ), }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 142..155, cls: Name( ExprName { node_index: NodeIndex(None), range: 142..145, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 145..155, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 146..149, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 146..147, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 148..149, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 148..149, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 151..154, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 151..152, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 153..154, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 153..154, value: Int( 2, ), }, ), }, ), }, ], }, }, ), ], rest: None, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 159..162, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 159..162, }, ), }, ), ], }, MatchCase { range: 167..230, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 172..225, cls: Name( ExprName { node_index: NodeIndex(None), range: 172..177, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 177..225, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 178..181, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 178..179, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 180..181, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 180..181, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 183..201, node_index: NodeIndex(None), attr: Identifier { id: Name("d"), range: 183..184, node_index: NodeIndex(None), }, pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 185..201, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 186..189, value: StringLiteralValue { inner: Single( StringLiteral { range: 186..189, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 194..197, value: StringLiteralValue { inner: Single( StringLiteral { range: 194..197, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 191..192, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 191..192, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 199..200, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 199..200, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), }, PatternKeyword { range: 203..224, node_index: NodeIndex(None), attr: Identifier { id: Name("other"), range: 203..208, node_index: NodeIndex(None), }, pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 209..224, cls: Name( ExprName { node_index: NodeIndex(None), range: 209..214, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 214..224, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 215..218, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 215..216, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 217..218, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 217..218, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 220..223, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 220..221, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 222..223, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 222..223, value: Int( 2, ), }, ), }, ), }, ], }, }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 227..230, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 227..230, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match x: 2 | case Class(x=1, x=2): ... | ^ Syntax Error: attribute name `x` repeated in class pattern 3 | case [Class(x=1, x=2)]: ... 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... | | 1 | match x: 2 | case Class(x=1, x=2): ... 3 | case [Class(x=1, x=2)]: ... | ^ Syntax Error: attribute name `x` repeated in class pattern 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... 5 | case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... | | 2 | case Class(x=1, x=2): ... 3 | case [Class(x=1, x=2)]: ... 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... | ^ Syntax Error: attribute name `x` repeated in class pattern 5 | case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... 6 | case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... | | 3 | case [Class(x=1, x=2)]: ... 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... 5 | case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... | ^ Syntax Error: attribute name `x` repeated in class pattern 6 | case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... | | 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... 5 | case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... 6 | case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` | 4 | case {"x": x, "y": Foo(x=1, x=2)}: ... 5 | case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ... 6 | case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ... | ^ Syntax Error: attribute name `x` repeated in class pattern invalid_syntax@duplicate_match_key.py.snap000064400000000000000000003767001046102023000322530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/duplicate_match_key.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..754, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..753, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..39, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 18..34, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 19..22, value: StringLiteralValue { inner: Single( StringLiteral { range: 19..22, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 27..30, value: StringLiteralValue { inner: Single( StringLiteral { range: 27..30, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 24..25, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 32..33, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 36..39, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 36..39, }, ), }, ), ], }, MatchCase { range: 44..72, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 49..67, keys: [ BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 50..54, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 50..54, node_index: NodeIndex(None), value: [ 120, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 59..63, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 59..63, node_index: NodeIndex(None), value: [ 120, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 56..57, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 56..57, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 65..66, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..72, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 69..72, }, ), }, ), ], }, MatchCase { range: 77..99, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 82..94, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 0, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 86..87, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..87, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 92..93, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 92..93, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, MatchCase { range: 104..130, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 109..125, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 110..113, value: Float( 1.0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..121, value: Float( 1.0, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 115..116, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 123..124, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 123..124, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 127..130, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 127..130, }, ), }, ), ], }, MatchCase { range: 135..171, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 140..166, keys: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 141..149, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 141..144, value: Float( 1.0, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 147..149, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 154..162, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 154..157, value: Float( 1.0, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..162, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 151..152, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 151..152, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 164..165, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 168..171, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 168..171, }, ), }, ), ], }, MatchCase { range: 176..204, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 181..199, keys: [ BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 182..186, value: true, }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 191..195, value: true, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 188..189, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 188..189, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 197..198, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..198, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 201..204, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 201..204, }, ), }, ), ], }, MatchCase { range: 209..237, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 214..232, keys: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 215..219, }, ), NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 224..228, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 221..222, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 221..222, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 230..231, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 230..231, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 234..237, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 234..237, }, ), }, ), ], }, MatchCase { range: 242..268, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 247..263, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 248..249, value: Int( 0, ), }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 254..259, value: false, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 251..252, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 251..252, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 261..262, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 261..262, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 265..268, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 265..268, }, ), }, ), ], }, MatchCase { range: 273..300, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 278..295, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 279..282, value: Float( 1.0, ), }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 287..291, value: true, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 284..285, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 284..285, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 293..294, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 293..294, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 297..300, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 297..300, }, ), }, ), ], }, MatchCase { range: 305..332, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 310..327, keys: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 311..313, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 312..313, value: Int( 0, ), }, ), }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 318..323, value: false, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 315..316, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 315..316, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 325..326, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 325..326, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 329..332, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 329..332, }, ), }, ), ], }, MatchCase { range: 337..367, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 342..362, keys: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 343..349, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 343..344, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 347..349, value: Complex { real: 0.0, imag: 0.0, }, }, ), }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 354..358, value: true, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 351..352, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 351..352, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 360..361, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 360..361, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 364..367, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 364..367, }, ), }, ), ], }, MatchCase { range: 372..449, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 377..444, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 383..407, value: StringLiteralValue { inner: Single( StringLiteral { range: 383..407, node_index: NodeIndex(None), value: "x\n y\n z\n ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 416..440, value: StringLiteralValue { inner: Single( StringLiteral { range: 416..440, node_index: NodeIndex(None), value: "x\n y\n z\n ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 409..410, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 409..410, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 442..443, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 442..443, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 446..449, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 446..449, }, ), }, ), ], }, MatchCase { range: 454..488, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 459..483, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 460..463, value: StringLiteralValue { inner: Single( StringLiteral { range: 460..463, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 468..471, value: StringLiteralValue { inner: Single( StringLiteral { range: 468..471, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 476..479, value: StringLiteralValue { inner: Single( StringLiteral { range: 476..479, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 465..466, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 465..466, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 473..474, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 473..474, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 481..482, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 481..482, value: Int( 3, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 485..488, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 485..488, }, ), }, ), ], }, MatchCase { range: 493..531, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 498..526, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 499..500, value: Int( 0, ), }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 505..508, value: StringLiteralValue { inner: Single( StringLiteral { range: 505..508, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 513..514, value: Int( 0, ), }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 519..522, value: StringLiteralValue { inner: Single( StringLiteral { range: 519..522, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 502..503, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 502..503, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 510..511, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 510..511, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 516..517, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 516..517, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 524..525, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 524..525, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 528..531, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 528..531, }, ), }, ), ], }, MatchCase { range: 536..564, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 541..559, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 542..558, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 543..546, value: StringLiteralValue { inner: Single( StringLiteral { range: 543..546, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 551..554, value: StringLiteralValue { inner: Single( StringLiteral { range: 551..554, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 548..549, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 548..549, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 556..557, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 556..557, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 561..564, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 561..564, }, ), }, ), ], }, MatchCase { range: 569..607, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 574..602, cls: Name( ExprName { node_index: NodeIndex(None), range: 574..577, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 577..602, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 578..581, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 578..579, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 580..581, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 580..581, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 583..601, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 583..584, node_index: NodeIndex(None), }, pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 585..601, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 586..589, value: StringLiteralValue { inner: Single( StringLiteral { range: 586..589, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 594..597, value: StringLiteralValue { inner: Single( StringLiteral { range: 594..597, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 591..592, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 591..592, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 599..600, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 599..600, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 604..607, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 604..607, }, ), }, ), ], }, MatchCase { range: 612..662, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 617..657, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 618..626, cls: Name( ExprName { node_index: NodeIndex(None), range: 618..621, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 621..626, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 622..625, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 622..623, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 624..625, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 624..625, value: Int( 1, ), }, ), }, ), }, ], }, }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 628..656, cls: Name( ExprName { node_index: NodeIndex(None), range: 628..631, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 631..656, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 632..635, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 632..633, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 634..635, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 634..635, value: Int( 1, ), }, ), }, ), }, PatternKeyword { range: 637..655, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 637..638, node_index: NodeIndex(None), }, pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 639..655, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 640..643, value: StringLiteralValue { inner: Single( StringLiteral { range: 640..643, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 648..651, value: StringLiteralValue { inner: Single( StringLiteral { range: 648..651, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 645..646, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 645..646, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 653..654, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 653..654, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), }, ], }, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 659..662, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 659..662, }, ), }, ), ], }, MatchCase { range: 667..691, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 672..686, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 673..674, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 679..682, value: Float( 2.0, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 676..677, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 676..677, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 684..685, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 684..685, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 688..691, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 688..691, }, ), }, ), ], }, MatchCase { range: 696..753, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 701..748, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 702..718, value: Int( 9007199254740993, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 723..744, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 723..739, value: Int( 9007199254740993, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 742..744, value: Complex { real: 0.0, imag: 0.0, }, }, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 720..721, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 720..721, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 746..747, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 746..747, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 750..753, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 750..753, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match x: 2 | case {"x": 1, "x": 2}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 3 | case {b"x": 1, b"x": 2}: ... 4 | case {0: 1, 0: 2}: ... | | 1 | match x: 2 | case {"x": 1, "x": 2}: ... 3 | case {b"x": 1, b"x": 2}: ... | ^^^^ Syntax Error: mapping pattern checks duplicate key `b"x"` 4 | case {0: 1, 0: 2}: ... 5 | case {1.0: 1, 1.0: 2}: ... | | 2 | case {"x": 1, "x": 2}: ... 3 | case {b"x": 1, b"x": 2}: ... 4 | case {0: 1, 0: 2}: ... | ^ Syntax Error: mapping pattern checks duplicate key `0` 5 | case {1.0: 1, 1.0: 2}: ... 6 | case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... | | 3 | case {b"x": 1, b"x": 2}: ... 4 | case {0: 1, 0: 2}: ... 5 | case {1.0: 1, 1.0: 2}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `1.0` 6 | case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... 7 | case {True: 1, True: 2}: ... | | 4 | case {0: 1, 0: 2}: ... 5 | case {1.0: 1, 1.0: 2}: ... 6 | case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... | ^^^^^^^^ Syntax Error: mapping pattern checks duplicate key `1.0 + 2j` 7 | case {True: 1, True: 2}: ... 8 | case {None: 1, None: 2}: ... | | 5 | case {1.0: 1, 1.0: 2}: ... 6 | case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... 7 | case {True: 1, True: 2}: ... | ^^^^ Syntax Error: mapping pattern checks duplicate key `True` 8 | case {None: 1, None: 2}: ... 9 | case {0: 1, False: 2}: ... | | 6 | case {1.0 + 2j: 1, 1.0 + 2j: 2}: ... 7 | case {True: 1, True: 2}: ... 8 | case {None: 1, None: 2}: ... | ^^^^ Syntax Error: mapping pattern checks duplicate key `None` 9 | case {0: 1, False: 2}: ... 10 | case {1.0: 1, True: 2}: ... | | 7 | case {True: 1, True: 2}: ... 8 | case {None: 1, None: 2}: ... 9 | case {0: 1, False: 2}: ... | ^^^^^ Syntax Error: mapping pattern checks duplicate key `False` 10 | case {1.0: 1, True: 2}: ... 11 | case {-0: 1, False: 2}: ... | | 8 | case {None: 1, None: 2}: ... 9 | case {0: 1, False: 2}: ... 10 | case {1.0: 1, True: 2}: ... | ^^^^ Syntax Error: mapping pattern checks duplicate key `True` 11 | case {-0: 1, False: 2}: ... 12 | case {1 + 0j: 1, True: 2}: ... | | 9 | case {0: 1, False: 2}: ... 10 | case {1.0: 1, True: 2}: ... 11 | case {-0: 1, False: 2}: ... | ^^^^^ Syntax Error: mapping pattern checks duplicate key `False` 12 | case {1 + 0j: 1, True: 2}: ... 13 | case { | | 10 | case {1.0: 1, True: 2}: ... 11 | case {-0: 1, False: 2}: ... 12 | case {1 + 0j: 1, True: 2}: ... | ^^^^ Syntax Error: mapping pattern checks duplicate key `True` 13 | case { 14 | """x | | 16 | z 17 | """: 1, 18 | / """x 19 | | y 20 | | z 21 | | """: 2}: ... | |_______^ Syntax Error: mapping pattern checks duplicate key `"""x\n y\n z\n """` 22 | case {"x": 1, "x": 2, "x": 3}: ... 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... | | 20 | z 21 | """: 2}: ... 22 | case {"x": 1, "x": 2, "x": 3}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... 24 | case [{"x": 1, "x": 2}]: ... | | 20 | z 21 | """: 2}: ... 22 | case {"x": 1, "x": 2, "x": 3}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... 24 | case [{"x": 1, "x": 2}]: ... | | 21 | """: 2}: ... 22 | case {"x": 1, "x": 2, "x": 3}: ... 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... | ^ Syntax Error: mapping pattern checks duplicate key `0` 24 | case [{"x": 1, "x": 2}]: ... 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... | | 21 | """: 2}: ... 22 | case {"x": 1, "x": 2, "x": 3}: ... 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 24 | case [{"x": 1, "x": 2}]: ... 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... | | 22 | case {"x": 1, "x": 2, "x": 3}: ... 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... 24 | case [{"x": 1, "x": 2}]: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... 26 | case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... | | 23 | case {0: 1, "x": 1, 0: 2, "x": 2}: ... 24 | case [{"x": 1, "x": 2}]: ... 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 26 | case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... 27 | case {2: 1, 2.0: 2}: ... | | 24 | case [{"x": 1, "x": 2}]: ... 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... 26 | case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `"x"` 27 | case {2: 1, 2.0: 2}: ... 28 | case {9007199254740993: 1, 9007199254740993 + 0j: 2}: ... | | 25 | case Foo(x=1, y={"x": 1, "x": 2}): ... 26 | case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ... 27 | case {2: 1, 2.0: 2}: ... | ^^^ Syntax Error: mapping pattern checks duplicate key `2.0` 28 | case {9007199254740993: 1, 9007199254740993 + 0j: 2}: ... | invalid_syntax@duplicate_type_parameter_names.py.snap000064400000000000000000000723211046102023000345030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/duplicate_type_parameter_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..261, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..22, name: Name( ExprName { node_index: NodeIndex(None), range: 5..10, id: Name("Alias"), ctx: Store, }, ), type_params: Some( TypeParams { range: 10..16, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 11..12, name: Identifier { id: Name("T"), range: 11..12, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 14..15, name: Identifier { id: Name("T"), range: 14..15, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..45, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 27..28, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 28..34, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 29..30, name: Identifier { id: Name("T"), range: 29..30, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 32..33, name: Identifier { id: Name("T"), range: 32..33, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 34..40, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 35..39, node_index: NodeIndex(None), parameter: Parameter { range: 35..39, node_index: NodeIndex(None), name: Identifier { id: Name("t"), range: 35..36, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("T"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 42..45, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 42..45, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 46..64, decorator_list: [], name: Identifier { id: Name("C"), range: 52..53, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 53..59, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 54..55, name: Identifier { id: Name("T"), range: 54..55, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 57..58, name: Identifier { id: Name("T"), range: 57..58, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 61..64, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 61..64, }, ), }, ), ], }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 65..132, name: Name( ExprName { node_index: NodeIndex(None), range: 70..75, id: Name("Alias"), ctx: Store, }, ), type_params: Some( TypeParams { range: 75..126, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 76..77, name: Identifier { id: Name("T"), range: 76..77, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 79..85, name: Identifier { id: Name("U"), range: 79..80, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 82..85, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 87..102, name: Identifier { id: Name("V"), range: 87..88, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 90..102, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 91..94, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 96..101, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 104..107, name: Identifier { id: Name("Ts"), range: 105..107, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 109..112, name: Identifier { id: Name("P"), range: 111..112, node_index: NodeIndex(None), }, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 114..125, name: Identifier { id: Name("T"), range: 114..115, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 118..125, id: Name("default"), ctx: Load, }, ), ), }, ), ], }, ), value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 129..132, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 133..154, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 137..138, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 138..147, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 139..140, name: Identifier { id: Name("T"), range: 139..140, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 142..143, name: Identifier { id: Name("T"), range: 142..143, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 145..146, name: Identifier { id: Name("T"), range: 145..146, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 147..149, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 151..154, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 151..154, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 169..188, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 173..174, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 174..181, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 175..176, name: Identifier { id: Name("T"), range: 175..176, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 178..180, name: Identifier { id: Name("T"), range: 179..180, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 181..183, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 185..188, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 185..188, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 218..238, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 222..223, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 223..231, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 224..225, name: Identifier { id: Name("T"), range: 224..225, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 227..230, name: Identifier { id: Name("T"), range: 229..230, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 231..233, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 235..238, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 235..238, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | type Alias[T, T] = ... | ^ Syntax Error: duplicate type parameter 2 | def f[T, T](t: T): ... 3 | class C[T, T]: ... | | 1 | type Alias[T, T] = ... 2 | def f[T, T](t: T): ... | ^ Syntax Error: duplicate type parameter 3 | class C[T, T]: ... 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... | | 1 | type Alias[T, T] = ... 2 | def f[T, T](t: T): ... 3 | class C[T, T]: ... | ^ Syntax Error: duplicate type parameter 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... 5 | def f[T, T, T](): ... # two errors | | 2 | def f[T, T](t: T): ... 3 | class C[T, T]: ... 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... | ^^^^^^^^^^^ Syntax Error: duplicate type parameter 5 | def f[T, T, T](): ... # two errors 6 | def f[T, *T](): ... # star is still duplicate | | 3 | class C[T, T]: ... 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... 5 | def f[T, T, T](): ... # two errors | ^ Syntax Error: duplicate type parameter 6 | def f[T, *T](): ... # star is still duplicate 7 | def f[T, **T](): ... # as is double star | | 3 | class C[T, T]: ... 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... 5 | def f[T, T, T](): ... # two errors | ^ Syntax Error: duplicate type parameter 6 | def f[T, *T](): ... # star is still duplicate 7 | def f[T, **T](): ... # as is double star | | 4 | type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ... 5 | def f[T, T, T](): ... # two errors 6 | def f[T, *T](): ... # star is still duplicate | ^^ Syntax Error: duplicate type parameter 7 | def f[T, **T](): ... # as is double star | | 5 | def f[T, T, T](): ... # two errors 6 | def f[T, *T](): ... # star is still duplicate 7 | def f[T, **T](): ... # as is double star | ^^^ Syntax Error: duplicate type parameter invalid_syntax@except_star_py310.py.snap000064400000000000000000000147261046102023000315270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_star_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..126, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 44..125, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 53..76, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 61..71, id: Name("ValueError"), ctx: Load, }, ), ), name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 73..76, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 73..76, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 77..98, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 85..93, id: Name("KeyError"), ctx: Load, }, ), ), name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 95..98, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 95..98, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 99..125, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 115..120, id: Name("Error"), ctx: Load, }, ), ), name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 122..125, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 122..125, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.10"} 2 | try: ... 3 | except* ValueError: ... | ^ Syntax Error: Cannot use `except*` on Python 3.10 (syntax was added in Python 3.11) 4 | except* KeyError: ... 5 | except * Error: ... | | 2 | try: ... 3 | except* ValueError: ... 4 | except* KeyError: ... | ^ Syntax Error: Cannot use `except*` on Python 3.10 (syntax was added in Python 3.11) 5 | except * Error: ... | | 3 | except* ValueError: ... 4 | except* KeyError: ... 5 | except * Error: ... | ^ Syntax Error: Cannot use `except*` on Python 3.10 (syntax was added in Python 3.11) invalid_syntax@except_stmt_invalid_expression.py.snap000064400000000000000000000117571046102023000345770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_invalid_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..74, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..38, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..38, node_index: NodeIndex(None), type_: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 21..28, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Load, }, ), ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 34..38, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 39..73, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 48..52, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 53..73, node_index: NodeIndex(None), type_: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 61..63, value: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 69..73, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | except yield x: | ^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | pass 5 | try: | | 5 | try: 6 | pass 7 | except* *x: | ^^ Syntax Error: Starred expression cannot be used here 8 | pass | invalid_syntax@except_stmt_missing_as_name.py.snap000064400000000000000000000070161046102023000340170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_missing_as_name.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..72, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..43, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 21..30, id: Name("Exception"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 39..43, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 44..72, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 51..60, id: Name("Exception"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 68..72, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | except Exception as: | ^ Syntax Error: Expected name after `as` 4 | pass 5 | except Exception as | | 3 | except Exception as: 4 | pass 5 | except Exception as | ^ Syntax Error: Expected name after `as` 6 | pass | invalid_syntax@except_stmt_missing_exception.py.snap000064400000000000000000000131021046102023000344030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_missing_exception.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..166, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..37, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..37, node_index: NodeIndex(None), type_: None, name: Some( Identifier { id: Name("exc"), range: 24..27, node_index: NodeIndex(None), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 33..37, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 92..165, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 101..105, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 106..123, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 119..123, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 124..140, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 136..140, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 141..165, node_index: NodeIndex(None), type_: None, name: Some( Identifier { id: Name("exc"), range: 152..155, node_index: NodeIndex(None), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 161..165, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | except as exc: | ^^ Syntax Error: Expected one or more exception types 4 | pass 5 | # If a '*' is present then exception type is required | | 6 | try: 7 | pass 8 | except*: | ^ Syntax Error: Expected one or more exception types 9 | pass 10 | except* | | 8 | except*: 9 | pass 10 | except* | ^ Syntax Error: Expected one or more exception types 11 | pass 12 | except* as exc: 13 | pass | | 10 | except* 11 | pass 12 | except* as exc: | ^^ Syntax Error: Expected one or more exception types 13 | pass | invalid_syntax@except_stmt_missing_exception_and_as_name.py.snap000064400000000000000000000035331046102023000367170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_missing_exception_and_as_name.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..34, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..33, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..33, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 29..33, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | except as: | ^^ Syntax Error: Expected one or more exception types 4 | pass | | 1 | try: 2 | pass 3 | except as: | ^ Syntax Error: Expected name after `as` 4 | pass | invalid_syntax@except_stmt_unparenthesized_tuple_as.py.snap000064400000000000000000000157111046102023000357700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_unparenthesized_tuple_as.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..86, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..42, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..42, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 21..25, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: Some( Identifier { id: Name("exc"), range: 29..32, node_index: NodeIndex(None), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 38..42, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 43..85, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 52..56, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 57..85, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 65..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: Some( Identifier { id: Name("eg"), range: 73..75, node_index: NodeIndex(None), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 81..85, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | except x, y as exc: | ^^^^ Syntax Error: Multiple exception types must be parenthesized when using `as` 4 | pass 5 | try: | | 5 | try: 6 | pass 7 | except* x, y as eg: | ^^^^ Syntax Error: Multiple exception types must be parenthesized when using `as` 8 | pass | invalid_syntax@except_stmt_unparenthesized_tuple_no_as_py313.py.snap000064400000000000000000000147101046102023000374210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/except_stmt_unparenthesized_tuple_no_as_py313.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..117, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 44..79, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 53..57, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 58..79, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 65..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 75..79, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 80..116, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 89..93, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 94..116, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 102..106, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 112..116, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` ## Unsupported Syntax Errors | 2 | try: 3 | pass 4 | except x, y: | ^^^^ Syntax Error: Multiple exception types must be parenthesized on Python 3.13 (syntax was added in Python 3.14) 5 | pass 6 | try: | | 6 | try: 7 | pass 8 | except* x, y: | ^^^^ Syntax Error: Multiple exception types must be parenthesized on Python 3.13 (syntax was added in Python 3.14) 9 | pass | invalid_syntax@expressions__arguments__double_starred.py.snap000064400000000000000000000234671046102023000362770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/double_starred.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..55, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..15, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..15, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 5..14, node_index: NodeIndex(None), arg: None, value: Yield( ExprYield { node_index: NodeIndex(None), range: 7..14, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Load, }, ), ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..27, value: Call( ExprCall { node_index: NodeIndex(None), range: 16..27, func: Name( ExprName { node_index: NodeIndex(None), range: 16..20, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 20..27, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 21..26, node_index: NodeIndex(None), arg: None, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 24..26, value: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..38, value: Call( ExprCall { node_index: NodeIndex(None), range: 28..38, func: Name( ExprName { node_index: NodeIndex(None), range: 28..32, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 32..38, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 33..37, node_index: NodeIndex(None), arg: None, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 35..37, value: Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 40..54, value: Call( ExprCall { node_index: NodeIndex(None), range: 40..54, func: Name( ExprName { node_index: NodeIndex(None), range: 40..44, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 44..54, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 1, ), }, ), ], keywords: [ Keyword { range: 45..48, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(**yield x) | ^^^^^^^ Syntax Error: Yield expression cannot be used here 2 | call(** *x) 3 | call(***x) | | 1 | call(**yield x) 2 | call(** *x) | ^^ Syntax Error: Starred expression cannot be used here 3 | call(***x) | | 1 | call(**yield x) 2 | call(** *x) 3 | call(***x) | ^^ Syntax Error: Starred expression cannot be used here 4 | 5 | call(**x := 1) | | 3 | call(***x) 4 | 5 | call(**x := 1) | ^^ Syntax Error: Expected `,`, found `:=` | 3 | call(***x) 4 | 5 | call(**x := 1) | ^ Syntax Error: Positional argument cannot follow keyword argument unpacking invalid_syntax@expressions__arguments__duplicate_keyword_arguments.py.snap000064400000000000000000000161141046102023000410730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/duplicate_keyword_arguments.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..28, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..28, func: Name( ExprName { node_index: NodeIndex(None), range: 0..3, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 3..28, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 4..7, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 4..5, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 1, ), }, ), }, Keyword { range: 9..12, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("b"), range: 9..10, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 2, ), }, ), }, Keyword { range: 14..17, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("c"), range: 14..15, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 3, ), }, ), }, Keyword { range: 19..22, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("b"), range: 19..20, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 4, ), }, ), }, Keyword { range: 24..27, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 24..25, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..27, value: Int( 5, ), }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | foo(a=1, b=2, c=3, b=4, a=5) | ^^^ Syntax Error: Duplicate keyword argument "b" | 1 | foo(a=1, b=2, c=3, b=4, a=5) | ^^^ Syntax Error: Duplicate keyword argument "a" invalid_syntax@expressions__arguments__invalid_expression.py.snap000064400000000000000000000215051046102023000371750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/invalid_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..15, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..15, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 5..14, node_index: NodeIndex(None), arg: Some( Identifier { id: Name(""), range: 5..10, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..32, value: Call( ExprCall { node_index: NodeIndex(None), range: 16..32, func: Name( ExprName { node_index: NodeIndex(None), range: 16..20, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 20..32, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 21..31, node_index: NodeIndex(None), arg: Some( Identifier { id: Name(""), range: 21..27, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..47, value: Call( ExprCall { node_index: NodeIndex(None), range: 34..47, func: Name( ExprName { node_index: NodeIndex(None), range: 34..38, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 38..47, node_index: NodeIndex(None), args: [ Yield( ExprYield { node_index: NodeIndex(None), range: 39..46, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("x"), ctx: Load, }, ), ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 48..66, value: Call( ExprCall { node_index: NodeIndex(None), range: 48..66, func: Name( ExprName { node_index: NodeIndex(None), range: 48..52, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 52..66, node_index: NodeIndex(None), args: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 53..65, value: Name( ExprName { node_index: NodeIndex(None), range: 64..65, id: Name("x"), ctx: Load, }, ), }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(x + y = 1) | ^^^^^ Syntax Error: Expected a parameter name 2 | call(x := 1 = 1) | | 1 | call(x + y = 1) 2 | call(x := 1 = 1) | ^^^^^^ Syntax Error: Expected a parameter name 3 | 4 | call(yield x) | | 2 | call(x := 1 = 1) 3 | 4 | call(yield x) | ^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | call(yield from x) | | 4 | call(yield x) 5 | call(yield from x) | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@expressions__arguments__invalid_keyword_expression.py.snap000064400000000000000000000260751046102023000407500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/invalid_keyword_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..69, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..17, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..17, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 5..16, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), value: Yield( ExprYield { node_index: NodeIndex(None), range: 9..16, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("y"), ctx: Load, }, ), ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..40, value: Call( ExprCall { node_index: NodeIndex(None), range: 18..40, func: Name( ExprName { node_index: NodeIndex(None), range: 18..22, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 22..40, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 23..39, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 23..24, node_index: NodeIndex(None), }, ), value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 27..39, value: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 41..53, value: Call( ExprCall { node_index: NodeIndex(None), range: 41..53, func: Name( ExprName { node_index: NodeIndex(None), range: 41..45, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 45..53, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 46..52, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 46..47, node_index: NodeIndex(None), }, ), value: Starred( ExprStarred { node_index: NodeIndex(None), range: 50..52, value: Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 54..68, value: Call( ExprCall { node_index: NodeIndex(None), range: 54..68, func: Name( ExprName { node_index: NodeIndex(None), range: 54..58, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 58..68, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 59..67, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 59..60, node_index: NodeIndex(None), }, ), value: Starred( ExprStarred { node_index: NodeIndex(None), range: 64..66, value: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(x = yield y) | ^^^^^^^ Syntax Error: Yield expression cannot be used here 2 | call(x = yield from y) 3 | call(x = *y) | | 1 | call(x = yield y) 2 | call(x = yield from y) | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | call(x = *y) 4 | call(x = (*y)) | | 1 | call(x = yield y) 2 | call(x = yield from y) 3 | call(x = *y) | ^^ Syntax Error: Starred expression cannot be used here 4 | call(x = (*y)) | | 2 | call(x = yield from y) 3 | call(x = *y) 4 | call(x = (*y)) | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__arguments__invalid_order.py.snap000064400000000000000000000350251046102023000361130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/invalid_order.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..100, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..17, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..17, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("x"), ctx: Load, }, ), ], keywords: [ Keyword { range: 5..13, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 7..13, id: Name("kwargs"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..30, value: Call( ExprCall { node_index: NodeIndex(None), range: 18..30, func: Name( ExprName { node_index: NodeIndex(None), range: 18..22, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 22..30, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("y"), ctx: Load, }, ), ], keywords: [ Keyword { range: 23..26, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 23..24, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 31..53, value: Call( ExprCall { node_index: NodeIndex(None), range: 31..53, func: Name( ExprName { node_index: NodeIndex(None), range: 31..35, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 35..53, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("y"), ctx: Load, }, ), ], keywords: [ Keyword { range: 36..39, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 36..37, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 1, ), }, ), }, Keyword { range: 41..49, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 43..49, id: Name("kwargs"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 54..75, value: Call( ExprCall { node_index: NodeIndex(None), range: 54..75, func: Name( ExprName { node_index: NodeIndex(None), range: 54..58, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 58..75, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 69..74, value: Name( ExprName { node_index: NodeIndex(None), range: 70..74, id: Name("args"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 59..67, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 61..67, id: Name("kwargs"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..99, value: Call( ExprCall { node_index: NodeIndex(None), range: 76..99, func: Name( ExprName { node_index: NodeIndex(None), range: 76..80, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 80..99, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 92..97, value: Name( ExprName { node_index: NodeIndex(None), range: 93..97, id: Name("args"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 81..89, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 83..89, id: Name("kwargs"), ctx: Load, }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(**kwargs, x) | ^ Syntax Error: Positional argument cannot follow keyword argument unpacking 2 | call(x=1, y) 3 | call(x=1, **kwargs, y) | | 1 | call(**kwargs, x) 2 | call(x=1, y) | ^ Syntax Error: Positional argument cannot follow keyword argument 3 | call(x=1, **kwargs, y) 4 | call(**kwargs, *args) | | 1 | call(**kwargs, x) 2 | call(x=1, y) 3 | call(x=1, **kwargs, y) | ^ Syntax Error: Positional argument cannot follow keyword argument unpacking 4 | call(**kwargs, *args) 5 | call(**kwargs, (*args)) | | 2 | call(x=1, y) 3 | call(x=1, **kwargs, y) 4 | call(**kwargs, *args) | ^^^^^ Syntax Error: Iterable argument unpacking cannot follow keyword argument unpacking 5 | call(**kwargs, (*args)) | | 3 | call(x=1, **kwargs, y) 4 | call(**kwargs, *args) 5 | call(**kwargs, (*args)) | ^^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__arguments__missing_argument.py.snap000064400000000000000000000043411046102023000366420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/missing_argument.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..10, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..10, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("y"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(x,,y) | ^ Syntax Error: Expected an expression or a ')' invalid_syntax@expressions__arguments__missing_comma.py.snap000064400000000000000000000043221046102023000361130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/missing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..9, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..9, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..9, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("y"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(x y) | ^ Syntax Error: Expected `,`, found name invalid_syntax@expressions__arguments__missing_expression.py.snap000064400000000000000000000157021046102023000372220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/missing_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..38, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..10, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..10, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 1, ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..21, value: Call( ExprCall { node_index: NodeIndex(None), range: 11..21, func: Name( ExprName { node_index: NodeIndex(None), range: 11..15, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 15..21, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 16..19, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 16..17, node_index: NodeIndex(None), }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 19..19, id: Name(""), ctx: Invalid, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..32, value: Call( ExprCall { node_index: NodeIndex(None), range: 22..32, func: Name( ExprName { node_index: NodeIndex(None), range: 22..26, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 26..32, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 27..28, value: Name( ExprName { node_index: NodeIndex(None), range: 28..28, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 30..31, id: Name("y"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..37, value: Name( ExprName { node_index: NodeIndex(None), range: 34..37, id: Name("foo"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | call( = 1) | ^ Syntax Error: Expected an expression or a ')' 2 | call(x = ) 3 | call(*, y) | | 1 | call( = 1) 2 | call(x = ) | ^ Syntax Error: Expected an expression 3 | call(*, y) | | 1 | call( = 1) 2 | call(x = ) 3 | call(*, y) | ^ Syntax Error: Expected an expression 4 | 5 | foo | invalid_syntax@expressions__arguments__starred.py.snap000064400000000000000000000230111046102023000347260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/starred.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..28, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..28, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..28, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 5..27, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 5..10, value: Name( ExprName { node_index: NodeIndex(None), range: 6..10, id: Name("data"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 11..27, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 15..19, id: Name("data"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 23..27, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 29..43, value: Call( ExprCall { node_index: NodeIndex(None), range: 29..43, func: Name( ExprName { node_index: NodeIndex(None), range: 29..33, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 33..43, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 34..42, value: Yield( ExprYield { node_index: NodeIndex(None), range: 35..42, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 44..63, value: Call( ExprCall { node_index: NodeIndex(None), range: 44..63, func: Name( ExprName { node_index: NodeIndex(None), range: 44..48, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 48..63, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 49..62, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 50..62, value: Name( ExprName { node_index: NodeIndex(None), range: 61..62, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | call(*data for data in iter) 2 | call(*yield x) | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | call(*yield from x) | | 1 | call(*data for data in iter) 2 | call(*yield x) 3 | call(*yield from x) | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here ## Unsupported Syntax Errors | 1 | call(*data for data in iter) | ^^^^^ Syntax Error: Cannot use iterable unpacking in a generator expression on Python 3.14 (syntax was added in Python 3.15) 2 | call(*yield x) 3 | call(*yield from x) | invalid_syntax@expressions__arguments__unclosed_0.py.snap000064400000000000000000000050201046102023000353150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..26, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..5, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..5, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 7..26, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 11..14, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 14..16, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 22..26, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | call( | ^ Syntax Error: Expected `)`, found newline 2 | 3 | def foo(): 4 | pass | invalid_syntax@expressions__arguments__unclosed_1.py.snap000064400000000000000000000057261046102023000353330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..27, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..6, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..6, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..6, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 8..27, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 12..15, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 15..17, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 23..27, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | call(x | ^ Syntax Error: Expected `)`, found newline 2 | 3 | def foo(): 4 | pass | invalid_syntax@expressions__arguments__unclosed_2.py.snap000064400000000000000000000057301046102023000353270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/arguments/unclosed_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..7, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..7, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 9..28, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 13..16, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 16..18, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 24..28, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | call(x, | ^ Syntax Error: Expected `)`, found newline 2 | 3 | def foo(): 4 | pass | invalid_syntax@expressions__attribute__invalid_member.py.snap000064400000000000000000000116671046102023000362530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/attribute/invalid_member.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..16, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..1, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1..3, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1..3, value: Float( 0.1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 4..5, value: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..7, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..7, value: Float( 0.1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..9, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..9, value: Float( 0.0, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..15, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 10..15, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 10..12, value: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 12..12, node_index: NodeIndex(None), }, ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 0, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x.1 | ^^ Syntax Error: Simple statements must be separated by newlines or semicolons 2 | x.1.0 3 | x.[0] | | 1 | x.1 2 | x.1.0 | ^^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | x.[0] | | 1 | x.1 2 | x.1.0 | ^^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | x.[0] | | 1 | x.1 2 | x.1.0 3 | x.[0] | ^ Syntax Error: Expected an identifier invalid_syntax@expressions__attribute__multiple_dots.py.snap000064400000000000000000000136111046102023000361510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/attribute/multiple_dots.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 0..10, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 0..6, value: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("extra"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 6..6, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("dot"), range: 7..10, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..19, value: Name( ExprName { node_index: NodeIndex(None), range: 11..19, id: Name("multiple"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..27, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 19..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), attr: Identifier { id: Name("dots"), range: 23..27, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..36, value: Name( ExprName { node_index: NodeIndex(None), range: 28..36, id: Name("multiple"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 36..45, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 36..45, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 36..40, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 36..39, }, ), attr: Identifier { id: Name(""), range: 40..40, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("dots"), range: 41..45, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | extra..dot | ^ Syntax Error: Expected an identifier 2 | multiple....dots 3 | multiple.....dots | | 1 | extra..dot 2 | multiple....dots | ^^^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | multiple.....dots | | 1 | extra..dot 2 | multiple....dots 3 | multiple.....dots | ^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 1 | extra..dot 2 | multiple....dots 3 | multiple.....dots | ^ Syntax Error: Expected an identifier invalid_syntax@expressions__attribute__no_member.py.snap000064400000000000000000000061151046102023000352310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/attribute/no_member.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..141, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 87..93, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 87..93, value: Name( ExprName { node_index: NodeIndex(None), range: 87..92, id: Name("first"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 93..93, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 94..100, value: Name( ExprName { node_index: NodeIndex(None), range: 94..100, id: Name("second"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 136..141, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 136..141, value: Name( ExprName { node_index: NodeIndex(None), range: 136..140, id: Name("last"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 141..141, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # The `second` is a variable on another line and not part of the attribute expression. 2 | first. | ^ Syntax Error: Expected an identifier 3 | second 4 | 5 | # No member access after the dot. | | 5 | # No member access after the dot. 6 | last. | ^ Syntax Error: Expected an identifier invalid_syntax@expressions__await__no_expression_0.py.snap000064400000000000000000000044441046102023000355050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/await/no_expression_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 61..66, value: Await( ExprAwait { node_index: NodeIndex(None), range: 61..66, value: Name( ExprName { node_index: NodeIndex(None), range: 66..66, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..73, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 68..73, left: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # No expression after `await`, an expression on another line 2 | await | ^ Syntax Error: Expected an expression 3 | 4 | x + y | invalid_syntax@expressions__await__no_expression_1.py.snap000064400000000000000000000045001046102023000354770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/await/no_expression_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 59..64, value: Await( ExprAwait { node_index: NodeIndex(None), range: 59..64, value: Name( ExprName { node_index: NodeIndex(None), range: 64..64, id: Name(""), ctx: Invalid, }, ), }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 66..85, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 70..73, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 73..75, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 81..85, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # No expression after `await`, a statement on another line 2 | await | ^ Syntax Error: Expected an expression 3 | 4 | def foo(): 5 | pass | invalid_syntax@expressions__await__recover.py.snap000064400000000000000000000325511046102023000340400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/await/recover.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..284, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 117..130, value: Await( ExprAwait { node_index: NodeIndex(None), range: 117..130, value: Await( ExprAwait { node_index: NodeIndex(None), range: 123..130, value: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 154..162, value: Await( ExprAwait { node_index: NodeIndex(None), range: 154..162, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 160..162, value: Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 163..173, value: Await( ExprAwait { node_index: NodeIndex(None), range: 163..173, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 170..172, value: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 214..227, value: Await( ExprAwait { node_index: NodeIndex(None), range: 214..227, value: Yield( ExprYield { node_index: NodeIndex(None), range: 220..227, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 226..227, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 228..245, value: Await( ExprAwait { node_index: NodeIndex(None), range: 228..245, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 234..245, parameters: Some( Parameters { range: 241..242, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 241..242, node_index: NodeIndex(None), parameter: Parameter { range: 241..242, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 241..242, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 244..245, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 246..254, value: Await( ExprAwait { node_index: NodeIndex(None), range: 246..254, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 252..254, op: UAdd, operand: Name( ExprName { node_index: NodeIndex(None), range: 253..254, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 255..263, value: Await( ExprAwait { node_index: NodeIndex(None), range: 255..263, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 261..263, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 262..263, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 264..272, value: Await( ExprAwait { node_index: NodeIndex(None), range: 264..272, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 270..272, op: Invert, operand: Name( ExprName { node_index: NodeIndex(None), range: 271..272, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 273..284, value: Await( ExprAwait { node_index: NodeIndex(None), range: 273..284, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 279..284, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 283..284, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 4 | # Nested await 5 | await await x | ^^^^^^^ Syntax Error: Await expression cannot be used here 6 | 7 | # Starred expressions | | 7 | # Starred expressions 8 | await *x | ^^ Syntax Error: Starred expression cannot be used here 9 | await (*x) | | 7 | # Starred expressions 8 | await *x 9 | await (*x) | ^^ Syntax Error: Starred expression cannot be used here 10 | 11 | # Invalid expression as per precedence | | 11 | # Invalid expression as per precedence 12 | await yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 13 | await lambda x: x 14 | await +x | | 11 | # Invalid expression as per precedence 12 | await yield x 13 | await lambda x: x | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 14 | await +x 15 | await -x | | 12 | await yield x 13 | await lambda x: x 14 | await +x | ^^ Syntax Error: Unary '+' expression cannot be used here 15 | await -x 16 | await ~x | | 13 | await lambda x: x 14 | await +x 15 | await -x | ^^ Syntax Error: Unary '-' expression cannot be used here 16 | await ~x 17 | await not x | | 14 | await +x 15 | await -x 16 | await ~x | ^^ Syntax Error: Unary '~' expression cannot be used here 17 | await not x | | 15 | await -x 16 | await ~x 17 | await not x | ^^^^^ Syntax Error: Boolean 'not' expression cannot be used here invalid_syntax@expressions__bin_op__invalid_rhs_expression.py.snap000064400000000000000000000123251046102023000373120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/invalid_rhs_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..15, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), op: Add, right: Lambda( ExprLambda { node_index: NodeIndex(None), range: 4..15, parameters: Some( Parameters { range: 11..12, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 11..12, node_index: NodeIndex(None), parameter: Parameter { range: 11..12, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 11..12, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 17..28, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 17..28, left: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Load, }, ), op: Sub, right: Yield( ExprYield { node_index: NodeIndex(None), range: 21..28, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("y"), ctx: Load, }, ), ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x + lambda y: y | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 2 | 3 | x - yield y | | 1 | x + lambda y: y 2 | 3 | x - yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@expressions__bin_op__missing_lhs.py.snap000064400000000000000000000040241046102023000350450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_lhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("y"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | / y | ^ Syntax Error: Expected a statement 2 | 3 | 1 + 2 | invalid_syntax@expressions__bin_op__missing_rhs_0.py.snap000064400000000000000000000053671046102023000353050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_rhs_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..3, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 0..1, value: Int( 0, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | 0 + | ^ Syntax Error: Expected an expression 2 | 3 | 1 + 2 | invalid_syntax@expressions__bin_op__missing_rhs_1.py.snap000064400000000000000000000107161046102023000353000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/missing_rhs_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..18, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..11, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..5, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 0..1, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 2, ), }, ), }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 8..11, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 3, ), }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 11..11, id: Name(""), ctx: Invalid, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..18, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 13..18, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 4, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..18, value: Int( 5, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | 1 + 2 - 3 * | ^ Syntax Error: Expected an expression 2 | 3 | 4 + 5 | invalid_syntax@expressions__bin_op__multiple_ops.py.snap000064400000000000000000000136051046102023000352470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/multiple_ops.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..19, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..3, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), op: Add, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 2..3, op: UAdd, operand: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 4..9, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4..9, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..13, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 10..13, left: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Load, }, ), op: Sub, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 12..13, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 13..13, id: Name(""), ctx: Invalid, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 14..19, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 14..19, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 14..15, value: Int( 1, ), }, ), op: Sub, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x++ | ^ Syntax Error: Expected an expression 2 | 1 + 2 3 | x-- 4 | 1 - 2 | | 1 | x++ 2 | 1 + 2 3 | x-- | ^ Syntax Error: Expected an expression 4 | 1 - 2 | invalid_syntax@expressions__bin_op__named_expression.py.snap000064400000000000000000000111261046102023000360720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/named_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..26, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..5, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), op: Sub, right: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..15, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 9..15, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..21, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 16..21, left: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Load, }, ), op: Div, right: Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 25..26, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 2, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x - y := (1, 2) | ^^ Syntax Error: Expected a statement 2 | x / y := 2 | | 1 | x - y := (1, 2) 2 | x / y := 2 | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__bin_op__starred_expression.py.snap000064400000000000000000000067221046102023000364600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bin_op/starred_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..14, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..6, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 0..6, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), op: Add, right: Starred( ExprStarred { node_index: NodeIndex(None), range: 4..6, value: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..14, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 7..14, left: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), op: Pow, right: Starred( ExprStarred { node_index: NodeIndex(None), range: 12..14, value: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x + *y | ^^ Syntax Error: Starred expression cannot be used here 2 | x ** *y | | 1 | x + *y 2 | x ** *y | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__bool_op__invalid_rhs_expression.py.snap000064400000000000000000000131661046102023000375010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bool_op/invalid_rhs_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 0..17, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), Lambda( ExprLambda { node_index: NodeIndex(None), range: 6..17, parameters: Some( Parameters { range: 13..14, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 13..14, node_index: NodeIndex(None), parameter: Parameter { range: 13..14, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 13..14, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..31, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 19..31, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("x"), ctx: Load, }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 24..31, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 30..31, id: Name("y"), ctx: Load, }, ), ), }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 1 | x and lambda y: y | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 2 | 3 | x or yield y | | 1 | x and lambda y: y 2 | 3 | x or yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@expressions__bool_op__missing_lhs.py.snap000064400000000000000000000014541046102023000352340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bool_op/missing_lhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..5, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4..5, value: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("y"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | and y | ^^^ Syntax Error: Expected a statement invalid_syntax@expressions__bool_op__missing_rhs.py.snap000064400000000000000000000055031046102023000352410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bool_op/missing_rhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..12, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 0..5, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 5..5, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..12, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 7..12, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x and | ^ Syntax Error: Expected an expression 2 | 3 | 1 + 2 | invalid_syntax@expressions__bool_op__named_expression.py.snap000064400000000000000000000075401046102023000362620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bool_op/named_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 0..7, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("a"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..12, value: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("b"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..19, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 13..19, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("a"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..24, value: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("b"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x and a := b | ^^ Syntax Error: Expected a statement 2 | x or a := b | | 1 | x and a := b 2 | x or a := b | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__bool_op__starred_expression.py.snap000064400000000000000000000074051046102023000366420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/bool_op/starred_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..16, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 0..8, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 6..8, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..16, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 9..16, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 14..16, value: Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 1 | x and *y | ^^ Syntax Error: Starred expression cannot be used here 2 | x or *y | | 1 | x and *y 2 | x or *y | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__compare__invalid_order.py.snap000064400000000000000000000143071046102023000355340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/invalid_order.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..131, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..10, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 5..10, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 35..41, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("x"), ctx: Store, }, ), ], value: Compare( ExprCompare { node_index: NodeIndex(None), range: 38..41, left: Name( ExprName { node_index: NodeIndex(None), range: 38..38, id: Name(""), ctx: Invalid, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 120..121, value: Name( ExprName { node_index: NodeIndex(None), range: 120..121, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 122..128, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 122..128, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 126..128, id: Name("is"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 129..130, value: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("y"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x in not y | ^^^^^ Syntax Error: Boolean 'not' expression cannot be used here 2 | 3 | # `=>` instead of `>=` | | 3 | # `=>` instead of `>=` 4 | x => y | ^ Syntax Error: Expected an expression 5 | 6 | # Same here as well, `not` without `in` is considered to be a unary operator | | 6 | # Same here as well, `not` without `in` is considered to be a unary operator 7 | x not is y | ^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 6 | # Same here as well, `not` without `in` is considered to be a unary operator 7 | x not is y | ^^ Syntax Error: Expected an identifier, but found a keyword `is` that cannot be used here | 6 | # Same here as well, `not` without `in` is considered to be a unary operator 7 | x not is y | ^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@expressions__compare__invalid_rhs_expression.py.snap000064400000000000000000000133371046102023000374760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/invalid_rhs_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..34, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..20, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..20, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 9..20, parameters: Some( Parameters { range: 16..17, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 16..17, node_index: NodeIndex(None), parameter: Parameter { range: 16..17, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 16..17, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..34, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 22..34, left: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Yield( ExprYield { node_index: NodeIndex(None), range: 27..34, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("y"), ctx: Load, }, ), ), }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 1 | x not in lambda y: y | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 2 | 3 | x == yield y | | 1 | x not in lambda y: y 2 | 3 | x == yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@expressions__compare__missing_lhs.py.snap000064400000000000000000000040251046102023000352260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/missing_lhs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("y"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | > y | ^ Syntax Error: Expected a statement 2 | 3 | 1 + 2 | invalid_syntax@expressions__compare__missing_rhs_0.py.snap000064400000000000000000000055561046102023000354650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/missing_rhs_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..3, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x > | ^ Syntax Error: Expected an expression 2 | 3 | 1 + 2 | invalid_syntax@expressions__compare__missing_rhs_1.py.snap000064400000000000000000000060671046102023000354640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/missing_rhs_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..71, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 59..60, value: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 61..64, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 61..64, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 64..64, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 66..71, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 66..71, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 66..67, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 70..71, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Without the `in`, this is considered to be a unary `not` 2 | x not | ^^^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | 4 | 1 + 2 | | 1 | # Without the `in`, this is considered to be a unary `not` 2 | x not | ^ Syntax Error: Expected an expression 3 | 4 | 1 + 2 | invalid_syntax@expressions__compare__missing_rhs_2.py.snap000064400000000000000000000056001046102023000354550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/missing_rhs_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..15, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..8, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 8..8, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..15, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 10..15, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 14..15, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x is not | ^ Syntax Error: Expected an expression 2 | 3 | 1 + 2 | invalid_syntax@expressions__compare__multiple_equals.py.snap000064400000000000000000000103021046102023000361070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/multiple_equals.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 25..32, targets: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 25..29, left: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 29..29, id: Name(""), ctx: Invalid, }, ), ], }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 31..32, id: Name("y"), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 33..40, targets: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 33..37, left: Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("x"), ctx: Load, }, ), ops: [ NotEq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 37..37, id: Name(""), ctx: Invalid, }, ), ], }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # This is not JavaScript 2 | x === y | ^ Syntax Error: Expected an expression 3 | x !== y | | 1 | # This is not JavaScript 2 | x === y | ^^^^ Syntax Error: Invalid assignment target 3 | x !== y | | 1 | # This is not JavaScript 2 | x === y 3 | x !== y | ^ Syntax Error: Expected an expression | 1 | # This is not JavaScript 2 | x === y 3 | x !== y | ^^^^ Syntax Error: Invalid assignment target invalid_syntax@expressions__compare__named_expression.py.snap000064400000000000000000000116761046102023000362640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/named_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..10, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 14..20, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 14..20, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 15..16, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..26, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 21..26, left: Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("x"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..31, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 2, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | x not in y := (1, 2) | ^^ Syntax Error: Expected a statement 2 | x > y := 2 | | 1 | x not in y := (1, 2) 2 | x > y := 2 | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__compare__starred_expression.py.snap000064400000000000000000000171551046102023000366420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/compare/starred_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..39, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..7, left: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), ops: [ GtE, ], comparators: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 5..7, value: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..19, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 8..19, left: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 17..19, value: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..27, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 21..27, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 22..27, left: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), ops: [ Lt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..39, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 28..39, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 29..39, left: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x >= *y | ^^ Syntax Error: Starred expression cannot be used here 2 | x not in *y | | 1 | x >= *y 2 | x not in *y | ^^ Syntax Error: Starred expression cannot be used here 3 | 4 | *x < y | | 2 | x not in *y 3 | 4 | *x < y | ^^^^^ Syntax Error: Comparison expression cannot be used here 5 | *x is not y | | 4 | *x < y 5 | *x is not y | ^^^^^^^^^^ Syntax Error: Comparison expression cannot be used here invalid_syntax@expressions__dict__comprehension.py.snap000064400000000000000000001267341046102023000350710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..362, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..34, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 17..34, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 23..33, node_index: NodeIndex(None), target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 1, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 35..54, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 35..54, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 41..53, node_index: NodeIndex(None), target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 45..48, value: StringLiteralValue { inner: Single( StringLiteral { range: 45..48, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 55..77, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 55..77, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 61..76, node_index: NodeIndex(None), target: Call( ExprCall { node_index: NodeIndex(None), range: 65..71, func: Name( ExprName { node_index: NodeIndex(None), range: 65..69, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 69..71, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 78..100, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 78..100, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 84..99, node_index: NodeIndex(None), target: Set( ExprSet { node_index: NodeIndex(None), range: 88..94, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("b"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 117..135, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 117..135, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 121..122, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 123..134, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("x"), ctx: Store, }, ), iter: Starred( ExprStarred { node_index: NodeIndex(None), range: 132..134, value: Name( ExprName { node_index: NodeIndex(None), range: 133..134, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 136..159, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 136..159, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 142..158, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 151..158, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 157..158, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 160..188, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 160..188, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 164..165, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 166..187, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 175..187, value: Name( ExprName { node_index: NodeIndex(None), range: 186..187, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 189..216, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 189..216, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 193..194, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 195..215, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 199..200, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 204..215, parameters: Some( Parameters { range: 211..212, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 211..212, node_index: NodeIndex(None), parameter: Parameter { range: 211..212, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 211..212, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 231..257, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 231..257, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 232..233, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 235..236, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 237..256, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 241..242, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 246..250, id: Name("data"), ctx: Load, }, ), ifs: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 254..256, value: Name( ExprName { node_index: NodeIndex(None), range: 255..256, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 258..289, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 258..289, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 262..263, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 264..288, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 268..269, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 273..277, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 281..288, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 290..326, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 290..326, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 291..292, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 294..295, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 296..325, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 300..301, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 305..309, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 313..325, value: Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 327..362, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 327..362, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 328..329, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 331..332, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 333..361, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 337..338, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 342..346, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 350..361, parameters: Some( Parameters { range: 357..358, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 357..358, node_index: NodeIndex(None), parameter: Parameter { range: 357..358, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 357..358, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 360..361, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # Invalid target 2 | {x: y for 1 in y} | ^ Syntax Error: Invalid assignment target 3 | {x: y for 'a' in y} 4 | {x: y for call() in y} | | 1 | # Invalid target 2 | {x: y for 1 in y} 3 | {x: y for 'a' in y} | ^^^ Syntax Error: Invalid assignment target 4 | {x: y for call() in y} 5 | {x: y for {a, b} in y} | | 2 | {x: y for 1 in y} 3 | {x: y for 'a' in y} 4 | {x: y for call() in y} | ^^^^^^ Syntax Error: Invalid assignment target 5 | {x: y for {a, b} in y} | | 3 | {x: y for 'a' in y} 4 | {x: y for call() in y} 5 | {x: y for {a, b} in y} | ^^^^^^ Syntax Error: Invalid assignment target 6 | 7 | # Invalid iter | | 7 | # Invalid iter 8 | {x: y for x in *y} | ^^ Syntax Error: Starred expression cannot be used here 9 | {x: y for x in yield y} 10 | {x: y for x in yield from y} | | 7 | # Invalid iter 8 | {x: y for x in *y} 9 | {x: y for x in yield y} | ^^^^^^^ Syntax Error: Yield expression cannot be used here 10 | {x: y for x in yield from y} 11 | {x: y for x in lambda y: y} | | 8 | {x: y for x in *y} 9 | {x: y for x in yield y} 10 | {x: y for x in yield from y} | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 11 | {x: y for x in lambda y: y} | | 9 | {x: y for x in yield y} 10 | {x: y for x in yield from y} 11 | {x: y for x in lambda y: y} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 12 | 13 | # Invalid if | | 13 | # Invalid if 14 | {x: y for x in data if *y} | ^^ Syntax Error: Starred expression cannot be used here 15 | {x: y for x in data if yield y} 16 | {x: y for x in data if yield from y} | | 13 | # Invalid if 14 | {x: y for x in data if *y} 15 | {x: y for x in data if yield y} | ^^^^^^^ Syntax Error: Yield expression cannot be used here 16 | {x: y for x in data if yield from y} 17 | {x: y for x in data if lambda y: y} | | 14 | {x: y for x in data if *y} 15 | {x: y for x in data if yield y} 16 | {x: y for x in data if yield from y} | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 17 | {x: y for x in data if lambda y: y} | | 15 | {x: y for x in data if yield y} 16 | {x: y for x in data if yield from y} 17 | {x: y for x in data if lambda y: y} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here invalid_syntax@expressions__dict__double_star.py.snap000064400000000000000000000700111046102023000345050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/double_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..278, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 125..135, value: Dict( ExprDict { node_index: NodeIndex(None), range: 125..135, items: [ DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Load, }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 133..134, value: Int( 1, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 134..134, id: Name(""), ctx: Invalid, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 136..162, value: Dict( ExprDict { node_index: NodeIndex(None), range: 136..162, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("a"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 140..141, value: Int( 1, ), }, ), }, DictItem { key: None, value: If( ExprIf { node_index: NodeIndex(None), range: 145..161, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 150..154, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 145..146, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 163..184, value: Dict( ExprDict { node_index: NodeIndex(None), range: 163..184, items: [ DictItem { key: None, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 166..177, parameters: Some( Parameters { range: 173..174, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 173..174, node_index: NodeIndex(None), parameter: Parameter { range: 173..174, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 173..174, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 176..177, id: Name("x"), ctx: Load, }, ), }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 179..180, id: Name("b"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 182..183, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 185..201, value: Dict( ExprDict { node_index: NodeIndex(None), range: 185..201, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 186..187, id: Name("a"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 189..190, value: Int( 1, ), }, ), }, DictItem { key: None, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 194..200, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 194..195, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 199..200, id: Name("y"), ctx: Load, }, ), ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 202..219, value: Dict( ExprDict { node_index: NodeIndex(None), range: 202..219, items: [ DictItem { key: None, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 205..212, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 205..206, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 211..212, id: Name("y"), ctx: Load, }, ), ], }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("b"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 217..218, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 220..241, value: Dict( ExprDict { node_index: NodeIndex(None), range: 220..241, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 221..222, id: Name("a"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 224..225, value: Int( 1, ), }, ), }, DictItem { key: None, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 229..234, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 233..234, id: Name("x"), ctx: Load, }, ), }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("b"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..240, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 242..252, value: Dict( ExprDict { node_index: NodeIndex(None), range: 242..252, items: [ DictItem { key: None, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 245..251, left: Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 250..251, id: Name("y"), ctx: Load, }, ), ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 253..267, value: Dict( ExprDict { node_index: NodeIndex(None), range: 253..267, items: [ DictItem { key: None, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 256..266, left: Name( ExprName { node_index: NodeIndex(None), range: 256..257, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("y"), ctx: Load, }, ), ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 268..277, value: Dict( ExprDict { node_index: NodeIndex(None), range: 268..277, items: [ DictItem { key: None, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 271..276, left: Name( ExprName { node_index: NodeIndex(None), range: 271..272, id: Name("x"), ctx: Load, }, ), ops: [ Lt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 275..276, id: Name("y"), ctx: Load, }, ), ], }, ), }, ], }, ), }, ), ], }, ) ``` ## Errors | 2 | # the ones which are higher than that. 3 | 4 | {**x := 1} | ^^ Syntax Error: Expected `,`, found `:=` 5 | {a: 1, **x if True else y} 6 | {**lambda x: x, b: 2} | | 2 | # the ones which are higher than that. 3 | 4 | {**x := 1} | ^ Syntax Error: Expected `:`, found `}` 5 | {a: 1, **x if True else y} 6 | {**lambda x: x, b: 2} | | 4 | {**x := 1} 5 | {a: 1, **x if True else y} | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 6 | {**lambda x: x, b: 2} 7 | {a: 1, **x or y} | | 4 | {**x := 1} 5 | {a: 1, **x if True else y} 6 | {**lambda x: x, b: 2} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 7 | {a: 1, **x or y} 8 | {**x and y, b: 2} | | 5 | {a: 1, **x if True else y} 6 | {**lambda x: x, b: 2} 7 | {a: 1, **x or y} | ^^^^^^ Syntax Error: Boolean expression cannot be used here 8 | {**x and y, b: 2} 9 | {a: 1, **not x, b: 2} | | 6 | {**lambda x: x, b: 2} 7 | {a: 1, **x or y} 8 | {**x and y, b: 2} | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 9 | {a: 1, **not x, b: 2} 10 | {**x in y} | | 7 | {a: 1, **x or y} 8 | {**x and y, b: 2} 9 | {a: 1, **not x, b: 2} | ^^^^^ Syntax Error: Boolean expression cannot be used here 10 | {**x in y} 11 | {**x not in y} | | 8 | {**x and y, b: 2} 9 | {a: 1, **not x, b: 2} 10 | {**x in y} | ^^^^^^ Syntax Error: Comparison expression cannot be used here 11 | {**x not in y} 12 | {**x < y} | | 9 | {a: 1, **not x, b: 2} 10 | {**x in y} 11 | {**x not in y} | ^^^^^^^^^^ Syntax Error: Comparison expression cannot be used here 12 | {**x < y} | | 10 | {**x in y} 11 | {**x not in y} 12 | {**x < y} | ^^^^^ Syntax Error: Comparison expression cannot be used here invalid_syntax@expressions__dict__double_star_comprehension.py.snap000064400000000000000000000100621046102023000374360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/double_star_comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..358, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 122..147, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 122..147, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 130..146, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 134..138, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 134..135, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 142..146, id: Name("data"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Errors | 2 | # it's actually a comprehension. 3 | 4 | {**x: y for x, y in data} | ^^^ Syntax Error: Starred expression cannot be used here 5 | 6 | # TODO(dhruvmanila): This test case fails because there's no way to represent `**y` | invalid_syntax@expressions__dict__missing_closing_brace_0.py.snap000064400000000000000000000100251046102023000367430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/missing_closing_brace_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..24, value: Dict( ExprDict { node_index: NodeIndex(None), range: 0..24, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 5..8, id: Name("def"), ctx: Load, }, ), }, DictItem { key: Some( Call( ExprCall { node_index: NodeIndex(None), range: 9..14, func: Name( ExprName { node_index: NodeIndex(None), range: 9..12, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 12..14, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 20..24, id: Name("pass"), ctx: Load, }, ), }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | {x: 2 | 3 | def foo(): | ^^^ Syntax Error: Expected an identifier, but found a keyword `def` that cannot be used here 4 | pass | | 1 | {x: 2 | 3 | def foo(): | ^^^ Syntax Error: Expected `,`, found name 4 | pass | | 3 | def foo(): 4 | pass | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here | 3 | def foo(): 4 | pass | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__dict__missing_closing_brace_1.py.snap000064400000000000000000000055601046102023000367540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/missing_closing_brace_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Dict( ExprDict { node_index: NodeIndex(None), range: 0..10, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 2, ), }, ), }, ), }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | {x: 2 | 3 | 1 + 2 | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__dict__missing_closing_brace_2.py.snap000064400000000000000000000060511046102023000367510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/missing_closing_brace_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..27, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..6, value: Dict( ExprDict { node_index: NodeIndex(None), range: 0..6, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), }, ], }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 8..27, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 12..15, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 15..17, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 23..27, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | {x: 1, | ^ Syntax Error: Expected `}`, found newline 2 | 3 | def foo(): 4 | pass | invalid_syntax@expressions__dict__named_expression_0.py.snap000064400000000000000000000144731046102023000357760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/named_expression_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..84, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 55..77, value: Dict( ExprDict { node_index: NodeIndex(None), range: 55..77, items: [ DictItem { key: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 56..62, target: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 1, ), }, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 64..65, id: Name("y"), ctx: Load, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("z"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 68..68, id: Name(""), ctx: Invalid, }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 72..73, value: Int( 2, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("a"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 79..84, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 79..84, left: Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Unparenthesized named expression not allowed in key 2 | 3 | {x := 1: y, z := 2: a} | ^^^^^^ Syntax Error: Unparenthesized named expression cannot be used here 4 | 5 | x + y | | 1 | # Unparenthesized named expression not allowed in key 2 | 3 | {x := 1: y, z := 2: a} | ^^ Syntax Error: Expected `:`, found `:=` 4 | 5 | x + y | invalid_syntax@expressions__dict__named_expression_1.py.snap000064400000000000000000000153611046102023000357740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/named_expression_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..86, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..79, value: Dict( ExprDict { node_index: NodeIndex(None), range: 57..79, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 61..62, id: Name("y"), ctx: Load, }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 66..67, value: Int( 1, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 67..67, id: Name(""), ctx: Invalid, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 69..70, id: Name("z"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("a"), ctx: Load, }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 77..78, value: Int( 2, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 78..78, id: Name(""), ctx: Invalid, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 81..86, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 81..86, left: Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 85..86, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Unparenthesized named expression not allowed in value 2 | 3 | {x: y := 1, z: a := 2} | ^^ Syntax Error: Expected `,`, found `:=` 4 | 5 | x + y | | 1 | # Unparenthesized named expression not allowed in value 2 | 3 | {x: y := 1, z: a := 2} | ^ Syntax Error: Expected `:`, found `,` 4 | 5 | x + y | | 1 | # Unparenthesized named expression not allowed in value 2 | 3 | {x: y := 1, z: a := 2} | ^^ Syntax Error: Expected `,`, found `:=` 4 | 5 | x + y | | 1 | # Unparenthesized named expression not allowed in value 2 | 3 | {x: y := 1, z: a := 2} | ^ Syntax Error: Expected `:`, found `}` 4 | 5 | x + y | invalid_syntax@expressions__dict__recover.py.snap000064400000000000000000000561151046102023000336600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/dict/recover.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..346, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 88..91, value: Set( ExprSet { node_index: NodeIndex(None), range: 88..91, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 89..89, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..105, value: Dict( ExprDict { node_index: NodeIndex(None), range: 93..105, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 94..95, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 97..98, value: Int( 2, ), }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..101, value: Int( 3, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 103..104, value: Int( 4, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 107..115, value: Dict( ExprDict { node_index: NodeIndex(None), range: 107..115, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 108..109, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 111..112, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..144, value: Dict( ExprDict { node_index: NodeIndex(None), range: 133..144, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 134..135, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 137..138, value: Int( 2, ), }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 139..140, value: Int( 3, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 142..143, value: Int( 4, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 157..162, value: Dict( ExprDict { node_index: NodeIndex(None), range: 157..162, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 1, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 160..160, id: Name(""), ctx: Invalid, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 201..205, value: Dict( ExprDict { node_index: NodeIndex(None), range: 201..205, items: [ DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 204..204, id: Name(""), ctx: Invalid, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 206..222, value: Dict( ExprDict { node_index: NodeIndex(None), range: 206..222, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 207..208, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 210..211, id: Name("y"), ctx: Load, }, ), }, DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 215..215, id: Name(""), ctx: Invalid, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 217..218, id: Name("a"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 220..221, id: Name("b"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 310..330, value: Dict( ExprDict { node_index: NodeIndex(None), range: 310..330, items: [ DictItem { key: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 311..313, value: Name( ExprName { node_index: NodeIndex(None), range: 312..313, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 315..316, id: Name("y"), ctx: Load, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 318..319, id: Name("z"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 321..322, id: Name("a"), ctx: Load, }, ), }, DictItem { key: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 324..326, value: Name( ExprName { node_index: NodeIndex(None), range: 325..326, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 328..329, id: Name("c"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 331..345, value: Dict( ExprDict { node_index: NodeIndex(None), range: 331..345, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 332..333, id: Name("x"), ctx: Load, }, ), ), value: Starred( ExprStarred { node_index: NodeIndex(None), range: 335..337, value: Name( ExprName { node_index: NodeIndex(None), range: 336..337, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 339..340, id: Name("z"), ctx: Load, }, ), ), value: Starred( ExprStarred { node_index: NodeIndex(None), range: 342..344, value: Name( ExprName { node_index: NodeIndex(None), range: 343..344, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # Test cases for dictionary expressions where the parser recovers from a syntax error. 2 | 3 | {,} | ^ Syntax Error: Expected an expression 4 | 5 | {1: 2,,3: 4} | | 3 | {,} 4 | 5 | {1: 2,,3: 4} | ^ Syntax Error: Expected an expression or a '}' 6 | 7 | {1: 2,,} | | 5 | {1: 2,,3: 4} 6 | 7 | {1: 2,,} | ^ Syntax Error: Expected an expression or a '}' 8 | 9 | # Missing comma | | 9 | # Missing comma 10 | {1: 2 3: 4} | ^ Syntax Error: Expected `,`, found int 11 | 12 | # No value | | 12 | # No value 13 | {1: } | ^ Syntax Error: Expected an expression 14 | 15 | # No value for double star unpacking | | 15 | # No value for double star unpacking 16 | {**} | ^ Syntax Error: Expected an expression 17 | {x: y, **, a: b} | | 15 | # No value for double star unpacking 16 | {**} 17 | {x: y, **, a: b} | ^ Syntax Error: Expected an expression 18 | 19 | # This is not a double star unpacking | | 22 | # Star expression not allowed here 23 | {*x: y, z: a, *b: c} | ^^ Syntax Error: Starred expression cannot be used here 24 | {x: *y, z: *a} | | 22 | # Star expression not allowed here 23 | {*x: y, z: a, *b: c} | ^^ Syntax Error: Starred expression cannot be used here 24 | {x: *y, z: *a} | | 22 | # Star expression not allowed here 23 | {*x: y, z: a, *b: c} 24 | {x: *y, z: *a} | ^^ Syntax Error: Starred expression cannot be used here | 22 | # Star expression not allowed here 23 | {*x: y, z: a, *b: c} 24 | {x: *y, z: *a} | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__emoji_identifiers.py.snap000064400000000000000000000067121046102023000345370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/emoji_identifiers.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..5, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 5..5, id: Name(""), ctx: Invalid, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 32..37, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("a"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 37..37, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 42..43, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 42..43, op: UAdd, operand: Name( ExprName { node_index: NodeIndex(None), range: 43..43, id: Name(""), ctx: Invalid, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | a = (🐶 | ^^ Syntax Error: Got unexpected token 🐶 2 | # comment 🐶 3 | ) | | 1 | a = (🐶 2 | # comment 🐶 3 | ) | ^ Syntax Error: Expected a statement 4 | 5 | a = (🐶 + | | 1 | a = (🐶 2 | # comment 🐶 3 | ) | ^ Syntax Error: Expected a statement 4 | 5 | a = (🐶 + 6 | # comment | | 3 | ) 4 | 5 | a = (🐶 + | ^^ Syntax Error: Got unexpected token 🐶 6 | # comment 7 | 🐶) | | 5 | a = (🐶 + 6 | # comment 7 | 🐶) | ^^ Syntax Error: Got unexpected token 🐶 | 5 | a = (🐶 + 6 | # comment 7 | 🐶) | ^ Syntax Error: Expected a statement | 5 | a = (🐶 + 6 | # comment 7 | 🐶) | ^ Syntax Error: Expected a statement invalid_syntax@expressions__emoji_statement.py.snap000064400000000000000000000005271046102023000342340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/emoji_statement.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..5, body: [], }, ) ``` ## Errors | 1 | 👍 | ^^ Syntax Error: Got unexpected token 👍 invalid_syntax@expressions__if__missing_orelse_expr_0.py.snap000064400000000000000000000060431046102023000361600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/if/missing_orelse_expr_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..88, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..67, value: If( ExprIf { node_index: NodeIndex(None), range: 53..67, test: Name( ExprName { node_index: NodeIndex(None), range: 58..62, id: Name("expr"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 67..67, id: Name(""), ctx: Invalid, }, ), }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 69..88, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 73..76, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 76..78, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 84..88, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # Missing orelse expression, followed by a statement 2 | x if expr else | ^ Syntax Error: Expected an expression 3 | 4 | def foo(): 5 | pass | invalid_syntax@expressions__if__missing_orelse_expr_1.py.snap000064400000000000000000000061531046102023000361630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/if/missing_orelse_expr_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..76, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 55..69, value: If( ExprIf { node_index: NodeIndex(None), range: 55..69, test: Name( ExprName { node_index: NodeIndex(None), range: 60..64, id: Name("expr"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 69..69, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 71..76, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 71..76, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Missing orelse expression, followed by an expression 2 | x if expr else | ^ Syntax Error: Expected an expression 3 | 4 | 1 + 1 | invalid_syntax@expressions__if__missing_test_expr_0.py.snap000064400000000000000000000060121046102023000356420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/if/missing_test_expr_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..76, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 51..55, value: If( ExprIf { node_index: NodeIndex(None), range: 51..55, test: Name( ExprName { node_index: NodeIndex(None), range: 55..55, id: Name(""), ctx: Invalid, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 55..55, id: Name(""), ctx: Invalid, }, ), }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 57..76, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 61..64, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 64..66, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 72..76, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # Missing test expression, followed by a statement 2 | x if | ^ Syntax Error: Expected an expression 3 | 4 | def foo(): 5 | pass | invalid_syntax@expressions__if__missing_test_expr_1.py.snap000064400000000000000000000061221046102023000356450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/if/missing_test_expr_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..57, value: If( ExprIf { node_index: NodeIndex(None), range: 53..57, test: Name( ExprName { node_index: NodeIndex(None), range: 57..57, id: Name(""), ctx: Invalid, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 57..57, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 59..64, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 59..64, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 59..60, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Missing test expression, followed by an expression 2 | x if | ^ Syntax Error: Expected an expression 3 | 4 | 1 + 1 | invalid_syntax@expressions__if__recover.py.snap000064400000000000000000000400251046102023000333240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/if/recover.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..215, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..43, value: If( ExprIf { node_index: NodeIndex(None), range: 26..43, test: Starred( ExprStarred { node_index: NodeIndex(None), range: 31..36, value: Name( ExprName { node_index: NodeIndex(None), range: 32..36, id: Name("expr"), ctx: Load, }, ), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 44..67, value: If( ExprIf { node_index: NodeIndex(None), range: 44..67, test: Lambda( ExprLambda { node_index: NodeIndex(None), range: 49..60, parameters: Some( Parameters { range: 56..57, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 56..57, node_index: NodeIndex(None), parameter: Parameter { range: 56..57, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 56..57, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("x"), ctx: Load, }, ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..87, value: If( ExprIf { node_index: NodeIndex(None), range: 68..87, test: Yield( ExprYield { node_index: NodeIndex(None), range: 73..80, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Load, }, ), ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 88..112, value: If( ExprIf { node_index: NodeIndex(None), range: 88..112, test: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 93..105, value: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("x"), ctx: Load, }, ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 142..164, value: If( ExprIf { node_index: NodeIndex(None), range: 142..164, test: Name( ExprName { node_index: NodeIndex(None), range: 147..151, id: Name("expr"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 142..143, id: Name("x"), ctx: Load, }, ), orelse: Starred( ExprStarred { node_index: NodeIndex(None), range: 157..164, value: Name( ExprName { node_index: NodeIndex(None), range: 158..164, id: Name("orelse"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 165..187, value: If( ExprIf { node_index: NodeIndex(None), range: 165..187, test: Name( ExprName { node_index: NodeIndex(None), range: 170..174, id: Name("expr"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("x"), ctx: Load, }, ), orelse: Yield( ExprYield { node_index: NodeIndex(None), range: 180..187, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 186..187, id: Name("y"), ctx: Load, }, ), ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 188..215, value: If( ExprIf { node_index: NodeIndex(None), range: 188..215, test: Name( ExprName { node_index: NodeIndex(None), range: 193..197, id: Name("expr"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 188..189, id: Name("x"), ctx: Load, }, ), orelse: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 203..215, value: Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Invalid test expression 2 | x if *expr else y | ^^^^^ Syntax Error: Starred expression cannot be used here 3 | x if lambda x: x else y 4 | x if yield x else y | | 1 | # Invalid test expression 2 | x if *expr else y 3 | x if lambda x: x else y | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 4 | x if yield x else y 5 | x if yield from x else y | | 2 | x if *expr else y 3 | x if lambda x: x else y 4 | x if yield x else y | ^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | x if yield from x else y | | 3 | x if lambda x: x else y 4 | x if yield x else y 5 | x if yield from x else y | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 6 | 7 | # Invalid orelse expression | | 7 | # Invalid orelse expression 8 | x if expr else *orelse | ^^^^^^^ Syntax Error: Starred expression cannot be used here 9 | x if expr else yield y 10 | x if expr else yield from y | | 7 | # Invalid orelse expression 8 | x if expr else *orelse 9 | x if expr else yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here 10 | x if expr else yield from y | | 8 | x if expr else *orelse 9 | x if expr else yield y 10 | x if expr else yield from y | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@expressions__lambda_default_parameters.py.snap000064400000000000000000000122271046102023000362140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/lambda_default_parameters.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..20, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..20, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..20, parameters: Some( Parameters { range: 7..17, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 7..8, node_index: NodeIndex(None), parameter: Parameter { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 7..8, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 10..14, node_index: NodeIndex(None), parameter: Parameter { range: 10..11, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 10..11, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 12..14, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 16..17, node_index: NodeIndex(None), parameter: Parameter { range: 16..17, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 16..17, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | lambda a, b=20, c: 1 | ^ Syntax Error: Parameter without a default cannot follow a parameter with a default invalid_syntax@expressions__lambda_duplicate_parameters.py.snap000064400000000000000000000420501046102023000365370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/lambda_duplicate_parameters.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..91, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..14, parameters: Some( Parameters { range: 7..11, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 7..8, node_index: NodeIndex(None), parameter: Parameter { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 7..8, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 10..11, node_index: NodeIndex(None), parameter: Parameter { range: 10..11, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 10..11, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..33, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 16..33, parameters: Some( Parameters { range: 23..30, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 23..24, node_index: NodeIndex(None), parameter: Parameter { range: 23..24, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 23..24, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 29..30, node_index: NodeIndex(None), parameter: Parameter { range: 29..30, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 29..30, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 35..52, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 35..52, parameters: Some( Parameters { range: 42..49, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 42..43, node_index: NodeIndex(None), parameter: Parameter { range: 42..43, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 42..43, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 45..49, node_index: NodeIndex(None), parameter: Parameter { range: 45..46, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 45..46, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..49, value: Int( 20, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 54..69, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 54..69, parameters: Some( Parameters { range: 61..66, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 61..62, node_index: NodeIndex(None), parameter: Parameter { range: 61..62, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 61..62, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 64..66, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 65..66, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 68..69, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 71..90, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 71..90, parameters: Some( Parameters { range: 78..87, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 78..79, node_index: NodeIndex(None), parameter: Parameter { range: 78..79, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 78..79, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 84..87, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 86..87, node_index: NodeIndex(None), }, annotation: None, }, ), }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 7 | lambda a, *a: 1 8 | 9 | lambda a, *, **a: 1 | ^^^ Syntax Error: Expected one or more keyword parameter after `*` separator ## Semantic Syntax Errors | 1 | lambda a, a: 1 | ^ Syntax Error: Duplicate parameter "a" 2 | 3 | lambda a, *, a: 1 | | 1 | lambda a, a: 1 2 | 3 | lambda a, *, a: 1 | ^ Syntax Error: Duplicate parameter "a" 4 | 5 | lambda a, a=20: 1 | | 3 | lambda a, *, a: 1 4 | 5 | lambda a, a=20: 1 | ^ Syntax Error: Duplicate parameter "a" 6 | 7 | lambda a, *a: 1 | | 5 | lambda a, a=20: 1 6 | 7 | lambda a, *a: 1 | ^ Syntax Error: Duplicate parameter "a" 8 | 9 | lambda a, *, **a: 1 | | 7 | lambda a, *a: 1 8 | 9 | lambda a, *, **a: 1 | ^ Syntax Error: Duplicate parameter "a" invalid_syntax@expressions__list__comprehension.py.snap000064400000000000000000001623471046102023000351210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..444, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..31, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 17..31, elt: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 20..30, node_index: NodeIndex(None), target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..48, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 32..48, elt: Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 35..47, node_index: NodeIndex(None), target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 39..42, value: StringLiteralValue { inner: Single( StringLiteral { range: 39..42, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..68, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 49..68, elt: Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 52..67, node_index: NodeIndex(None), target: Call( ExprCall { node_index: NodeIndex(None), range: 56..62, func: Name( ExprName { node_index: NodeIndex(None), range: 56..60, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 60..62, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 69..88, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 69..88, elt: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 72..87, node_index: NodeIndex(None), target: Set( ExprSet { node_index: NodeIndex(None), range: 76..82, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("b"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 105..120, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 105..120, elt: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 108..119, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Store, }, ), iter: Starred( ExprStarred { node_index: NodeIndex(None), range: 117..119, value: Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..141, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 121..141, elt: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 124..140, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 133..140, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 142..167, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 142..167, elt: Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 145..166, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 149..150, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 154..166, value: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 168..192, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 168..192, elt: Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 171..191, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 175..176, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 180..191, parameters: Some( Parameters { range: 187..188, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 187..188, node_index: NodeIndex(None), parameter: Parameter { range: 187..188, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 187..188, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..216, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 193..216, elt: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 194..197, left: Name( ExprName { node_index: NodeIndex(None), range: 194..194, id: Name(""), ctx: Invalid, }, ), op: Pow, right: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("x"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 198..215, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("x"), ctx: Store, }, ), iter: List( ExprList { node_index: NodeIndex(None), range: 207..215, elts: [ Dict( ExprDict { node_index: NodeIndex(None), range: 208..214, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 209..210, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 212..213, value: Int( 2, ), }, ), }, ], }, ), ], ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 217..221, value: List( ExprList { node_index: NodeIndex(None), range: 217..221, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 218..220, value: Name( ExprName { node_index: NodeIndex(None), range: 219..220, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, }, ), }, ), For( StmtFor { node_index: NodeIndex(None), range: 222..232, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 226..227, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 231..232, id: Name("y"), ctx: Load, }, ), body: [], orelse: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 234..241, value: List( ExprList { node_index: NodeIndex(None), range: 234..241, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 235..237, value: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 239..241, value: Name( ExprName { node_index: NodeIndex(None), range: 240..241, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, }, ), }, ), For( StmtFor { node_index: NodeIndex(None), range: 242..252, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 246..247, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 251..252, id: Name("y"), ctx: Load, }, ), body: [], orelse: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 268..291, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 268..291, elt: Name( ExprName { node_index: NodeIndex(None), range: 269..270, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 271..290, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 275..276, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 280..284, id: Name("data"), ctx: Load, }, ), ifs: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 288..290, value: Name( ExprName { node_index: NodeIndex(None), range: 289..290, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 292..320, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 292..320, elt: Name( ExprName { node_index: NodeIndex(None), range: 293..294, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 295..319, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 299..300, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 304..308, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 312..319, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 318..319, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 321..354, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 321..354, elt: Name( ExprName { node_index: NodeIndex(None), range: 322..323, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 324..353, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 328..329, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 333..337, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 341..353, value: Name( ExprName { node_index: NodeIndex(None), range: 352..353, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 355..387, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 355..387, elt: Name( ExprName { node_index: NodeIndex(None), range: 356..357, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 358..386, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 362..363, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 367..371, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 375..386, parameters: Some( Parameters { range: 382..383, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 382..383, node_index: NodeIndex(None), parameter: Parameter { range: 382..383, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 382..383, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 385..386, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 388..415, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 388..415, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 389..403, value: If( ExprIf { node_index: NodeIndex(None), range: 390..403, test: Name( ExprName { node_index: NodeIndex(None), range: 395..396, id: Name("x"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 390..391, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 402..403, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), generators: [ Comprehension { range: 404..414, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 408..409, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 413..414, id: Name("z"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 416..443, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 416..443, elt: If( ExprIf { node_index: NodeIndex(None), range: 417..431, test: Name( ExprName { node_index: NodeIndex(None), range: 422..423, id: Name("x"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 417..418, id: Name("x"), ctx: Load, }, ), orelse: Starred( ExprStarred { node_index: NodeIndex(None), range: 429..431, value: Name( ExprName { node_index: NodeIndex(None), range: 430..431, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 432..442, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 436..437, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 441..442, id: Name("z"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # Invalid target 2 | [x for 1 in y] | ^ Syntax Error: Invalid assignment target 3 | [x for 'a' in y] 4 | [x for call() in y] | | 1 | # Invalid target 2 | [x for 1 in y] 3 | [x for 'a' in y] | ^^^ Syntax Error: Invalid assignment target 4 | [x for call() in y] 5 | [x for {a, b} in y] | | 2 | [x for 1 in y] 3 | [x for 'a' in y] 4 | [x for call() in y] | ^^^^^^ Syntax Error: Invalid assignment target 5 | [x for {a, b} in y] | | 3 | [x for 'a' in y] 4 | [x for call() in y] 5 | [x for {a, b} in y] | ^^^^^^ Syntax Error: Invalid assignment target 6 | 7 | # Invalid iter | | 7 | # Invalid iter 8 | [x for x in *y] | ^^ Syntax Error: Starred expression cannot be used here 9 | [x for x in yield y] 10 | [x for x in yield from y] | | 7 | # Invalid iter 8 | [x for x in *y] 9 | [x for x in yield y] | ^^^^^^^ Syntax Error: Yield expression cannot be used here 10 | [x for x in yield from y] 11 | [x for x in lambda y: y] | | 8 | [x for x in *y] 9 | [x for x in yield y] 10 | [x for x in yield from y] | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 11 | [x for x in lambda y: y] 12 | [**x for x in [{1: 2}]] | | 9 | [x for x in yield y] 10 | [x for x in yield from y] 11 | [x for x in lambda y: y] | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] | | 10 | [x for x in yield from y] 11 | [x for x in lambda y: y] 12 | [**x for x in [{1: 2}]] | ^^ Syntax Error: Expected an expression 13 | [*x, for x in y] 14 | [*x, *y for x in y] | | 11 | [x for x in lambda y: y] 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] | ^^^ Syntax Error: Expected `]`, found `for` 14 | [*x, *y for x in y] | | 11 | [x for x in lambda y: y] 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] | ^ Syntax Error: Expected `:`, found `]` 14 | [*x, *y for x in y] | | 11 | [x for x in lambda y: y] 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] | ^ Syntax Error: Expected a statement 14 | [*x, *y for x in y] 15 | 16 | # Invalid if | | 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] 14 | [*x, *y for x in y] | ^^^ Syntax Error: Expected `]`, found `for` 15 | 16 | # Invalid if | | 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] 14 | [*x, *y for x in y] | ^ Syntax Error: Expected `:`, found `]` 15 | 16 | # Invalid if | | 12 | [**x for x in [{1: 2}]] 13 | [*x, for x in y] 14 | [*x, *y for x in y] | ^ Syntax Error: Expected a statement 15 | 16 | # Invalid if 17 | [x for x in data if *y] | | 16 | # Invalid if 17 | [x for x in data if *y] | ^^ Syntax Error: Starred expression cannot be used here 18 | [x for x in data if yield y] 19 | [x for x in data if yield from y] | | 16 | # Invalid if 17 | [x for x in data if *y] 18 | [x for x in data if yield y] | ^^^^^^^ Syntax Error: Yield expression cannot be used here 19 | [x for x in data if yield from y] 20 | [x for x in data if lambda y: y] | | 17 | [x for x in data if *y] 18 | [x for x in data if yield y] 19 | [x for x in data if yield from y] | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 20 | [x for x in data if lambda y: y] 21 | [*x if x else y for x in z] | | 18 | [x for x in data if yield y] 19 | [x for x in data if yield from y] 20 | [x for x in data if lambda y: y] | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 21 | [*x if x else y for x in z] 22 | [x if x else *y for x in z] | | 19 | [x for x in data if yield from y] 20 | [x for x in data if lambda y: y] 21 | [*x if x else y for x in z] | ^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 22 | [x if x else *y for x in z] | | 20 | [x for x in data if lambda y: y] 21 | [*x if x else y for x in z] 22 | [x if x else *y for x in z] | ^^ Syntax Error: Starred expression cannot be used here ## Unsupported Syntax Errors | 19 | [x for x in data if yield from y] 20 | [x for x in data if lambda y: y] 21 | [*x if x else y for x in z] | ^^^^^^^^^^^^^^ Syntax Error: Cannot use iterable unpacking in a list comprehension on Python 3.14 (syntax was added in Python 3.15) 22 | [x if x else *y for x in z] | invalid_syntax@expressions__list__missing_closing_bracket_0.py.snap000064400000000000000000000024171046102023000373400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/missing_closing_bracket_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..43, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 42..43, value: List( ExprList { node_index: NodeIndex(None), range: 42..43, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 43..43, id: Name(""), ctx: Invalid, }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # Missing closing bracket 0: No elements 2 | 3 | [ | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__list__missing_closing_bracket_1.py.snap000064400000000000000000000041311046102023000373340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/missing_closing_bracket_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..133, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 125..133, value: List( ExprList { node_index: NodeIndex(None), range: 125..133, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 128..133, left: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("y"), ctx: Load, }, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 4 | [ 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__list__missing_closing_bracket_2.py.snap000064400000000000000000000050301046102023000373340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/missing_closing_bracket_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..141, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 131..141, value: List( ExprList { node_index: NodeIndex(None), range: 131..141, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 132..133, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 136..141, left: Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("y"), ctx: Load, }, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 4 | [1, 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__list__missing_closing_bracket_3.py.snap000064400000000000000000000056641046102023000373520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/missing_closing_bracket_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..140, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 114..119, value: List( ExprList { node_index: NodeIndex(None), range: 114..119, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 121..140, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 125..128, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 128..130, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 136..140, }, ), ], }, ), ], }, ) ``` ## Errors | 2 | # token starts a statement. 3 | 4 | [1, 2 | ^ Syntax Error: Expected `]`, found newline 5 | 6 | def foo(): 7 | pass | invalid_syntax@expressions__list__recover.py.snap000064400000000000000000000274641046102023000337150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/recover.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..208, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 82..85, value: List( ExprList { node_index: NodeIndex(None), range: 82..85, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 83..83, id: Name(""), ctx: Invalid, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 87..93, value: List( ExprList { node_index: NodeIndex(None), range: 87..93, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 91..92, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..100, value: List( ExprList { node_index: NodeIndex(None), range: 95..100, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 96..97, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 118..123, value: List( ExprList { node_index: NodeIndex(None), range: 118..123, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 121..122, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 156..162, value: List( ExprList { node_index: NodeIndex(None), range: 156..162, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 157..158, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..161, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 185..194, value: List( ExprList { node_index: NodeIndex(None), range: 185..194, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 186..187, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 189..192, left: Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 192..192, id: Name(""), ctx: Invalid, }, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 196..202, value: List( ExprList { node_index: NodeIndex(None), range: 196..202, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..198, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 200..201, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 204..207, value: List( ExprList { node_index: NodeIndex(None), range: 204..207, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 205..206, value: Name( ExprName { node_index: NodeIndex(None), range: 206..206, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # Test cases for list expressions where the parser recovers from a syntax error. 2 | 3 | [,] | ^ Syntax Error: Expected an expression 4 | 5 | [1,,2] | | 3 | [,] 4 | 5 | [1,,2] | ^ Syntax Error: Expected an expression or a ']' 6 | 7 | [1,,] | | 5 | [1,,2] 6 | 7 | [1,,] | ^ Syntax Error: Expected an expression or a ']' 8 | 9 | # Missing comma | | 9 | # Missing comma 10 | [1 2] | ^ Syntax Error: Expected `,`, found int 11 | 12 | # Dictionary element in a list | | 12 | # Dictionary element in a list 13 | [1: 2] | ^ Syntax Error: Expected an expression or a ']' 14 | 15 | # Missing expression | | 15 | # Missing expression 16 | [1, x + ] | ^ Syntax Error: Expected an expression 17 | 18 | [1; 2] | | 16 | [1, x + ] 17 | 18 | [1; 2] | ^ Syntax Error: Expected an expression or a ']' 19 | 20 | [*] | | 18 | [1; 2] 19 | 20 | [*] | ^ Syntax Error: Expected an expression invalid_syntax@expressions__list__star_expression_precedence.py.snap000064400000000000000000000566421046102023000376550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/list/star_expression_precedence.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..200, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 84..93, value: List( ExprList { node_index: NodeIndex(None), range: 84..93, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 86..88, value: Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("y"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 94..106, value: List( ExprList { node_index: NodeIndex(None), range: 94..106, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 95..102, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 96..102, left: Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 107..118, value: List( ExprList { node_index: NodeIndex(None), range: 107..118, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 108..114, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 109..114, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 116..117, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 119..132, value: List( ExprList { node_index: NodeIndex(None), range: 119..132, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 120..128, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 121..128, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 121..122, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 130..131, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..145, value: List( ExprList { node_index: NodeIndex(None), range: 133..145, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 134..141, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 135..141, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 146..168, value: List( ExprList { node_index: NodeIndex(None), range: 146..168, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 147..164, value: If( ExprIf { node_index: NodeIndex(None), range: 148..164, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 153..157, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 148..149, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 169..186, value: List( ExprList { node_index: NodeIndex(None), range: 169..186, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 170..182, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 171..182, parameters: Some( Parameters { range: 178..179, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 178..179, node_index: NodeIndex(None), parameter: Parameter { range: 178..179, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 178..179, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 181..182, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 184..185, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 187..199, value: List( ExprList { node_index: NodeIndex(None), range: 187..199, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 188..195, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 188..190, value: Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 194..195, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("z"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # For list expression, the minimum binding power of star expression is bitwise or. 2 | 3 | [(*x), y] | ^^ Syntax Error: Starred expression cannot be used here 4 | [*x in y, z] 5 | [*not x, z] | | 3 | [(*x), y] 4 | [*x in y, z] | ^^^^^^ Syntax Error: Comparison expression cannot be used here 5 | [*not x, z] 6 | [*x and y, z] | | 3 | [(*x), y] 4 | [*x in y, z] 5 | [*not x, z] | ^^^^^ Syntax Error: Boolean expression cannot be used here 6 | [*x and y, z] 7 | [*x or y, z] | | 4 | [*x in y, z] 5 | [*not x, z] 6 | [*x and y, z] | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 7 | [*x or y, z] 8 | [*x if True else y, z] | | 5 | [*not x, z] 6 | [*x and y, z] 7 | [*x or y, z] | ^^^^^^ Syntax Error: Boolean expression cannot be used here 8 | [*x if True else y, z] 9 | [*lambda x: x, z] | | 6 | [*x and y, z] 7 | [*x or y, z] 8 | [*x if True else y, z] | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 9 | [*lambda x: x, z] 10 | [*x := 2, z] | | 7 | [*x or y, z] 8 | [*x if True else y, z] 9 | [*lambda x: x, z] | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 10 | [*x := 2, z] | | 8 | [*x if True else y, z] 9 | [*lambda x: x, z] 10 | [*x := 2, z] | ^^ Syntax Error: Assignment expression target must be an identifier invalid_syntax@expressions__named__invalid_target.py.snap000064400000000000000000000222721046102023000353450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/invalid_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..109, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..68, value: Named( ExprNamed { node_index: NodeIndex(None), range: 59..67, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 59..62, value: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("y"), range: 61..62, node_index: NodeIndex(None), }, ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 66..67, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 69..80, value: Named( ExprNamed { node_index: NodeIndex(None), range: 70..79, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 70..74, value: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("y"), ctx: Load, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 81..90, value: Named( ExprNamed { node_index: NodeIndex(None), range: 82..89, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 82..84, value: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 91..109, value: Named( ExprNamed { node_index: NodeIndex(None), range: 92..108, target: List( ExprList { node_index: NodeIndex(None), range: 92..98, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("y"), ctx: Store, }, ), ], ctx: Store, }, ), value: List( ExprList { node_index: NodeIndex(None), range: 102..108, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 103..104, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 106..107, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Assignment expression target can only be an identifier 2 | 3 | (x.y := 1) | ^^^ Syntax Error: Assignment expression target must be an identifier 4 | (x[y] := 1) 5 | (*x := 1) | | 3 | (x.y := 1) 4 | (x[y] := 1) | ^^^^ Syntax Error: Assignment expression target must be an identifier 5 | (*x := 1) 6 | ([x, y] := [1, 2]) | | 3 | (x.y := 1) 4 | (x[y] := 1) 5 | (*x := 1) | ^^ Syntax Error: Assignment expression target must be an identifier 6 | ([x, y] := [1, 2]) | | 4 | (x[y] := 1) 5 | (*x := 1) 6 | ([x, y] := [1, 2]) | ^^^^^^ Syntax Error: Assignment expression target must be an identifier invalid_syntax@expressions__named__missing_expression_0.py.snap000064400000000000000000000020201046102023000365050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/missing_expression_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..75, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 71..72, value: Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("x"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # There are no parentheses, so this isn't parsed as named expression. 2 | 3 | x := | ^^ Syntax Error: Expected a statement | 1 | # There are no parentheses, so this isn't parsed as named expression. 2 | 3 | x := | ^ Syntax Error: Expected a statement invalid_syntax@expressions__named__missing_expression_1.py.snap000064400000000000000000000027621046102023000365230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/missing_expression_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..33, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 28..33, value: Named( ExprNamed { node_index: NodeIndex(None), range: 29..33, target: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 33..33, id: Name(""), ctx: Invalid, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # EOF after the `:=` token 2 | 3 | (x := | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__named__missing_expression_2.py.snap000064400000000000000000000063541046102023000365250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/missing_expression_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..87, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 61..71, value: Named( ExprNamed { node_index: NodeIndex(None), range: 62..71, target: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 68..71, id: Name("def"), ctx: Load, }, ), }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 72..87, target: Call( ExprCall { node_index: NodeIndex(None), range: 72..77, func: Name( ExprName { node_index: NodeIndex(None), range: 72..75, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 75..77, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 83..87, id: Name("pass"), ctx: Load, }, ), value: None, simple: false, }, ), ], }, ) ``` ## Errors | 3 | (x := 4 | 5 | def foo(): | ^^^ Syntax Error: Expected an identifier, but found a keyword `def` that cannot be used here 6 | pass | | 3 | (x := 4 | 5 | def foo(): | ^^^ Syntax Error: Expected `)`, found name 6 | pass | | 5 | def foo(): 6 | pass | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here | 5 | def foo(): 6 | pass | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__named__missing_expression_3.py.snap000064400000000000000000000044141046102023000365210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/missing_expression_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 100..112, value: Named( ExprNamed { node_index: NodeIndex(None), range: 101..112, target: Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("x"), ctx: Store, }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 107..112, left: Name( ExprName { node_index: NodeIndex(None), range: 107..108, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 4 | (x := 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__named__missing_expression_4.py.snap000064400000000000000000000052401046102023000365200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/named/missing_expression_4.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..78, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 64..71, value: Named( ExprNamed { node_index: NodeIndex(None), range: 65..69, target: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 69..69, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 73..78, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 73..78, left: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # No expression on the right side of the assignment expression 2 | 3 | (x := ) | ^ Syntax Error: Expected an expression 4 | 5 | x + y | invalid_syntax@expressions__parenthesized__generator.py.snap000064400000000000000000000062361046102023000361220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/generator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..21, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 0..8, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 1..7, target: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 1, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), For( StmtFor { node_index: NodeIndex(None), range: 9..19, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("y"), ctx: Load, }, ), body: [], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | (x := 1, for x in y) | ^^^ Syntax Error: Expected `)`, found `for` | 1 | (x := 1, for x in y) | ^ Syntax Error: Expected `:`, found `)` | 1 | (x := 1, for x in y) | ^ Syntax Error: Expected a statement invalid_syntax@expressions__parenthesized__missing_closing_paren_0.py.snap000064400000000000000000000015751046102023000407300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/missing_closing_paren_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 46..47, value: Name( ExprName { node_index: NodeIndex(None), range: 47..47, id: Name(""), ctx: Invalid, }, ), }, ), ], }, ) ``` ## Errors | 1 | # Missing closing parentheses 0: No elements 2 | 3 | ( | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__parenthesized__missing_closing_paren_1.py.snap000064400000000000000000000030151046102023000407200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/missing_closing_paren_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..137, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 129..137, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 132..137, left: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 4 | ( 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__parenthesized__missing_closing_paren_2.py.snap000064400000000000000000000051221046102023000407220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/missing_closing_paren_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..146, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 136..146, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 136..146, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 137..138, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 141..146, left: Name( ExprName { node_index: NodeIndex(None), range: 141..142, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 145..146, id: Name("y"), ctx: Load, }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Errors | 4 | (1, 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__parenthesized__missing_closing_paren_3.py.snap000064400000000000000000000057561046102023000407400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/missing_closing_paren_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 118..123, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 118..123, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 125..144, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 129..132, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 132..134, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 140..144, }, ), ], }, ), ], }, ) ``` ## Errors | 2 | # token starts a statement. 3 | 4 | (1, 2 | ^ Syntax Error: Expected `)`, found newline 5 | 6 | def foo(): 7 | pass | invalid_syntax@expressions__parenthesized__parenthesized.py.snap000064400000000000000000000045231046102023000367760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/parenthesized.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..125, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 66..70, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 67..69, value: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 119..120, value: Name( ExprName { node_index: NodeIndex(None), range: 119..120, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 124..125, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 124..125, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Starred expression isn't allowed in a parenthesized expression. 2 | (*x) | ^^ Syntax Error: Starred expression cannot be used here 3 | 4 | # Unparenthesized named expression is allowed. | | 4 | # Unparenthesized named expression is allowed. 5 | x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__parenthesized__tuple.py.snap000064400000000000000000000314661046102023000352700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/tuple.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..267, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..86, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 83..86, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 84..84, id: Name(""), ctx: Invalid, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 88..94, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 88..94, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 92..93, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 96..101, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 96..101, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 97..98, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 119..121, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 120..121, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 122..123, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 2, ), }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 157..162, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 1, ), }, ), annotation: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 161..162, value: Int( 2, ), }, ), value: None, simple: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 186..195, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 186..195, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 187..188, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 190..193, left: Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 193..193, id: Name(""), ctx: Invalid, }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 197..199, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 198..199, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 201..202, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 2, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 255..267, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 255..267, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 255..256, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 258..259, id: Name("y"), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 263..264, value: Int( 2, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 266..267, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` ## Errors | 1 | # Test cases for tuple expressions where the parser recovers from a syntax error. 2 | 3 | (,) | ^ Syntax Error: Expected an expression 4 | 5 | (1,,2) | | 3 | (,) 4 | 5 | (1,,2) | ^ Syntax Error: Expected an expression or a ')' 6 | 7 | (1,,) | | 5 | (1,,2) 6 | 7 | (1,,) | ^ Syntax Error: Expected an expression or a ')' 8 | 9 | # Missing comma | | 9 | # Missing comma 10 | (1 2) | ^ Syntax Error: Expected `)`, found int 11 | 12 | # Dictionary element in a list | | 9 | # Missing comma 10 | (1 2) | ^ Syntax Error: Expected a statement 11 | 12 | # Dictionary element in a list | | 9 | # Missing comma 10 | (1 2) | ^ Syntax Error: Expected a statement 11 | 12 | # Dictionary element in a list 13 | (1: 2) | | 12 | # Dictionary element in a list 13 | (1: 2) | ^ Syntax Error: Expected `)`, found `:` 14 | 15 | # Missing expression | | 12 | # Dictionary element in a list 13 | (1: 2) | ^ Syntax Error: Invalid annotated assignment target 14 | 15 | # Missing expression | | 12 | # Dictionary element in a list 13 | (1: 2) | ^ Syntax Error: Expected a statement 14 | 15 | # Missing expression | | 12 | # Dictionary element in a list 13 | (1: 2) | ^ Syntax Error: Expected a statement 14 | 15 | # Missing expression 16 | (1, x + ) | | 15 | # Missing expression 16 | (1, x + ) | ^ Syntax Error: Expected an expression 17 | 18 | (1; 2) | | 16 | (1, x + ) 17 | 18 | (1; 2) | ^ Syntax Error: Expected `)`, found `;` 19 | 20 | # Unparenthesized named expression is not allowed | | 16 | (1, x + ) 17 | 18 | (1; 2) | ^ Syntax Error: Expected a statement 19 | 20 | # Unparenthesized named expression is not allowed | | 16 | (1, x + ) 17 | 18 | (1; 2) | ^ Syntax Error: Expected a statement 19 | 20 | # Unparenthesized named expression is not allowed 21 | x, y := 2, z | | 20 | # Unparenthesized named expression is not allowed 21 | x, y := 2, z | ^^ Syntax Error: Expected `,`, found `:=` invalid_syntax@expressions__parenthesized__tuple_starred_expr.py.snap000064400000000000000000002251121046102023000400430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/parenthesized/tuple_starred_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..532, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 157..178, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 157..178, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 158..165, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 159..165, left: Name( ExprName { node_index: NodeIndex(None), range: 159..160, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 164..165, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 167..168, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 170..177, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 171..177, left: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 176..177, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 179..198, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 179..198, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 180..186, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 181..186, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 185..186, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 188..189, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 191..197, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 192..197, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 199..222, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 199..222, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 200..208, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 201..208, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 201..202, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 207..208, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 210..211, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 213..221, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 214..221, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 220..221, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 223..244, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 223..244, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 224..231, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 225..231, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 225..226, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 230..231, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 233..234, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 236..243, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 237..243, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 237..238, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 242..243, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 245..286, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 245..286, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 246..263, value: If( ExprIf { node_index: NodeIndex(None), range: 247..263, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 252..256, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 247..248, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 262..263, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 268..285, value: If( ExprIf { node_index: NodeIndex(None), range: 269..285, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 274..278, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 269..270, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 284..285, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 287..318, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 287..318, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 288..300, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 289..300, parameters: Some( Parameters { range: 296..297, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 296..297, node_index: NodeIndex(None), parameter: Parameter { range: 296..297, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 296..297, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 299..300, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 302..303, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 305..317, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 306..317, parameters: Some( Parameters { range: 313..314, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 313..314, node_index: NodeIndex(None), parameter: Parameter { range: 313..314, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 313..314, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 316..317, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 319..340, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 319..340, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 320..327, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 320..322, value: Name( ExprName { node_index: NodeIndex(None), range: 321..322, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 326..327, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 329..330, id: Name("z"), ctx: Load, }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 332..339, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 332..334, value: Name( ExprName { node_index: NodeIndex(None), range: 333..334, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 338..339, value: Int( 2, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 363..382, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 363..382, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 363..370, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 364..370, left: Name( ExprName { node_index: NodeIndex(None), range: 364..365, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 369..370, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 372..373, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 375..382, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 376..382, left: Name( ExprName { node_index: NodeIndex(None), range: 376..377, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 381..382, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 383..400, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 383..400, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 383..389, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 384..389, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 388..389, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 391..392, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 394..400, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 395..400, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 399..400, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 401..422, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 401..422, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 401..409, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 402..409, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 402..403, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 408..409, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 411..412, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 414..422, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 415..422, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 415..416, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 421..422, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 423..442, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 423..442, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 423..430, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 424..430, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 424..425, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 429..430, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 432..433, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 435..442, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 436..442, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 436..437, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 441..442, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 443..482, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 443..482, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 443..460, value: If( ExprIf { node_index: NodeIndex(None), range: 444..460, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 449..453, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 444..445, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 459..460, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 462..463, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 465..482, value: If( ExprIf { node_index: NodeIndex(None), range: 466..482, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 471..475, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 466..467, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 481..482, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 483..512, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 483..512, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 483..495, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 484..495, parameters: Some( Parameters { range: 491..492, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 491..492, node_index: NodeIndex(None), parameter: Parameter { range: 491..492, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 491..492, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 494..495, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 497..498, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 500..512, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 501..512, parameters: Some( Parameters { range: 508..509, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 508..509, node_index: NodeIndex(None), parameter: Parameter { range: 508..509, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 508..509, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 511..512, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 513..515, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 513..515, value: Name( ExprName { node_index: NodeIndex(None), range: 514..515, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 519..532, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 519..532, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 519..520, value: Int( 2, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 522..523, id: Name("z"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 525..527, value: Name( ExprName { node_index: NodeIndex(None), range: 526..527, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 531..532, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` ## Errors | 2 | # Test the first and any other element as there are two separate calls. 3 | 4 | (*x in y, z, *x in y) | ^^^^^^ Syntax Error: Comparison expression cannot be used here 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) | | 2 | # Test the first and any other element as there are two separate calls. 3 | 4 | (*x in y, z, *x in y) | ^^^^^^ Syntax Error: Comparison expression cannot be used here 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) | | 4 | (*x in y, z, *x in y) 5 | (*not x, z, *not x) | ^^^^^ Syntax Error: Boolean expression cannot be used here 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) | | 4 | (*x in y, z, *x in y) 5 | (*not x, z, *not x) | ^^^^^ Syntax Error: Boolean expression cannot be used here 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) | | 4 | (*x in y, z, *x in y) 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) | | 4 | (*x in y, z, *x in y) 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) | | 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) | ^^^^^^ Syntax Error: Boolean expression cannot be used here 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) | | 5 | (*not x, z, *not x) 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) | ^^^^^^ Syntax Error: Boolean expression cannot be used here 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) | | 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 9 | (*lambda x: x, z, *lambda x: x) 10 | (*x := 2, z, *x := 2) | | 6 | (*x and y, z, *x and y) 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 9 | (*lambda x: x, z, *lambda x: x) 10 | (*x := 2, z, *x := 2) | | 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 10 | (*x := 2, z, *x := 2) | | 7 | (*x or y, z, *x or y) 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 10 | (*x := 2, z, *x := 2) | | 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) 10 | (*x := 2, z, *x := 2) | ^^ Syntax Error: Assignment expression target must be an identifier | 8 | (*x if True else y, z, *x if True else y) 9 | (*lambda x: x, z, *lambda x: x) 10 | (*x := 2, z, *x := 2) | ^^ Syntax Error: Assignment expression target must be an identifier | 13 | # Non-parenthesized 14 | *x in y, z, *x in y | ^^^^^^ Syntax Error: Comparison expression cannot be used here 15 | *not x, z, *not x 16 | *x and y, z, *x and y | | 13 | # Non-parenthesized 14 | *x in y, z, *x in y | ^^^^^^ Syntax Error: Comparison expression cannot be used here 15 | *not x, z, *not x 16 | *x and y, z, *x and y | | 13 | # Non-parenthesized 14 | *x in y, z, *x in y 15 | *not x, z, *not x | ^^^^^ Syntax Error: Boolean expression cannot be used here 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y | | 13 | # Non-parenthesized 14 | *x in y, z, *x in y 15 | *not x, z, *not x | ^^^^^ Syntax Error: Boolean expression cannot be used here 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y | | 14 | *x in y, z, *x in y 15 | *not x, z, *not x 16 | *x and y, z, *x and y | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y | | 14 | *x in y, z, *x in y 15 | *not x, z, *not x 16 | *x and y, z, *x and y | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y | | 15 | *not x, z, *not x 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y | ^^^^^^ Syntax Error: Boolean expression cannot be used here 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x | | 15 | *not x, z, *not x 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y | ^^^^^^ Syntax Error: Boolean expression cannot be used here 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x | | 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 19 | *lambda x: x, z, *lambda x: x 20 | *x := 2, z, *x := 2 | | 16 | *x and y, z, *x and y 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 19 | *lambda x: x, z, *lambda x: x 20 | *x := 2, z, *x := 2 | | 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 20 | *x := 2, z, *x := 2 | | 17 | *x or y, z, *x or y 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 20 | *x := 2, z, *x := 2 | | 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x 20 | *x := 2, z, *x := 2 | ^^ Syntax Error: Expected a statement | 18 | *x if True else y, z, *x if True else y 19 | *lambda x: x, z, *lambda x: x 20 | *x := 2, z, *x := 2 | ^^ Syntax Error: Expected `,`, found `:=` invalid_syntax@expressions__set__comprehension.py.snap000064400000000000000000001135631046102023000347350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..327, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..31, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 17..31, elt: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 20..30, node_index: NodeIndex(None), target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..48, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 32..48, elt: Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 35..47, node_index: NodeIndex(None), target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 39..42, value: StringLiteralValue { inner: Single( StringLiteral { range: 39..42, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..68, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 49..68, elt: Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 52..67, node_index: NodeIndex(None), target: Call( ExprCall { node_index: NodeIndex(None), range: 56..62, func: Name( ExprName { node_index: NodeIndex(None), range: 56..60, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 60..62, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 69..88, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 69..88, elt: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 72..87, node_index: NodeIndex(None), target: Set( ExprSet { node_index: NodeIndex(None), range: 76..82, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("b"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 105..120, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 105..120, elt: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 108..119, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Store, }, ), iter: Starred( ExprStarred { node_index: NodeIndex(None), range: 117..119, value: Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..141, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 121..141, elt: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 124..140, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 133..140, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 142..167, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 142..167, elt: Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 145..166, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 149..150, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 154..166, value: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 168..192, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 168..192, elt: Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 171..191, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 175..176, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 180..191, parameters: Some( Parameters { range: 187..188, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 187..188, node_index: NodeIndex(None), parameter: Parameter { range: 187..188, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 187..188, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 207..230, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 207..230, elt: Name( ExprName { node_index: NodeIndex(None), range: 208..209, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 210..229, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 219..223, id: Name("data"), ctx: Load, }, ), ifs: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 227..229, value: Name( ExprName { node_index: NodeIndex(None), range: 228..229, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 231..259, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 231..259, elt: Name( ExprName { node_index: NodeIndex(None), range: 232..233, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 234..258, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 238..239, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 243..247, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 251..258, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 257..258, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 260..293, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 260..293, elt: Name( ExprName { node_index: NodeIndex(None), range: 261..262, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 263..292, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 267..268, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 272..276, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 280..292, value: Name( ExprName { node_index: NodeIndex(None), range: 291..292, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 294..326, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 294..326, elt: Name( ExprName { node_index: NodeIndex(None), range: 295..296, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 297..325, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 301..302, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 306..310, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 314..325, parameters: Some( Parameters { range: 321..322, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 321..322, node_index: NodeIndex(None), parameter: Parameter { range: 321..322, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 321..322, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # Invalid target 2 | {x for 1 in y} | ^ Syntax Error: Invalid assignment target 3 | {x for 'a' in y} 4 | {x for call() in y} | | 1 | # Invalid target 2 | {x for 1 in y} 3 | {x for 'a' in y} | ^^^ Syntax Error: Invalid assignment target 4 | {x for call() in y} 5 | {x for {a, b} in y} | | 2 | {x for 1 in y} 3 | {x for 'a' in y} 4 | {x for call() in y} | ^^^^^^ Syntax Error: Invalid assignment target 5 | {x for {a, b} in y} | | 3 | {x for 'a' in y} 4 | {x for call() in y} 5 | {x for {a, b} in y} | ^^^^^^ Syntax Error: Invalid assignment target 6 | 7 | # Invalid iter | | 7 | # Invalid iter 8 | {x for x in *y} | ^^ Syntax Error: Starred expression cannot be used here 9 | {x for x in yield y} 10 | {x for x in yield from y} | | 7 | # Invalid iter 8 | {x for x in *y} 9 | {x for x in yield y} | ^^^^^^^ Syntax Error: Yield expression cannot be used here 10 | {x for x in yield from y} 11 | {x for x in lambda y: y} | | 8 | {x for x in *y} 9 | {x for x in yield y} 10 | {x for x in yield from y} | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 11 | {x for x in lambda y: y} | | 9 | {x for x in yield y} 10 | {x for x in yield from y} 11 | {x for x in lambda y: y} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 12 | 13 | # Invalid if | | 13 | # Invalid if 14 | {x for x in data if *y} | ^^ Syntax Error: Starred expression cannot be used here 15 | {x for x in data if yield y} 16 | {x for x in data if yield from y} | | 13 | # Invalid if 14 | {x for x in data if *y} 15 | {x for x in data if yield y} | ^^^^^^^ Syntax Error: Yield expression cannot be used here 16 | {x for x in data if yield from y} 17 | {x for x in data if lambda y: y} | | 14 | {x for x in data if *y} 15 | {x for x in data if yield y} 16 | {x for x in data if yield from y} | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 17 | {x for x in data if lambda y: y} | | 15 | {x for x in data if yield y} 16 | {x for x in data if yield from y} 17 | {x for x in data if lambda y: y} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here invalid_syntax@expressions__set__missing_closing_curly_brace_0.py.snap000064400000000000000000000023551046102023000400400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/missing_closing_curly_brace_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 46..47, value: Set( ExprSet { node_index: NodeIndex(None), range: 46..47, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 47..47, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # Missing closing curly brace 0: No elements 2 | 3 | { | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__set__missing_closing_curly_brace_1.py.snap000064400000000000000000000040631046102023000400370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/missing_closing_curly_brace_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..136, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 128..136, value: Set( ExprSet { node_index: NodeIndex(None), range: 128..136, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 131..136, left: Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 4 | { 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__set__missing_closing_curly_brace_2.py.snap000064400000000000000000000047621046102023000400460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/missing_closing_curly_brace_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 134..144, value: Set( ExprSet { node_index: NodeIndex(None), range: 134..144, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 139..144, left: Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 4 | {1, 5 | 6 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__set__missing_closing_curly_brace_3.py.snap000064400000000000000000000056161046102023000400460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/missing_closing_curly_brace_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 118..123, value: Set( ExprSet { node_index: NodeIndex(None), range: 118..123, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 2, ), }, ), ], }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 125..144, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 129..132, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 132..134, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 140..144, }, ), ], }, ), ], }, ) ``` ## Errors | 2 | # token starts a statement. 3 | 4 | {1, 2 | ^ Syntax Error: Expected `}`, found newline 5 | 6 | def foo(): 7 | pass | invalid_syntax@expressions__set__recover.py.snap000064400000000000000000000272231046102023000335260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/recover.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..323, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 197..200, value: Set( ExprSet { node_index: NodeIndex(None), range: 197..200, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 198..198, id: Name(""), ctx: Invalid, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 202..208, value: Set( ExprSet { node_index: NodeIndex(None), range: 202..208, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 203..204, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 206..207, value: Int( 2, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 210..215, value: Set( ExprSet { node_index: NodeIndex(None), range: 210..215, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 211..212, value: Int( 1, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 233..238, value: Set( ExprSet { node_index: NodeIndex(None), range: 233..238, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 234..235, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 236..237, value: Int( 2, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 271..277, value: Dict( ExprDict { node_index: NodeIndex(None), range: 271..277, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 272..273, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 275..276, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 300..309, value: Set( ExprSet { node_index: NodeIndex(None), range: 300..309, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 301..302, value: Int( 1, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 304..307, left: Name( ExprName { node_index: NodeIndex(None), range: 304..305, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 307..307, id: Name(""), ctx: Invalid, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 311..317, value: Set( ExprSet { node_index: NodeIndex(None), range: 311..317, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 312..313, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 315..316, value: Int( 2, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 319..322, value: List( ExprList { node_index: NodeIndex(None), range: 319..322, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 320..321, value: Name( ExprName { node_index: NodeIndex(None), range: 321..321, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 3 | # These are same as for the list expressions. 4 | 5 | {,} | ^ Syntax Error: Expected an expression 6 | 7 | {1,,2} | | 5 | {,} 6 | 7 | {1,,2} | ^ Syntax Error: Expected an expression or a '}' 8 | 9 | {1,,} | | 7 | {1,,2} 8 | 9 | {1,,} | ^ Syntax Error: Expected an expression or a '}' 10 | 11 | # Missing comma | | 11 | # Missing comma 12 | {1 2} | ^ Syntax Error: Expected `,`, found int 13 | 14 | # Dictionary element in a list | | 17 | # Missing expression 18 | {1, x + } | ^ Syntax Error: Expected an expression 19 | 20 | {1; 2} | | 18 | {1, x + } 19 | 20 | {1; 2} | ^ Syntax Error: Expected an expression or a '}' 21 | 22 | [*] | | 20 | {1; 2} 21 | 22 | [*] | ^ Syntax Error: Expected an expression invalid_syntax@expressions__set__star_expression_precedence.py.snap000064400000000000000000000561301046102023000374650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/set/star_expression_precedence.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..198, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..92, value: Set( ExprSet { node_index: NodeIndex(None), range: 83..92, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 85..87, value: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..105, value: Set( ExprSet { node_index: NodeIndex(None), range: 93..105, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 94..101, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 95..101, left: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 103..104, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 106..117, value: Set( ExprSet { node_index: NodeIndex(None), range: 106..117, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 107..113, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 108..113, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 115..116, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 118..131, value: Set( ExprSet { node_index: NodeIndex(None), range: 118..131, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 119..127, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 120..127, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 120..121, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 132..144, value: Set( ExprSet { node_index: NodeIndex(None), range: 132..144, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 133..140, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 134..140, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 134..135, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 142..143, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 145..167, value: Set( ExprSet { node_index: NodeIndex(None), range: 145..167, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 146..163, value: If( ExprIf { node_index: NodeIndex(None), range: 147..163, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 152..156, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 147..148, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 162..163, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 168..185, value: Set( ExprSet { node_index: NodeIndex(None), range: 168..185, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 169..181, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 170..181, parameters: Some( Parameters { range: 177..178, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 177..178, node_index: NodeIndex(None), parameter: Parameter { range: 177..178, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 177..178, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 180..181, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 183..184, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 186..198, value: Set( ExprSet { node_index: NodeIndex(None), range: 186..198, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 187..194, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 187..189, value: Name( ExprName { node_index: NodeIndex(None), range: 188..189, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 193..194, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("z"), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # For set expression, the minimum binding power of star expression is bitwise or. 2 | 3 | {(*x), y} | ^^ Syntax Error: Starred expression cannot be used here 4 | {*x in y, z} 5 | {*not x, z} | | 3 | {(*x), y} 4 | {*x in y, z} | ^^^^^^ Syntax Error: Comparison expression cannot be used here 5 | {*not x, z} 6 | {*x and y, z} | | 3 | {(*x), y} 4 | {*x in y, z} 5 | {*not x, z} | ^^^^^ Syntax Error: Boolean expression cannot be used here 6 | {*x and y, z} 7 | {*x or y, z} | | 4 | {*x in y, z} 5 | {*not x, z} 6 | {*x and y, z} | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 7 | {*x or y, z} 8 | {*x if True else y, z} | | 5 | {*not x, z} 6 | {*x and y, z} 7 | {*x or y, z} | ^^^^^^ Syntax Error: Boolean expression cannot be used here 8 | {*x if True else y, z} 9 | {*lambda x: x, z} | | 6 | {*x and y, z} 7 | {*x or y, z} 8 | {*x if True else y, z} | ^^^^^^^^^^^^^^^^ Syntax Error: Conditional expression cannot be used here 9 | {*lambda x: x, z} 10 | {*x := 2, z} | | 7 | {*x or y, z} 8 | {*x if True else y, z} 9 | {*lambda x: x, z} | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 10 | {*x := 2, z} | | 8 | {*x if True else y, z} 9 | {*lambda x: x, z} 10 | {*x := 2, z} | ^^ Syntax Error: Assignment expression target must be an identifier invalid_syntax@expressions__subscript__invalid_slice_element.py.snap000064400000000000000000000331431046102023000376200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/subscript/invalid_slice_element.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..133, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..10, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 2..9, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 2..8, target: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 33..39, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 33..39, value: Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 35..38, lower: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 35..37, value: Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 40..46, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 40..46, value: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 42..45, lower: None, upper: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 43..45, value: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 47..54, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 47..54, value: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 49..53, lower: None, upper: None, step: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 51..53, value: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 70..73, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 70..73, value: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 123..133, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 123..133, value: Name( ExprName { node_index: NodeIndex(None), range: 123..124, id: Name("x"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 125..132, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 125..127, value: Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 131..132, value: Int( 1, ), }, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x[x := 1:] | ^^^^^^ Syntax Error: Unparenthesized named expression cannot be used here 2 | 3 | # Starred expression | | 3 | # Starred expression 4 | x[*x:] | ^^ Syntax Error: Starred expression cannot be used here 5 | x[:*x] 6 | x[::*x] | | 3 | # Starred expression 4 | x[*x:] 5 | x[:*x] | ^^ Syntax Error: Starred expression cannot be used here 6 | x[::*x] | | 4 | x[*x:] 5 | x[:*x] 6 | x[::*x] | ^^ Syntax Error: Starred expression cannot be used here 7 | 8 | # Empty slice | | 8 | # Empty slice 9 | x[] | ^ Syntax Error: Expected index or slice expression 10 | 11 | # Mixed starred expression and named expression | | 11 | # Mixed starred expression and named expression 12 | x[*x := 1] | ^^ Syntax Error: Assignment expression target must be an identifier invalid_syntax@expressions__subscript__unclosed_slice_0.py.snap000064400000000000000000000057631046102023000365230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/subscript/unclosed_slice_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..10, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 2..10, lower: None, upper: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("y"), ctx: Load, }, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | x[: 2 | 3 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__subscript__unclosed_slice_1.py.snap000064400000000000000000000074531046102023000365220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/subscript/unclosed_slice_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..25, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..9, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 2..9, lower: None, upper: None, step: Some( Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("def"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 10..25, target: Call( ExprCall { node_index: NodeIndex(None), range: 10..15, func: Name( ExprName { node_index: NodeIndex(None), range: 10..13, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 13..15, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 21..25, id: Name("pass"), ctx: Load, }, ), value: None, simple: false, }, ), ], }, ) ``` ## Errors | 1 | x[:: 2 | 3 | def foo(): | ^^^ Syntax Error: Expected an identifier, but found a keyword `def` that cannot be used here 4 | pass | | 1 | x[:: 2 | 3 | def foo(): | ^^^ Syntax Error: Expected `]`, found name 4 | pass | | 3 | def foo(): 4 | pass | ^^^^ Syntax Error: Expected an identifier, but found a keyword `pass` that cannot be used here | 3 | def foo(): 4 | pass | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@expressions__unary.py.snap000064400000000000000000000031451046102023000322020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/unary.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 0..5, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..10, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | not x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__unary__named_expression.py.snap000064400000000000000000000057401046102023000357670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/unary/named_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..18, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..2, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 0..2, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 6..7, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..13, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 8..13, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 17..18, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..18, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | -x := 1 | ^^ Syntax Error: Expected a statement 2 | not x := 1 | | 1 | -x := 1 2 | not x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@expressions__unary__no_expression_0.py.snap000064400000000000000000000043771046102023000355430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/unary/no_expression_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 0..3, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..10, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | not | ^ Syntax Error: Expected an expression 2 | 3 | x + y | invalid_syntax@expressions__unary__no_expression_1.py.snap000064400000000000000000000043701046102023000355350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/unary/no_expression_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..8, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..1, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 0..1, op: UAdd, operand: Name( ExprName { node_index: NodeIndex(None), range: 1..1, id: Name(""), ctx: Invalid, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 3..8, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 3..8, left: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | + | ^ Syntax Error: Expected an expression 2 | 3 | x + y | invalid_syntax@expressions__yield__named_expression.py.snap000064400000000000000000000116041046102023000357330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/yield/named_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 52..59, value: Yield( ExprYield { node_index: NodeIndex(None), range: 52..59, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 63..64, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 66..84, value: Yield( ExprYield { node_index: NodeIndex(None), range: 66..84, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 72..84, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 72..73, value: Int( 1, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 80..81, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Unparenthesized named expressions are not allowed 2 | yield x := 1 | ^^ Syntax Error: Expected a statement 3 | 4 | yield 1, x := 2, 3 | | 2 | yield x := 1 3 | 4 | yield 1, x := 2, 3 | ^^ Syntax Error: Expected `,`, found `:=` invalid_syntax@expressions__yield__star_expression.py.snap000064400000000000000000000132171046102023000356220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/yield/star_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 37..47, value: Yield( ExprYield { node_index: NodeIndex(None), range: 37..47, value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 44..46, value: Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..66, value: Yield( ExprYield { node_index: NodeIndex(None), range: 49..66, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 55..66, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 55..63, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 56..63, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Cannot use starred expression here 2 | yield (*x) | ^^ Syntax Error: Starred expression cannot be used here 3 | 4 | yield *x and y, z | | 2 | yield (*x) 3 | 4 | yield *x and y, z | ^^^^^^^ Syntax Error: Boolean expression cannot be used here ## Semantic Syntax Errors | 1 | # Cannot use starred expression here 2 | yield (*x) | ^^ Syntax Error: Starred expression cannot be used here 3 | 4 | yield *x and y, z | invalid_syntax@expressions__yield_from__starred_expression.py.snap000064400000000000000000000076151046102023000373450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/yield_from/starred_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..100, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 70..83, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 70..83, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 81..83, value: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 84..100, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 84..100, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 95..100, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 95..97, value: Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Yield from doesn't allow top-level starred expression unlike yield 2 | 3 | yield from *x | ^^ Syntax Error: Starred expression cannot be used here 4 | yield from *x, y | | 3 | yield from *x 4 | yield from *x, y | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@expressions__yield_from__unparenthesized.py.snap000064400000000000000000000163451046102023000366320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/expressions/yield_from/unparenthesized.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..192, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 35..47, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 35..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 51..52, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 89..104, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 89..104, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 100..104, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 103..104, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 168..192, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 168..192, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 179..192, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 180..181, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 183..191, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 184..191, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 184..185, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # Unparenthesized named expression 2 | yield from x := 1 | ^^ Syntax Error: Expected a statement 3 | 4 | # Unparenthesized tuple expression | | 4 | # Unparenthesized tuple expression 5 | yield from x, y | ^^^^ Syntax Error: Unparenthesized tuple expression cannot be used here 6 | 7 | # This is a tuple expression parsing | | 7 | # This is a tuple expression parsing 8 | # vvvvvvvvvvvvv 9 | yield from (x, *x and y) | ^^^^^^^ Syntax Error: Boolean expression cannot be used here invalid_syntax@f_string_conversion_follows_exclamation.py.snap000064400000000000000000000201761046102023000364570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_conversion_follows_exclamation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..9, value: FStringValue { inner: Single( FString( FString { range: 0..9, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..8, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..19, value: TString( ExprTString { node_index: NodeIndex(None), range: 10..19, value: TStringValue { inner: Single( TString { range: 10..19, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 12..18, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..29, value: FString( ExprFString { node_index: NodeIndex(None), range: 20..29, value: FStringValue { inner: Single( FString( FString { range: 20..29, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 22..28, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{x! s}" | ^ Syntax Error: f-string: conversion type must come right after the exclamation mark 2 | t"{x! s}" 3 | f"{x! z}" | | 1 | f"{x! s}" 2 | t"{x! s}" | ^ Syntax Error: t-string: conversion type must come right after the exclamation mark 3 | f"{x! z}" | | 1 | f"{x! s}" 2 | t"{x! s}" 3 | f"{x! z}" | ^ Syntax Error: f-string: conversion type must come right after the exclamation mark | 1 | f"{x! s}" 2 | t"{x! s}" 3 | f"{x! z}" | ^ Syntax Error: f-string: invalid conversion character invalid_syntax@f_string_empty_expression.py.snap000064400000000000000000000126601046102023000335550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_empty_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..14, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..5, value: FStringValue { inner: Single( FString( FString { range: 0..5, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..4, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 6..13, value: FString( ExprFString { node_index: NodeIndex(None), range: 6..13, value: FStringValue { inner: Single( FString( FString { range: 6..13, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 8..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 9..9, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{}" | ^ Syntax Error: Expected an expression 2 | f"{ }" | | 1 | f"{}" 2 | f"{ }" | ^ Syntax Error: Expected an expression invalid_syntax@f_string_invalid_conversion_flag_name_tok.py.snap000064400000000000000000000055731046102023000367060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_invalid_conversion_flag_name_tok.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..9, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..8, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..8, value: FStringValue { inner: Single( FString( FString { range: 0..8, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..7, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{x!z}" | ^ Syntax Error: f-string: invalid conversion character invalid_syntax@f_string_invalid_conversion_flag_other_tok.py.snap000064400000000000000000000127741046102023000371100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_invalid_conversion_flag_other_tok.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..22, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..10, value: FStringValue { inner: Single( FString( FString { range: 0..10, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..9, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..21, value: FString( ExprFString { node_index: NodeIndex(None), range: 11..21, value: FStringValue { inner: Single( FString( FString { range: 11..21, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 13..20, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{x!123}" | ^^^ Syntax Error: f-string: invalid conversion character 2 | f"{x!'a'}" | | 1 | f"{x!123}" 2 | f"{x!'a'}" | ^^^ Syntax Error: f-string: invalid conversion character invalid_syntax@f_string_invalid_starred_expr.py.snap000064400000000000000000000303531046102023000343470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_invalid_starred_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 77..83, value: FString( ExprFString { node_index: NodeIndex(None), range: 77..83, value: FStringValue { inner: Single( FString( FString { range: 77..83, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 79..82, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 80..81, value: Name( ExprName { node_index: NodeIndex(None), range: 81..81, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 84..97, value: FString( ExprFString { node_index: NodeIndex(None), range: 84..97, value: FStringValue { inner: Single( FString( FString { range: 84..97, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 86..96, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 87..95, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 88..95, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 94..95, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 98..111, value: FString( ExprFString { node_index: NodeIndex(None), range: 98..111, value: FStringValue { inner: Single( FString( FString { range: 98..111, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 100..110, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 101..109, value: Yield( ExprYield { node_index: NodeIndex(None), range: 102..109, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # Starred expression inside f-string has a minimum precedence of bitwise or. 2 | f"{*}" | ^ Syntax Error: Expected an expression 3 | f"{*x and y}" 4 | f"{*yield x}" | | 1 | # Starred expression inside f-string has a minimum precedence of bitwise or. 2 | f"{*}" 3 | f"{*x and y}" | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 4 | f"{*yield x}" | | 2 | f"{*}" 3 | f"{*x and y}" 4 | f"{*yield x}" | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@f_string_lambda_without_parentheses.py.snap000064400000000000000000000150751046102023000355470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_lambda_without_parentheses.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..17, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..16, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..16, value: FStringValue { inner: Single( FString( FString { range: 0..16, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..12, node_index: NodeIndex(None), expression: Lambda( ExprLambda { node_index: NodeIndex(None), range: 3..12, parameters: Some( Parameters { range: 10..11, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 10..11, node_index: NodeIndex(None), parameter: Parameter { range: 10..11, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 10..11, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 12..12, id: Name(""), ctx: Invalid, }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 12..14, node_index: NodeIndex(None), value: " x", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{lambda x: x}" | ^^ Syntax Error: Expected an expression | 1 | f"{lambda x: x}" | ^^^^^^^^^ Syntax Error: f-string: lambda expressions are not allowed without parentheses | 1 | f"{lambda x: x}" | ^^ Syntax Error: f-string: expecting `}` | 1 | f"{lambda x: x}" | ^ Syntax Error: Expected an element of or the end of the f-string invalid_syntax@f_string_unclosed_lbrace.py.snap000064400000000000000000000331641046102023000332660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..38, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..4, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..4, value: FStringValue { inner: Single( FString( FString { range: 0..4, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2..3, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..14, value: FString( ExprFString { node_index: NodeIndex(None), range: 5..14, value: FStringValue { inner: Single( FString( FString { range: 5..14, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 7..13, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 8..11, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Repr, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..23, value: FString( ExprFString { node_index: NodeIndex(None), range: 15..23, value: FStringValue { inner: Single( FString( FString { range: 15..23, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 17..22, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 18..21, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "foo", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 24..28, value: FString( ExprFString { node_index: NodeIndex(None), range: 24..28, value: FStringValue { inner: Single( FString( FString { range: 24..28, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 26..27, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 27..27, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 29..37, value: FString( ExprFString { node_index: NodeIndex(None), range: 29..37, value: FStringValue { inner: Single( FString( FString { range: 29..37, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 33..34, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 34..34, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"{" | ^ Syntax Error: Expected an expression 2 | f"{foo!r" 3 | f"{foo=" | | 1 | f"{" 2 | f"{foo!r" | ^ Syntax Error: f-string: expecting `}` 3 | f"{foo=" 4 | f"{" | | 1 | f"{" 2 | f"{foo!r" 3 | f"{foo=" | ^ Syntax Error: f-string: expecting `}` 4 | f"{" 5 | f"""{""" | | 2 | f"{foo!r" 3 | f"{foo=" 4 | f"{" | ^ Syntax Error: Expected an expression 5 | f"""{""" | | 3 | f"{foo=" 4 | f"{" 5 | f"""{""" | ^^^ Syntax Error: Expected an expression invalid_syntax@f_string_unclosed_lbrace_in_format_spec.py.snap000064400000000000000000000177711046102023000363440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/f_string_unclosed_lbrace_in_format_spec.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..29, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..12, value: FStringValue { inner: Single( FString( FString { range: 0..12, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..8, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 8..11, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 11..11, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..28, value: FString( ExprFString { node_index: NodeIndex(None), range: 13..28, value: FStringValue { inner: Single( FString( FString { range: 13..28, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 15..21, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 21..27, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 24..27, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 24..27, node_index: NodeIndex(None), value: ".3f", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f"hello {x:" | ^ Syntax Error: f-string: expecting `}` 2 | f"hello {x:.3f" | | 1 | f"hello {x:" 2 | f"hello {x:.3f" | ^ Syntax Error: f-string: expecting `}` invalid_syntax@for_iter_unpack_py38.py.snap000064400000000000000000000230261046102023000323000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_iter_unpack_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..106, body: [ For( StmtFor { node_index: NodeIndex(None), range: 43..63, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 52..58, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 52..54, value: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 60..63, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 60..63, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 64..84, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 74..79, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 77..79, value: Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 85..105, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 94..100, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 98..100, value: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 102..105, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 102..105, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | for x in *a, b: ... | ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9) 3 | for x in a, *b: ... 4 | for x in *a, *b: ... | | 1 | # parse_options: {"target-version": "3.8"} 2 | for x in *a, b: ... 3 | for x in a, *b: ... | ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9) 4 | for x in *a, *b: ... | | 2 | for x in *a, b: ... 3 | for x in a, *b: ... 4 | for x in *a, *b: ... | ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9) | 2 | for x in *a, b: ... 3 | for x in a, *b: ... 4 | for x in *a, *b: ... | ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@for_stmt_invalid_iter_expr.py.snap000064400000000000000000000162471046102023000336760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_iter_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..71, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..22, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Store, }, ), iter: Starred( ExprStarred { node_index: NodeIndex(None), range: 9..17, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 10..17, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("b"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 23..44, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 32..39, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("a"), ctx: Load, }, ), ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 41..44, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 41..44, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 45..60, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 49..55, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("x"), ctx: Load, }, ), body: [], orelse: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 64..70, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..65, value: Int( 1, ), }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 67..70, }, ), value: None, simple: false, }, ), ], }, ) ``` ## Errors | 1 | for x in *a and b: ... | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 2 | for x in yield a: ... 3 | for target in x := 1: ... | | 1 | for x in *a and b: ... 2 | for x in yield a: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | for target in x := 1: ... | | 1 | for x in *a and b: ... 2 | for x in yield a: ... 3 | for target in x := 1: ... | ^^ Syntax Error: Expected `:`, found `:=` | 1 | for x in *a and b: ... 2 | for x in yield a: ... 3 | for target in x := 1: ... | ^ Syntax Error: Invalid annotated assignment target ## Semantic Syntax Errors | 1 | for x in *a and b: ... | ^^^^^^^^ Syntax Error: Starred expression cannot be used here 2 | for x in yield a: ... 3 | for target in x := 1: ... | invalid_syntax@for_stmt_invalid_target.py.snap000064400000000000000000000510441046102023000331550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..154, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..15, is_async: false, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 1, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 12..15, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 12..15, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 16..33, is_async: false, target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 20..23, value: StringLiteralValue { inner: Single( StringLiteral { range: 20..23, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 30..33, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 30..33, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 34..56, is_async: false, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 38..46, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 39..46, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..56, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 53..56, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 57..77, is_async: false, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 61..67, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 62..67, left: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Load, }, ), }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 74..77, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 74..77, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 78..99, is_async: false, target: Await( ExprAwait { node_index: NodeIndex(None), range: 82..89, value: Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("x"), ctx: Load, }, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 100..121, is_async: false, target: Yield( ExprYield { node_index: NodeIndex(None), range: 104..116, value: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 110..116, left: Name( ExprName { node_index: NodeIndex(None), range: 110..111, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 115..116, id: Name("y"), ctx: Load, }, ), ], }, ), ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 116..116, id: Name(""), ctx: Invalid, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 118..121, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 118..121, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 122..153, is_async: false, target: List( ExprList { node_index: NodeIndex(None), range: 126..143, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("x"), ctx: Store, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 130..131, value: Int( 1, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 133..134, id: Name("y"), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 136..142, value: List( ExprList { node_index: NodeIndex(None), range: 137..142, elts: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 138..141, value: StringLiteralValue { inner: Single( StringLiteral { range: 138..141, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 147..148, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 150..153, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 150..153, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for 1 in x: ... | ^ Syntax Error: Invalid assignment target 2 | for "a" in x: ... 3 | for *x and y in z: ... | | 1 | for 1 in x: ... 2 | for "a" in x: ... | ^^^ Syntax Error: Invalid assignment target 3 | for *x and y in z: ... 4 | for *x | y in z: ... | | 1 | for 1 in x: ... 2 | for "a" in x: ... 3 | for *x and y in z: ... | ^^^^^^^ Syntax Error: Invalid assignment target 4 | for *x | y in z: ... 5 | for await x in z: ... | | 2 | for "a" in x: ... 3 | for *x and y in z: ... 4 | for *x | y in z: ... | ^^^^^ Syntax Error: Invalid assignment target 5 | for await x in z: ... 6 | for yield x in y: ... | | 3 | for *x and y in z: ... 4 | for *x | y in z: ... 5 | for await x in z: ... | ^^^^^^^ Syntax Error: Invalid assignment target 6 | for yield x in y: ... 7 | for [x, 1, y, *["a"]] in z: ... | | 4 | for *x | y in z: ... 5 | for await x in z: ... 6 | for yield x in y: ... | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 7 | for [x, 1, y, *["a"]] in z: ... | | 4 | for *x | y in z: ... 5 | for await x in z: ... 6 | for yield x in y: ... | ^ Syntax Error: Expected `in`, found `:` 7 | for [x, 1, y, *["a"]] in z: ... | | 5 | for await x in z: ... 6 | for yield x in y: ... 7 | for [x, 1, y, *["a"]] in z: ... | ^ Syntax Error: Invalid assignment target | 5 | for await x in z: ... 6 | for yield x in y: ... 7 | for [x, 1, y, *["a"]] in z: ... | ^^^ Syntax Error: Invalid assignment target ## Semantic Syntax Errors | 1 | for 1 in x: ... 2 | for "a" in x: ... 3 | for *x and y in z: ... | ^^^^^^^^ Syntax Error: Starred expression cannot be used here 4 | for *x | y in z: ... 5 | for await x in z: ... | | 2 | for "a" in x: ... 3 | for *x and y in z: ... 4 | for *x | y in z: ... | ^^^^^^ Syntax Error: Starred expression cannot be used here 5 | for await x in z: ... 6 | for yield x in y: ... | invalid_syntax@for_stmt_invalid_target_binary_expr.py.snap000064400000000000000000000326161046102023000355630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_target_binary_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..124, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..24, is_async: false, target: Compare( ExprCompare { node_index: NodeIndex(None), range: 4..14, left: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("y"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 25..45, is_async: false, target: Compare( ExprCompare { node_index: NodeIndex(None), range: 29..35, left: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("y"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 42..45, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 42..45, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 46..66, is_async: false, target: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 50..56, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("y"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 63..66, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 63..66, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 67..83, is_async: false, target: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 71..73, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("x"), ctx: Store, }, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("y"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 80..83, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 80..83, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 84..103, is_async: false, target: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 88..93, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("x"), ctx: Store, }, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("y"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 100..103, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 100..103, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 104..123, is_async: false, target: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 108..113, left: Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("y"), ctx: Load, }, ), }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 117..118, id: Name("z"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 120..123, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 120..123, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for x not in y in z: ... | ^^^^^^^^^^ Syntax Error: Invalid assignment target 2 | for x == y in z: ... 3 | for x or y in z: ... | | 1 | for x not in y in z: ... 2 | for x == y in z: ... | ^^^^^^ Syntax Error: Invalid assignment target 3 | for x or y in z: ... 4 | for -x in y: ... | | 1 | for x not in y in z: ... 2 | for x == y in z: ... 3 | for x or y in z: ... | ^^^^^^ Syntax Error: Invalid assignment target 4 | for -x in y: ... 5 | for not x in y: ... | | 2 | for x == y in z: ... 3 | for x or y in z: ... 4 | for -x in y: ... | ^^ Syntax Error: Invalid assignment target 5 | for not x in y: ... 6 | for x | y in z: ... | | 3 | for x or y in z: ... 4 | for -x in y: ... 5 | for not x in y: ... | ^^^^^ Syntax Error: Invalid assignment target 6 | for x | y in z: ... | | 4 | for -x in y: ... 5 | for not x in y: ... 6 | for x | y in z: ... | ^^^^^ Syntax Error: Invalid assignment target invalid_syntax@for_stmt_invalid_target_in_keyword.py.snap000064400000000000000000000475671046102023000354260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_invalid_target_in_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..170, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..28, is_async: false, target: Call( ExprCall { node_index: NodeIndex(None), range: 4..13, func: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("d"), ctx: Load, }, ), arguments: Arguments { range: 5..13, node_index: NodeIndex(None), args: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 6..12, left: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("y"), ctx: Load, }, ), ], }, ), ], keywords: [], }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 17..23, id: Name("target"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 29..56, is_async: false, target: Call( ExprCall { node_index: NodeIndex(None), range: 33..43, func: Compare( ExprCompare { node_index: NodeIndex(None), range: 34..40, left: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Load, }, ), ], }, ), arguments: Arguments { range: 41..43, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 47..51, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..56, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 53..56, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 57..82, is_async: false, target: Compare( ExprCompare { node_index: NodeIndex(None), range: 62..68, left: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("y"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 73..77, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 79..82, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 79..82, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 83..111, is_async: false, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 87..98, elts: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 88..94, left: Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("y"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("z"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 102..106, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 108..111, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 108..111, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 112..140, is_async: false, target: List( ExprList { node_index: NodeIndex(None), range: 116..127, elts: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 117..123, left: Name( ExprName { node_index: NodeIndex(None), range: 117..118, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("y"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("z"), ctx: Store, }, ), ], ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 131..135, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 137..140, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 137..140, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 141..169, is_async: false, target: Set( ExprSet { node_index: NodeIndex(None), range: 145..156, elts: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 146..152, left: Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("y"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 154..155, id: Name("z"), ctx: Load, }, ), ], }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 160..164, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 166..169, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 166..169, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for d(x in y) in target: ... | ^^^^^^^^^ Syntax Error: Invalid assignment target 2 | for (x in y)() in iter: ... 3 | for (x in y) in iter: ... | | 1 | for d(x in y) in target: ... 2 | for (x in y)() in iter: ... | ^^^^^^^^^^ Syntax Error: Invalid assignment target 3 | for (x in y) in iter: ... 4 | for (x in y, z) in iter: ... | | 1 | for d(x in y) in target: ... 2 | for (x in y)() in iter: ... 3 | for (x in y) in iter: ... | ^^^^^^ Syntax Error: Invalid assignment target 4 | for (x in y, z) in iter: ... 5 | for [x in y, z] in iter: ... | | 2 | for (x in y)() in iter: ... 3 | for (x in y) in iter: ... 4 | for (x in y, z) in iter: ... | ^^^^^^ Syntax Error: Invalid assignment target 5 | for [x in y, z] in iter: ... 6 | for {x in y, z} in iter: ... | | 3 | for (x in y) in iter: ... 4 | for (x in y, z) in iter: ... 5 | for [x in y, z] in iter: ... | ^^^^^^ Syntax Error: Invalid assignment target 6 | for {x in y, z} in iter: ... | | 4 | for (x in y, z) in iter: ... 5 | for [x in y, z] in iter: ... 6 | for {x in y, z} in iter: ... | ^^^^^^^^^^^ Syntax Error: Invalid assignment target invalid_syntax@for_stmt_missing_in_keyword.py.snap000064400000000000000000000064011046102023000340610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_missing_in_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..12, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("a"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("b"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..12, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 9..12, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 13..23, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("a"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 18..18, id: Name(""), ctx: Invalid, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for a b: ... | ^ Syntax Error: Expected `in`, found name 2 | for a: ... | | 1 | for a b: ... 2 | for a: ... | ^ Syntax Error: Expected `in`, found `:` invalid_syntax@for_stmt_missing_iter.py.snap000064400000000000000000000046151046102023000326570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_missing_iter.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..20, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..19, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 8..8, id: Name(""), ctx: Invalid, }, ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 14..19, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("a"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for x in: | ^ Syntax Error: Expected an expression 2 | a = 1 | invalid_syntax@for_stmt_missing_target.py.snap000064400000000000000000000033711046102023000332000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/for_stmt_missing_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..14, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..13, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 3..3, id: Name(""), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 10..13, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 10..13, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | for in x: ... | ^^ Syntax Error: Expected an identifier invalid_syntax@from_import_dotted_names.py.snap000064400000000000000000000153611046102023000333310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_dotted_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..16, module: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 14..15, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 14..15, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 17..34, module: Some( Identifier { id: Name("x"), range: 22..23, node_index: NodeIndex(None), }, ), names: [ Alias { range: 31..32, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 31..32, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 33..34, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 33..34, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 35..66, module: Some( Identifier { id: Name("x"), range: 40..41, node_index: NodeIndex(None), }, ), names: [ Alias { range: 49..50, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 49..50, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 52..53, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 52..53, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 54..55, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 54..55, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 57..58, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 57..58, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 60..61, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 60..61, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 62..63, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 62..63, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 65..66, node_index: NodeIndex(None), name: Identifier { id: Name("g"), range: 65..66, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from x import a. | ^ Syntax Error: Expected `,`, found `.` 2 | from x import a.b 3 | from x import a, b.c, d, e.f, g | | 1 | from x import a. 2 | from x import a.b | ^ Syntax Error: Expected `,`, found `.` 3 | from x import a, b.c, d, e.f, g | | 1 | from x import a. 2 | from x import a.b 3 | from x import a, b.c, d, e.f, g | ^ Syntax Error: Expected `,`, found `.` | 1 | from x import a. 2 | from x import a.b 3 | from x import a, b.c, d, e.f, g | ^ Syntax Error: Expected `,`, found `.` invalid_syntax@from_import_empty_names.py.snap000064400000000000000000000050431046102023000332000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_empty_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..48, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..13, module: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), names: [], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 14..30, module: Some( Identifier { id: Name("x"), range: 19..20, node_index: NodeIndex(None), }, ), names: [], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 31..47, module: Some( Identifier { id: Name("x"), range: 36..37, node_index: NodeIndex(None), }, ), names: [], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from x import | ^ Syntax Error: Expected one or more symbol names after import 2 | from x import () 3 | from x import ,, | | 1 | from x import 2 | from x import () | ^ Syntax Error: Expected one or more symbol names after import 3 | from x import ,, | | 1 | from x import 2 | from x import () 3 | from x import ,, | ^ Syntax Error: Expected an import name | 1 | from x import 2 | from x import () 3 | from x import ,, | ^ Syntax Error: Expected an import name | 1 | from x import 2 | from x import () 3 | from x import ,, | ^ Syntax Error: Expected one or more symbol names after import invalid_syntax@from_import_missing_module.py.snap000064400000000000000000000027671046102023000337070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_missing_module.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..19, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..4, module: None, names: [], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 5..18, module: None, names: [ Alias { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 17..18, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from | ^ Syntax Error: Expected a module name 2 | from import x | | 1 | from 2 | from import x | ^^^^^^ Syntax Error: Expected a module name invalid_syntax@from_import_missing_rpar.py.snap000064400000000000000000000134451046102023000333610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_missing_rpar.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..19, module: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 15..16, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 15..16, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 18..19, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 18..19, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..25, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 20..25, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 26..46, module: Some( Identifier { id: Name("x"), range: 31..32, node_index: NodeIndex(None), }, ), names: [ Alias { range: 41..42, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 41..42, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 44..45, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 44..45, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 47..52, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 47..52, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..48, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | from x import (a, b | ^ Syntax Error: Expected `)`, found newline 2 | 1 + 1 3 | from x import (a, b, 4 | 2 + 2 | | 1 | from x import (a, b 2 | 1 + 1 3 | from x import (a, b, | ^ Syntax Error: Expected `)`, found newline 4 | 2 + 2 | invalid_syntax@from_import_parenthesized_star.py.snap000064400000000000000000000025501046102023000345550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_parenthesized_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..18, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..17, module: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 15..16, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 15..16, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from x import (*) | ^^ Syntax Error: Star import cannot be parenthesized invalid_syntax@from_import_star_with_other_names.py.snap000064400000000000000000000172451046102023000352560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_star_with_other_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..87, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..18, module: Some( Identifier { id: Name("x"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 14..15, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 14..15, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 17..18, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 19..40, module: Some( Identifier { id: Name("x"), range: 24..25, node_index: NodeIndex(None), }, ), names: [ Alias { range: 33..34, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 33..34, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 36..37, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 36..37, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 39..40, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 39..40, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 41..64, module: Some( Identifier { id: Name("x"), range: 46..47, node_index: NodeIndex(None), }, ), names: [ Alias { range: 55..56, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 55..56, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 58..64, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 58..59, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("b"), range: 63..64, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 65..86, module: Some( Identifier { id: Name("x"), range: 70..71, node_index: NodeIndex(None), }, ), names: [ Alias { range: 79..80, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 79..80, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 82..83, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 82..83, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 85..86, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 85..86, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from x import *, a | ^^^^ Syntax Error: Star import must be the only import 2 | from x import a, *, b 3 | from x import *, a as b | | 1 | from x import *, a 2 | from x import a, *, b | ^^^^^^^ Syntax Error: Star import must be the only import 3 | from x import *, a as b 4 | from x import *, *, a | | 1 | from x import *, a 2 | from x import a, *, b 3 | from x import *, a as b | ^^^^^^^^^ Syntax Error: Star import must be the only import 4 | from x import *, *, a | | 2 | from x import a, *, b 3 | from x import *, a as b 4 | from x import *, *, a | ^^^^^^^ Syntax Error: Star import must be the only import invalid_syntax@from_import_unparenthesized_trailing_comma.py.snap000064400000000000000000000105101046102023000371270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/from_import_unparenthesized_trailing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..59, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..16, module: Some( Identifier { id: Name("a"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 14..15, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 14..15, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 17..38, module: Some( Identifier { id: Name("a"), range: 22..23, node_index: NodeIndex(None), }, ), names: [ Alias { range: 31..37, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 31..32, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("c"), range: 36..37, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 39..58, module: Some( Identifier { id: Name("a"), range: 44..45, node_index: NodeIndex(None), }, ), names: [ Alias { range: 53..54, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 53..54, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 56..57, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 56..57, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | from a import b, | ^ Syntax Error: Trailing comma not allowed 2 | from a import b as c, 3 | from a import b, c, | | 1 | from a import b, 2 | from a import b as c, | ^ Syntax Error: Trailing comma not allowed 3 | from a import b, c, | | 1 | from a import b, 2 | from a import b as c, 3 | from a import b, c, | ^ Syntax Error: Trailing comma not allowed invalid_syntax@function_def_empty_body.py.snap000064400000000000000000000070071046102023000331420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_empty_body.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..10, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 11..28, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 15..18, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 18..20, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 24..27, id: Name("int"), ctx: Load, }, ), ), body: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 29..35, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..35, value: Int( 42, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | def foo(): 2 | def foo() -> int: | ^^^ Syntax Error: Expected an indented block after function definition 3 | x = 42 | | 1 | def foo(): 2 | def foo() -> int: 3 | x = 42 | ^ Syntax Error: Expected an indented block after function definition invalid_syntax@function_def_invalid_return_expr.py.snap000064400000000000000000000166641046102023000350630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_invalid_return_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..74, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..22, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..17, value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..47, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 27..30, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 30..32, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 37..41, value: Name( ExprName { node_index: NodeIndex(None), range: 38..41, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..47, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 44..47, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 48..73, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 52..55, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 55..57, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 61..68, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("x"), ctx: Load, }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 70..73, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 70..73, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo() -> *int: ... | ^^^^ Syntax Error: Starred expression cannot be used here 2 | def foo() -> (*int): ... 3 | def foo() -> yield x: ... | | 1 | def foo() -> *int: ... 2 | def foo() -> (*int): ... | ^^^^ Syntax Error: Starred expression cannot be used here 3 | def foo() -> yield x: ... | | 1 | def foo() -> *int: ... 2 | def foo() -> (*int): ... 3 | def foo() -> yield x: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here ## Semantic Syntax Errors | 1 | def foo() -> *int: ... 2 | def foo() -> (*int): ... 3 | def foo() -> yield x: ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation invalid_syntax@function_def_missing_identifier.py.snap000064400000000000000000000072651046102023000346500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_missing_identifier.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..11, is_async: false, decorator_list: [], name: Identifier { id: Name(""), range: 3..3, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 4..6, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 8..11, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 8..11, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 12..30, is_async: false, decorator_list: [], name: Identifier { id: Name(""), range: 15..15, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 16..18, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 22..25, id: Name("int"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 27..30, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 27..30, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def (): ... | ^ Syntax Error: Expected an identifier 2 | def () -> int: ... | | 1 | def (): ... 2 | def () -> int: ... | ^ Syntax Error: Expected an identifier invalid_syntax@function_def_missing_return_type.py.snap000064400000000000000000000034721046102023000351020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_missing_return_type.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..19, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..18, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 15..18, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 15..18, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo() -> : ... | ^ Syntax Error: Expected an expression invalid_syntax@function_def_unclosed_parameter_list.py.snap000064400000000000000000000242301046102023000356730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_unclosed_parameter_list.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..74, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..18, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..18, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..14, node_index: NodeIndex(None), parameter: Parameter { range: 8..14, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 11..14, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 16..18, node_index: NodeIndex(None), parameter: Parameter { range: 16..18, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 16..17, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 19..43, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 23..26, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 26..28, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 34..43, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..43, value: Int( 42, ), }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..74, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 51..74, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 52..58, node_index: NodeIndex(None), parameter: Parameter { range: 52..58, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 52..53, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 55..58, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 60..66, node_index: NodeIndex(None), parameter: Parameter { range: 60..66, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 60..61, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 63..66, id: Name("str"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 67..73, node_index: NodeIndex(None), parameter: Parameter { range: 67..68, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 67..68, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..73, value: Int( 10, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), ], }, ) ``` ## Errors | 1 | def foo(a: int, b: 2 | def foo(): | ^^^ Syntax Error: Expected an expression 3 | return 42 4 | def foo(a: int, b: str | | 1 | def foo(a: int, b: | ^ Syntax Error: Expected `)`, found newline 2 | def foo(): 3 | return 42 4 | def foo(a: int, b: str | | 1 | def foo(a: int, b: 2 | def foo(): | ^^^ Syntax Error: Expected an indented block after function definition 3 | return 42 4 | def foo(a: int, b: str | | 3 | return 42 4 | def foo(a: int, b: str 5 | x = 10 | ^ Syntax Error: Expected `,`, found name | 4 | def foo(a: int, b: str 5 | x = 10 | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@function_def_unclosed_type_param_list.py.snap000064400000000000000000000156471046102023000360700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_unclosed_type_param_list.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..39, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 7..15, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 8..10, name: Identifier { id: Name("T1"), range: 8..10, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 12..15, name: Identifier { id: Name("T2"), range: 13..15, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 15..21, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 16..17, node_index: NodeIndex(None), parameter: Parameter { range: 16..17, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 16..17, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 19..20, node_index: NodeIndex(None), parameter: Parameter { range: 19..20, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 19..20, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 27..39, value: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 34..39, left: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("b"), ctx: Load, }, ), }, ), ), }, ), ], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 40..46, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..46, value: Int( 10, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | def foo[T1, *T2(a, b): | ^ Syntax Error: Expected `]`, found `(` 2 | return a + b 3 | x = 10 | invalid_syntax@function_def_unparenthesized_return_types.py.snap000064400000000000000000000130521046102023000370170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_def_unparenthesized_return_types.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..50, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..22, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 13..17, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 13..16, id: Name("int"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..49, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 27..30, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 30..32, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 36..44, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 36..39, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 41..44, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 46..49, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 46..49, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo() -> int,: ... | ^^^^ Syntax Error: Multiple return types must be parenthesized 2 | def foo() -> int, str: ... | | 1 | def foo() -> int,: ... 2 | def foo() -> int, str: ... | ^^^^^^^^ Syntax Error: Multiple return types must be parenthesized invalid_syntax@function_type_params_py311.py.snap000064400000000000000000000116471046102023000334370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/function_type_params_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..79, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..61, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 51..54, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 52..53, name: Identifier { id: Name("T"), range: 52..53, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 54..56, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 62..78, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 66..69, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 69..71, node_index: NodeIndex(None), type_params: [], }, ), parameters: Parameters { range: 71..73, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 75..78, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 75..78, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | def foo[T](): ... 3 | def foo[](): ... | ^ Syntax Error: Type parameter list cannot be empty ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | def foo[T](): ... | ^^^ Syntax Error: Cannot use type parameter lists on Python 3.11 (syntax was added in Python 3.12) 3 | def foo[](): ... | | 1 | # parse_options: {"target-version": "3.11"} 2 | def foo[T](): ... 3 | def foo[](): ... | ^^ Syntax Error: Cannot use type parameter lists on Python 3.11 (syntax was added in Python 3.12) invalid_syntax@global_stmt_empty.py.snap000064400000000000000000000010671046102023000317710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/global_stmt_empty.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..7, body: [ Global( StmtGlobal { node_index: NodeIndex(None), range: 0..6, names: [], }, ), ], }, ) ``` ## Errors | 1 | global | ^ Syntax Error: Global statement must have at least one name invalid_syntax@global_stmt_expression.py.snap000064400000000000000000000032001046102023000330210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/global_stmt_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..13, body: [ Global( StmtGlobal { node_index: NodeIndex(None), range: 0..8, names: [ Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..12, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 9..12, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | global x + 1 | ^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@global_stmt_trailing_comma.py.snap000064400000000000000000000037131046102023000336200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/global_stmt_trailing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..32, body: [ Global( StmtGlobal { node_index: NodeIndex(None), range: 0..8, names: [], }, ), Global( StmtGlobal { node_index: NodeIndex(None), range: 9..18, names: [ Identifier { id: Name("x"), range: 16..17, node_index: NodeIndex(None), }, ], }, ), Global( StmtGlobal { node_index: NodeIndex(None), range: 19..31, names: [ Identifier { id: Name("x"), range: 26..27, node_index: NodeIndex(None), }, Identifier { id: Name("y"), range: 29..30, node_index: NodeIndex(None), }, ], }, ), ], }, ) ``` ## Errors | 1 | global , | ^ Syntax Error: Expected an identifier 2 | global x, 3 | global x, y, | | 1 | global , | ^ Syntax Error: Global statement must have at least one name 2 | global x, 3 | global x, y, | | 1 | global , 2 | global x, | ^ Syntax Error: Trailing comma not allowed 3 | global x, y, | | 1 | global , 2 | global x, 3 | global x, y, | ^ Syntax Error: Trailing comma not allowed invalid_syntax@if_stmt_elif_missing_colon.py.snap000064400000000000000000000053201046102023000336270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_elif_missing_colon.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..45, test: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 10..14, }, ), ], elif_else_clauses: [ ElifElseClause { range: 15..30, node_index: NodeIndex(None), test: Some( Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("y"), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 26..30, }, ), ], }, ElifElseClause { range: 31..45, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 41..45, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | if x: 2 | pass 3 | elif y | ^ Syntax Error: Expected `:`, found newline 4 | pass 5 | else: 6 | pass | invalid_syntax@if_stmt_empty_body.py.snap000064400000000000000000000041241046102023000321410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_empty_body.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..15, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..8, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..14, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 9..14, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | if True: 2 | 1 + 1 | ^ Syntax Error: Expected an indented block after `if` statement invalid_syntax@if_stmt_invalid_elif_test_expr.py.snap000064400000000000000000000101771046102023000345150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_invalid_elif_test_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..56, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..55, test: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 10..14, }, ), ], elif_else_clauses: [ ElifElseClause { range: 15..32, node_index: NodeIndex(None), test: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 20..22, value: Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 28..32, }, ), ], }, ElifElseClause { range: 33..55, node_index: NodeIndex(None), test: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 38..45, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Load, }, ), ), }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 51..55, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | if x: 2 | pass 3 | elif *x: | ^^ Syntax Error: Starred expression cannot be used here 4 | pass 5 | elif yield x: | | 3 | elif *x: 4 | pass 5 | elif yield x: | ^^^^^^^ Syntax Error: Yield expression cannot be used here 6 | pass | invalid_syntax@if_stmt_invalid_test_expr.py.snap000064400000000000000000000115741046102023000335200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_invalid_test_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..48, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..10, test: Starred( ExprStarred { node_index: NodeIndex(None), range: 3..5, value: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 7..10, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 7..10, }, ), }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 11..26, test: Yield( ExprYield { node_index: NodeIndex(None), range: 14..21, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("x"), ctx: Load, }, ), ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..26, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 23..26, }, ), }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 27..47, test: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 30..42, value: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..47, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 44..47, }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if *x: ... | ^^ Syntax Error: Starred expression cannot be used here 2 | if yield x: ... 3 | if yield from x: ... | | 1 | if *x: ... 2 | if yield x: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | if yield from x: ... | | 1 | if *x: ... 2 | if yield x: ... 3 | if yield from x: ... | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@if_stmt_missing_colon.py.snap000064400000000000000000000053761046102023000326430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_missing_colon.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..25, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..4, test: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("x"), ctx: Load, }, ), body: [], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 5..18, test: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("x"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 14..18, }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 19..24, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("a"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | if x | ^ Syntax Error: Expected `:`, found newline 2 | if x 3 | pass 4 | a = 1 | | 1 | if x 2 | if x | ^^ Syntax Error: Expected an indented block after `if` statement 3 | pass 4 | a = 1 | | 1 | if x 2 | if x | ^ Syntax Error: Expected `:`, found newline 3 | pass 4 | a = 1 | invalid_syntax@if_stmt_missing_test.py.snap000064400000000000000000000026441046102023000325030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_missing_test.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..9, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..8, test: Name( ExprName { node_index: NodeIndex(None), range: 2..2, id: Name(""), ctx: Invalid, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5..8, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5..8, }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if : ... | ^ Syntax Error: Expected an expression invalid_syntax@if_stmt_misspelled_elif.py.snap000064400000000000000000000054541046102023000331350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/if_stmt_misspelled_elif.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..17, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 13..17, }, ), ], elif_else_clauses: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 18..22, target: Name( ExprName { node_index: NodeIndex(None), range: 18..21, id: Name("elf"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 22..22, id: Name(""), ctx: Invalid, }, ), value: None, simple: true, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 27..31, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 42..46, }, ), ], }, ) ``` ## Errors | 1 | if True: 2 | pass 3 | elf: | ^ Syntax Error: Expected an expression 4 | pass 5 | else: 6 | pass | | 2 | pass 3 | elf: 4 | pass | ^^^^ Syntax Error: Unexpected indentation 5 | else: 6 | pass | | 3 | elf: 4 | pass 5 | else: | ^^^^ Syntax Error: Expected a statement 6 | pass | | 3 | elf: 4 | pass 5 | else: | ^ Syntax Error: Expected a statement 6 | pass | | 3 | elf: 4 | pass 5 | else: | ^ Syntax Error: Expected a statement 6 | pass | | 4 | pass 5 | else: 6 | pass | ^^^^ Syntax Error: Unexpected indentation invalid_syntax@implicitly_concatenated_unterminated_string.py.snap000064400000000000000000000223331046102023000372770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..14, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..14, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 0..7, node_index: NodeIndex(None), value: "hello", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 8..14, node_index: NodeIndex(None), value: "world", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: true, }, }, ], value: "helloworld", }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..20, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 15..20, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 15..16, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..40, value: FString( ExprFString { node_index: NodeIndex(None), range: 21..40, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 21..28, node_index: NodeIndex(None), value: "hello", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 29..40, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 31..37, node_index: NodeIndex(None), value: "world ", }, ), Interpolation( InterpolatedElement { range: 37..40, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 41..46, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 41..46, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..42, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | 'hello' 'world | ^^^^^^ Syntax Error: missing closing quote in string literal 2 | 1 + 1 3 | 'hello' f'world {x} | | 1 | 'hello' 'world 2 | 1 + 1 3 | 'hello' f'world {x} | ^ Syntax Error: f-string: unterminated string 4 | 2 + 2 | invalid_syntax@implicitly_concatenated_unterminated_string_multiline.py.snap000064400000000000000000000254771046102023000413750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string_multiline.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..31, value: FString( ExprFString { node_index: NodeIndex(None), range: 6..31, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 6..13, node_index: NodeIndex(None), value: "hello", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 18..31, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 20..26, node_index: NodeIndex(None), value: "world ", }, ), Interpolation( InterpolatedElement { range: 26..29, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..37, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 32..37, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..37, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 38..78, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..76, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 44..51, node_index: NodeIndex(None), value: "first", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 56..63, node_index: NodeIndex(None), value: "second", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: true, }, }, ), FString( FString { range: 68..76, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 70..75, node_index: NodeIndex(None), value: "third", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 79..84, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 79..84, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 2, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | ( 2 | 'hello' 3 | f'world {x} | ^ Syntax Error: f-string: unterminated string 4 | ) 5 | 1 + 1 | | 2 | 'hello' 3 | f'world {x} 4 | ) | ^ Syntax Error: Expected an element of or the end of the f-string 5 | 1 + 1 6 | ( | | 2 | 'hello' 3 | f'world {x} 4 | ) | ^ Syntax Error: Expected FStringEnd, found newline 5 | 1 + 1 6 | ( 7 | 'first' | | 6 | ( 7 | 'first' 8 | 'second | ^^^^^^^ Syntax Error: missing closing quote in string literal 9 | f'third' 10 | ) | invalid_syntax@import_alias_missing_asname.py.snap000064400000000000000000000020431046102023000337770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_alias_missing_asname.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..12, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..11, names: [ Alias { range: 7..11, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | import x as | ^ Syntax Error: Expected symbol after `as` invalid_syntax@import_from_star.py.snap000064400000000000000000000243221046102023000316310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_from_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..34, is_async: false, decorator_list: [], name: Identifier { id: Name("f1"), range: 4..6, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 6..8, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 14..34, module: Some( Identifier { id: Name("module"), range: 19..25, node_index: NodeIndex(None), }, ), names: [ Alias { range: 33..34, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 33..34, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 35..68, decorator_list: [], name: Identifier { id: Name("C"), range: 41..42, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 48..68, module: Some( Identifier { id: Name("module"), range: 53..59, node_index: NodeIndex(None), }, ), names: [ Alias { range: 67..68, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 67..68, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 69..105, is_async: false, decorator_list: [], name: Identifier { id: Name("f2"), range: 73..75, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 75..77, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 83..105, module: Some( Identifier { id: Name("module"), range: 90..96, node_index: NodeIndex(None), }, ), names: [ Alias { range: 104..105, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 104..105, node_index: NodeIndex(None), }, asname: None, }, ], level: 2, is_lazy: false, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 106..143, is_async: false, decorator_list: [], name: Identifier { id: Name("f3"), range: 110..112, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 112..114, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 120..143, module: Some( Identifier { id: Name("module"), range: 125..131, node_index: NodeIndex(None), }, ), names: [ Alias { range: 139..140, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 139..140, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 142..143, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 142..143, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ), ], }, ) ``` ## Errors | 6 | from ..module import * 7 | def f3(): 8 | from module import *, * | ^^^^ Syntax Error: Star import must be the only import ## Semantic Syntax Errors | 1 | def f1(): 2 | from module import * | ^^^^^^^^^^^^^^^^^^^^ Syntax Error: `from module import *` only allowed at module level 3 | class C: 4 | from module import * | | 2 | from module import * 3 | class C: 4 | from module import * | ^^^^^^^^^^^^^^^^^^^^ Syntax Error: `from module import *` only allowed at module level 5 | def f2(): 6 | from ..module import * | | 4 | from module import * 5 | def f2(): 6 | from ..module import * | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: `from ..module import *` only allowed at module level 7 | def f3(): 8 | from module import *, * | | 6 | from ..module import * 7 | def f3(): 8 | from module import *, * | ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: `from module import *` only allowed at module level invalid_syntax@import_stmt_empty.py.snap000064400000000000000000000011351046102023000320370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_stmt_empty.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..7, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..6, names: [], is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | import | ^ Syntax Error: Expected one or more symbol names after import invalid_syntax@import_stmt_parenthesized_names.py.snap000064400000000000000000000053221046102023000347330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_stmt_parenthesized_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..25, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..6, names: [], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..10, value: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("a"), ctx: Load, }, ), }, ), Import( StmtImport { node_index: NodeIndex(None), range: 11..17, names: [], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..24, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 18..24, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Errors | 1 | import (a) | ^ Syntax Error: Expected one or more symbol names after import 2 | import (a, b) | | 1 | import (a) 2 | import (a, b) | ^ Syntax Error: Expected one or more symbol names after import invalid_syntax@import_stmt_star_import.py.snap000064400000000000000000000102321046102023000332420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_stmt_star_import.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..6, names: [], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..8, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 7..8, value: Name( ExprName { node_index: NodeIndex(None), range: 8..8, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), }, ), Import( StmtImport { node_index: NodeIndex(None), range: 9..18, names: [ Alias { range: 16..17, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 16..17, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..23, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 19..23, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 19..20, value: Name( ExprName { node_index: NodeIndex(None), range: 20..20, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` ## Errors | 1 | import * | ^ Syntax Error: Expected one or more symbol names after import 2 | import x, *, y | | 1 | import * | ^ Syntax Error: Expected an expression 2 | import x, *, y | | 1 | import * 2 | import x, *, y | ^ Syntax Error: Trailing comma not allowed | 1 | import * 2 | import x, *, y | ^ Syntax Error: Simple statements must be separated by newlines or semicolons | 1 | import * 2 | import x, *, y | ^ Syntax Error: Expected an expression invalid_syntax@import_stmt_trailing_comma.py.snap000064400000000000000000000036331046102023000336730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/import_stmt_trailing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..22, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..8, names: [], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 9..21, names: [ Alias { range: 16..17, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 16..17, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 19..20, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 19..20, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), ], }, ) ``` ## Errors | 1 | import , | ^ Syntax Error: Expected an import name 2 | import x, y, | | 1 | import , | ^ Syntax Error: Expected one or more symbol names after import 2 | import x, y, | | 1 | import , 2 | import x, y, | ^ Syntax Error: Trailing comma not allowed invalid_syntax@incomplete_attribute_before_for_in_delimiter.py.snap000064400000000000000000000405401046102023000374010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/incomplete_attribute_before_for_in_delimiter.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..142, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 0..22, elt: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1..6, value: Name( ExprName { node_index: NodeIndex(None), range: 1..5, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 6..6, node_index: NodeIndex(None), }, ctx: Load, }, ), generators: [ Comprehension { range: 7..21, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 11..15, id: Name("item"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 19..21, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..51, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 23..51, elt: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 24..29, value: Name( ExprName { node_index: NodeIndex(None), range: 24..28, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 29..29, node_index: NodeIndex(None), }, ctx: Load, }, ), generators: [ Comprehension { range: 30..50, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 40..44, id: Name("item"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 48..50, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 52..74, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 52..74, elt: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 53..58, value: Name( ExprName { node_index: NodeIndex(None), range: 53..57, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 58..58, node_index: NodeIndex(None), }, ctx: Load, }, ), generators: [ Comprehension { range: 59..73, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 63..67, id: Name("item"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 71..73, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 75..97, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 75..97, elt: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 76..81, value: Name( ExprName { node_index: NodeIndex(None), range: 76..80, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 81..81, node_index: NodeIndex(None), }, ctx: Load, }, ), generators: [ Comprehension { range: 82..96, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 86..90, id: Name("item"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 94..96, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 98..120, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 98..120, elt: Name( ExprName { node_index: NodeIndex(None), range: 99..103, id: Name("item"), ctx: Load, }, ), generators: [ Comprehension { range: 104..119, node_index: NodeIndex(None), target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 108..113, value: Name( ExprName { node_index: NodeIndex(None), range: 108..112, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 113..113, node_index: NodeIndex(None), }, ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 117..119, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), For( StmtFor { node_index: NodeIndex(None), range: 121..141, is_async: false, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 125..130, value: Name( ExprName { node_index: NodeIndex(None), range: 125..129, id: Name("item"), ctx: Load, }, ), attr: Identifier { id: Name(""), range: 130..130, node_index: NodeIndex(None), }, ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 134..136, id: Name("xs"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 138..141, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 138..141, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | [item. for item in xs] | ^^^ Syntax Error: Expected an identifier 2 | [item. async for item in xs] 3 | {item. for item in xs} | | 1 | [item. for item in xs] 2 | [item. async for item in xs] | ^^^^^ Syntax Error: Expected an identifier 3 | {item. for item in xs} 4 | (item. for item in xs) | | 1 | [item. for item in xs] 2 | [item. async for item in xs] 3 | {item. for item in xs} | ^^^ Syntax Error: Expected an identifier 4 | (item. for item in xs) 5 | [item for item. in xs] | | 2 | [item. async for item in xs] 3 | {item. for item in xs} 4 | (item. for item in xs) | ^^^ Syntax Error: Expected an identifier 5 | [item for item. in xs] 6 | for item. in xs: ... | | 3 | {item. for item in xs} 4 | (item. for item in xs) 5 | [item for item. in xs] | ^^ Syntax Error: Expected an identifier 6 | for item. in xs: ... | | 4 | (item. for item in xs) 5 | [item for item. in xs] 6 | for item. in xs: ... | ^^ Syntax Error: Expected an identifier invalid_syntax@invalid_annotation_class.py.snap000064400000000000000000000612761046102023000333210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..247, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..26, decorator_list: [], name: Identifier { id: Name("F"), range: 6..7, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 7..10, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 8..9, name: Identifier { id: Name("T"), range: 8..9, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 10..21, node_index: NodeIndex(None), args: [ Named( ExprNamed { node_index: NodeIndex(None), range: 11..20, target: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("y"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 16..20, id: Name("list"), ctx: Load, }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..26, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 23..26, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 27..53, decorator_list: [], name: Identifier { id: Name("I"), range: 33..34, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 34..37, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 35..36, name: Identifier { id: Name("T"), range: 35..36, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 37..48, node_index: NodeIndex(None), args: [ Yield( ExprYield { node_index: NodeIndex(None), range: 39..46, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 1, ), }, ), ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 50..53, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 54..85, decorator_list: [], name: Identifier { id: Name("J"), range: 60..61, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 61..64, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 62..63, name: Identifier { id: Name("T"), range: 62..63, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 64..80, node_index: NodeIndex(None), args: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 66..78, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 77..78, value: Int( 1, ), }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 82..85, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 82..85, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 86..112, decorator_list: [], name: Identifier { id: Name("K"), range: 92..93, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 93..107, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 94..106, name: Identifier { id: Name("T"), range: 94..95, node_index: NodeIndex(None), }, bound: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 98..105, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..105, value: Int( 1, ), }, ), ), }, ), ), default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 109..112, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 137..162, decorator_list: [], name: Identifier { id: Name("L"), range: 143..144, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 144..157, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 145..156, name: Identifier { id: Name("T"), range: 145..146, node_index: NodeIndex(None), }, bound: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 149..155, target: Name( ExprName { node_index: NodeIndex(None), range: 149..150, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 154..155, value: Int( 1, ), }, ), }, ), ), default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 159..162, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 159..162, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 193..219, decorator_list: [], name: Identifier { id: Name("M"), range: 199..200, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 200..203, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 201..202, name: Identifier { id: Name("T"), range: 201..202, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 203..214, node_index: NodeIndex(None), args: [ Await( ExprAwait { node_index: NodeIndex(None), range: 205..212, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 211..212, value: Int( 1, ), }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 216..219, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 216..219, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 220..246, decorator_list: [], name: Identifier { id: Name("N"), range: 226..227, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 227..241, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 228..240, name: Identifier { id: Name("T"), range: 228..229, node_index: NodeIndex(None), }, bound: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 232..239, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 238..239, value: Int( 1, ), }, ), }, ), ), default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 243..246, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 243..246, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | class F[T](y := list): ... | ^^^^^^^^^ Syntax Error: named expression cannot be used within a generic definition 2 | class I[T]((yield 1)): ... 3 | class J[T]((yield from 1)): ... | | 1 | class F[T](y := list): ... 2 | class I[T]((yield 1)): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition 3 | class J[T]((yield from 1)): ... 4 | class K[T: (yield 1)]: ... # yield in TypeVar | | 1 | class F[T](y := list): ... 2 | class I[T]((yield 1)): ... 3 | class J[T]((yield from 1)): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition 4 | class K[T: (yield 1)]: ... # yield in TypeVar 5 | class L[T: (x := 1)]: ... # named expr in TypeVar | | 2 | class I[T]((yield 1)): ... 3 | class J[T]((yield from 1)): ... 4 | class K[T: (yield 1)]: ... # yield in TypeVar | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound 5 | class L[T: (x := 1)]: ... # named expr in TypeVar 6 | class M[T]((await 1)): ... | | 3 | class J[T]((yield from 1)): ... 4 | class K[T: (yield 1)]: ... # yield in TypeVar 5 | class L[T: (x := 1)]: ... # named expr in TypeVar | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound 6 | class M[T]((await 1)): ... 7 | class N[T: (await 1)]: ... | | 4 | class K[T: (yield 1)]: ... # yield in TypeVar 5 | class L[T: (x := 1)]: ... # named expr in TypeVar 6 | class M[T]((await 1)): ... | ^^^^^^^ Syntax Error: await expression cannot be used within a generic definition 7 | class N[T: (await 1)]: ... | | 5 | class L[T: (x := 1)]: ... # named expr in TypeVar 6 | class M[T]((await 1)): ... 7 | class N[T: (await 1)]: ... | ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar bound invalid_syntax@invalid_annotation_function.py.snap000064400000000000000000002407641046102023000340420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..987, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..28, is_async: false, decorator_list: [], name: Identifier { id: Name("d"), range: 4..5, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 5..8, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 6..7, name: Identifier { id: Name("T"), range: 6..7, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 8..10, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 15..22, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 29..58, is_async: false, decorator_list: [], name: Identifier { id: Name("e"), range: 33..34, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 34..37, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 35..36, name: Identifier { id: Name("T"), range: 35..36, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 37..53, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 38..52, node_index: NodeIndex(None), parameter: Parameter { range: 38..52, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 38..41, node_index: NodeIndex(None), }, annotation: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 44..51, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 50..51, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 55..58, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 55..58, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 59..86, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 63..64, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 64..67, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 65..66, name: Identifier { id: Name("T"), range: 65..66, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 67..69, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 74..80, target: Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 3, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..86, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 83..86, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 87..115, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 91..92, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 92..95, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 93..94, name: Identifier { id: Name("T"), range: 93..94, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 95..110, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 96..109, node_index: NodeIndex(None), parameter: Parameter { range: 96..109, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 96..99, node_index: NodeIndex(None), }, annotation: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 102..108, target: Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 107..108, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 112..115, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 112..115, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 116..143, is_async: false, decorator_list: [], name: Identifier { id: Name("h"), range: 120..121, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 121..124, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 122..123, name: Identifier { id: Name("T"), range: 122..123, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 124..138, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 125..137, node_index: NodeIndex(None), parameter: Parameter { range: 125..137, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 125..126, node_index: NodeIndex(None), }, annotation: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 129..136, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 1, ), }, ), ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 140..143, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 140..143, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 144..172, is_async: false, decorator_list: [], name: Identifier { id: Name("j"), range: 148..149, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 149..152, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 150..151, name: Identifier { id: Name("T"), range: 150..151, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 152..154, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 159..166, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 165..166, value: Int( 1, ), }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 169..172, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 169..172, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 173..205, is_async: false, decorator_list: [], name: Identifier { id: Name("l"), range: 177..178, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 178..181, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 179..180, name: Identifier { id: Name("T"), range: 179..180, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 181..200, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 182..199, node_index: NodeIndex(None), parameter: Parameter { range: 182..199, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 182..183, node_index: NodeIndex(None), }, annotation: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 186..198, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..198, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 202..205, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 202..205, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 206..239, is_async: false, decorator_list: [], name: Identifier { id: Name("n"), range: 210..211, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 211..214, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 212..213, name: Identifier { id: Name("T"), range: 212..213, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 214..216, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 221..233, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 232..233, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 236..239, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 236..239, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 240..266, is_async: false, decorator_list: [], name: Identifier { id: Name("p"), range: 244..245, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 245..259, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 246..258, name: Identifier { id: Name("T"), range: 246..247, node_index: NodeIndex(None), }, bound: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 250..257, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 256..257, value: Int( 1, ), }, ), ), }, ), ), default: None, }, ), ], }, ), parameters: Parameters { range: 259..261, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 263..266, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 263..266, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 297..324, is_async: false, decorator_list: [], name: Identifier { id: Name("q"), range: 301..302, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 302..317, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 303..316, name: Identifier { id: Name("T"), range: 303..304, node_index: NodeIndex(None), }, bound: None, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 308..315, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 314..315, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 317..319, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 321..324, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 321..324, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 356..385, is_async: false, decorator_list: [], name: Identifier { id: Name("r"), range: 360..361, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 361..378, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 362..377, name: Identifier { id: Name("Ts"), range: 363..365, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 369..376, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 375..376, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 378..380, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 382..385, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 382..385, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 420..450, is_async: false, decorator_list: [], name: Identifier { id: Name("s"), range: 424..425, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 425..443, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 426..442, name: Identifier { id: Name("Ts"), range: 428..430, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 434..441, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 440..441, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 443..445, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 447..450, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 447..450, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 481..506, is_async: false, decorator_list: [], name: Identifier { id: Name("t"), range: 485..486, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 486..499, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 487..498, name: Identifier { id: Name("T"), range: 487..488, node_index: NodeIndex(None), }, bound: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 491..497, target: Name( ExprName { node_index: NodeIndex(None), range: 491..492, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 496..497, value: Int( 1, ), }, ), }, ), ), default: None, }, ), ], }, ), parameters: Parameters { range: 499..501, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 503..506, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 503..506, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 543..569, is_async: false, decorator_list: [], name: Identifier { id: Name("u"), range: 547..548, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 548..562, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 549..561, name: Identifier { id: Name("T"), range: 549..550, node_index: NodeIndex(None), }, bound: None, default: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 554..560, target: Name( ExprName { node_index: NodeIndex(None), range: 554..555, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 559..560, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 562..564, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 566..569, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 566..569, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 607..635, is_async: false, decorator_list: [], name: Identifier { id: Name("v"), range: 611..612, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 612..628, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 613..627, name: Identifier { id: Name("Ts"), range: 614..616, node_index: NodeIndex(None), }, default: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 620..626, target: Name( ExprName { node_index: NodeIndex(None), range: 620..621, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 625..626, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 628..630, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 632..635, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 632..635, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 676..705, is_async: false, decorator_list: [], name: Identifier { id: Name("w"), range: 680..681, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 681..698, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 682..697, name: Identifier { id: Name("Ts"), range: 684..686, node_index: NodeIndex(None), }, default: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 690..696, target: Name( ExprName { node_index: NodeIndex(None), range: 690..691, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 695..696, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 698..700, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 702..705, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 702..705, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 742..768, is_async: false, decorator_list: [], name: Identifier { id: Name("t"), range: 746..747, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 747..761, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 748..760, name: Identifier { id: Name("T"), range: 748..749, node_index: NodeIndex(None), }, bound: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 752..759, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 758..759, value: Int( 1, ), }, ), }, ), ), default: None, }, ), ], }, ), parameters: Parameters { range: 761..763, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 765..768, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 765..768, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 800..827, is_async: false, decorator_list: [], name: Identifier { id: Name("u"), range: 804..805, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 805..820, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 806..819, name: Identifier { id: Name("T"), range: 806..807, node_index: NodeIndex(None), }, bound: None, default: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 811..818, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 817..818, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 820..822, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 824..827, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 824..827, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 860..889, is_async: false, decorator_list: [], name: Identifier { id: Name("v"), range: 864..865, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 865..882, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 866..881, name: Identifier { id: Name("Ts"), range: 867..869, node_index: NodeIndex(None), }, default: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 873..880, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 879..880, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 882..884, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 886..889, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 886..889, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 925..955, is_async: false, decorator_list: [], name: Identifier { id: Name("w"), range: 929..930, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 930..948, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 931..947, name: Identifier { id: Name("Ts"), range: 933..935, node_index: NodeIndex(None), }, default: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 939..946, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 945..946, value: Int( 1, ), }, ), }, ), ), }, ), ], }, ), parameters: Parameters { range: 948..950, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 952..955, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 952..955, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | def d[T]() -> (await 1): ... | ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation 2 | def e[T](arg: (await 1)): ... 3 | def f[T]() -> (y := 3): ... | | 1 | def d[T]() -> (await 1): ... 2 | def e[T](arg: (await 1)): ... | ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation 3 | def f[T]() -> (y := 3): ... 4 | def g[T](arg: (x := 1)): ... | | 1 | def d[T]() -> (await 1): ... 2 | def e[T](arg: (await 1)): ... 3 | def f[T]() -> (y := 3): ... | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation 4 | def g[T](arg: (x := 1)): ... 5 | def h[T](x: (yield 1)): ... | | 2 | def e[T](arg: (await 1)): ... 3 | def f[T]() -> (y := 3): ... 4 | def g[T](arg: (x := 1)): ... | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation 5 | def h[T](x: (yield 1)): ... 6 | def j[T]() -> (yield 1): ... | | 3 | def f[T]() -> (y := 3): ... 4 | def g[T](arg: (x := 1)): ... 5 | def h[T](x: (yield 1)): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 6 | def j[T]() -> (yield 1): ... 7 | def l[T](x: (yield from 1)): ... | | 4 | def g[T](arg: (x := 1)): ... 5 | def h[T](x: (yield 1)): ... 6 | def j[T]() -> (yield 1): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 7 | def l[T](x: (yield from 1)): ... 8 | def n[T]() -> (yield from 1): ... | | 5 | def h[T](x: (yield 1)): ... 6 | def j[T]() -> (yield 1): ... 7 | def l[T](x: (yield from 1)): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 8 | def n[T]() -> (yield from 1): ... 9 | def p[T: (yield 1)](): ... # yield in TypeVar bound | | 6 | def j[T]() -> (yield 1): ... 7 | def l[T](x: (yield from 1)): ... 8 | def n[T]() -> (yield from 1): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 9 | def p[T: (yield 1)](): ... # yield in TypeVar bound 10 | def q[T = (yield 1)](): ... # yield in TypeVar default | | 7 | def l[T](x: (yield from 1)): ... 8 | def n[T]() -> (yield from 1): ... 9 | def p[T: (yield 1)](): ... # yield in TypeVar bound | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound 10 | def q[T = (yield 1)](): ... # yield in TypeVar default 11 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default | | 8 | def n[T]() -> (yield from 1): ... 9 | def p[T: (yield 1)](): ... # yield in TypeVar bound 10 | def q[T = (yield 1)](): ... # yield in TypeVar default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default 11 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default 12 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default | | 9 | def p[T: (yield 1)](): ... # yield in TypeVar bound 10 | def q[T = (yield 1)](): ... # yield in TypeVar default 11 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVarTuple default 12 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default 13 | def t[T: (x := 1)](): ... # named expr in TypeVar bound | | 10 | def q[T = (yield 1)](): ... # yield in TypeVar default 11 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default 12 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default | ^^^^^^^ Syntax Error: yield expression cannot be used within a ParamSpec default 13 | def t[T: (x := 1)](): ... # named expr in TypeVar bound 14 | def u[T = (x := 1)](): ... # named expr in TypeVar default | | 11 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default 12 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default 13 | def t[T: (x := 1)](): ... # named expr in TypeVar bound | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound 14 | def u[T = (x := 1)](): ... # named expr in TypeVar default 15 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default | | 12 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default 13 | def t[T: (x := 1)](): ... # named expr in TypeVar bound 14 | def u[T = (x := 1)](): ... # named expr in TypeVar default | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar default 15 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default 16 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default | | 13 | def t[T: (x := 1)](): ... # named expr in TypeVar bound 14 | def u[T = (x := 1)](): ... # named expr in TypeVar default 15 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVarTuple default 16 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default 17 | def t[T: (await 1)](): ... # await in TypeVar bound | | 14 | def u[T = (x := 1)](): ... # named expr in TypeVar default 15 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default 16 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default | ^^^^^^ Syntax Error: named expression cannot be used within a ParamSpec default 17 | def t[T: (await 1)](): ... # await in TypeVar bound 18 | def u[T = (await 1)](): ... # await in TypeVar default | | 15 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default 16 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default 17 | def t[T: (await 1)](): ... # await in TypeVar bound | ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar bound 18 | def u[T = (await 1)](): ... # await in TypeVar default 19 | def v[*Ts = (await 1)](): ... # await in TypeVarTuple default | | 16 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default 17 | def t[T: (await 1)](): ... # await in TypeVar bound 18 | def u[T = (await 1)](): ... # await in TypeVar default | ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar default 19 | def v[*Ts = (await 1)](): ... # await in TypeVarTuple default 20 | def w[**Ts = (await 1)](): ... # await in ParamSpec default | | 17 | def t[T: (await 1)](): ... # await in TypeVar bound 18 | def u[T = (await 1)](): ... # await in TypeVar default 19 | def v[*Ts = (await 1)](): ... # await in TypeVarTuple default | ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVarTuple default 20 | def w[**Ts = (await 1)](): ... # await in ParamSpec default | | 18 | def u[T = (await 1)](): ... # await in TypeVar default 19 | def v[*Ts = (await 1)](): ... # await in TypeVarTuple default 20 | def w[**Ts = (await 1)](): ... # await in ParamSpec default | ^^^^^^^ Syntax Error: await expression cannot be used within a ParamSpec default invalid_syntax@invalid_annotation_function_py314.py.snap000064400000000000000000000756521046102023000350040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..316, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..68, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 48..49, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 49..51, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 56..62, target: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 3, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 65..68, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 65..68, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 69..94, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 73..74, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 74..89, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 75..88, node_index: NodeIndex(None), parameter: Parameter { range: 75..88, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 75..78, node_index: NodeIndex(None), }, annotation: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 81..87, target: Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..87, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 91..94, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 91..94, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 95..235, is_async: false, decorator_list: [], name: Identifier { id: Name("outer"), range: 99..104, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 104..106, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 112..136, is_async: false, decorator_list: [], name: Identifier { id: Name("i"), range: 116..117, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 117..131, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 118..130, node_index: NodeIndex(None), parameter: Parameter { range: 118..130, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 118..119, node_index: NodeIndex(None), }, annotation: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 122..129, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 1, ), }, ), ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 133..136, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 133..136, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 141..166, is_async: false, decorator_list: [], name: Identifier { id: Name("k"), range: 145..146, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 146..148, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 153..160, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 159..160, value: Int( 1, ), }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 163..166, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 163..166, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 171..200, is_async: false, decorator_list: [], name: Identifier { id: Name("m"), range: 175..176, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 176..195, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 177..194, node_index: NodeIndex(None), parameter: Parameter { range: 177..194, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 177..178, node_index: NodeIndex(None), }, annotation: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 181..193, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 192..193, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 197..200, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 197..200, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 205..235, is_async: false, decorator_list: [], name: Identifier { id: Name("o"), range: 209..210, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 210..212, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 217..229, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 228..229, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 232..235, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 232..235, }, ), }, ), ], }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 236..315, is_async: true, decorator_list: [], name: Identifier { id: Name("outer"), range: 246..251, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 251..253, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 259..284, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 263..264, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 264..266, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 271..278, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 277..278, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 281..284, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 281..284, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 289..315, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 293..294, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 294..310, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 295..309, node_index: NodeIndex(None), parameter: Parameter { range: 295..309, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 295..298, node_index: NodeIndex(None), }, annotation: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 301..308, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 307..308, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 312..315, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 312..315, }, ), }, ), ], }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | def f() -> (y := 3): ... | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation 3 | def g(arg: (x := 1)): ... 4 | def outer(): | | 1 | # parse_options: {"target-version": "3.14"} 2 | def f() -> (y := 3): ... 3 | def g(arg: (x := 1)): ... | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation 4 | def outer(): 5 | def i(x: (yield 1)): ... | | 3 | def g(arg: (x := 1)): ... 4 | def outer(): 5 | def i(x: (yield 1)): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 6 | def k() -> (yield 1): ... 7 | def m(x: (yield from 1)): ... | | 4 | def outer(): 5 | def i(x: (yield 1)): ... 6 | def k() -> (yield 1): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 7 | def m(x: (yield from 1)): ... 8 | def o() -> (yield from 1): ... | | 5 | def i(x: (yield 1)): ... 6 | def k() -> (yield 1): ... 7 | def m(x: (yield from 1)): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 8 | def o() -> (yield from 1): ... 9 | async def outer(): | | 6 | def k() -> (yield 1): ... 7 | def m(x: (yield from 1)): ... 8 | def o() -> (yield from 1): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 9 | async def outer(): 10 | def f() -> (await 1): ... | | 8 | def o() -> (yield from 1): ... 9 | async def outer(): 10 | def f() -> (await 1): ... | ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation 11 | def g(arg: (await 1)): ... | | 9 | async def outer(): 10 | def f() -> (await 1): ... 11 | def g(arg: (await 1)): ... | ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation invalid_syntax@invalid_annotation_py314.py.snap000064400000000000000000000221241046102023000330610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 44..55, target: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("a"), ctx: Store, }, ), annotation: Named( ExprNamed { node_index: NodeIndex(None), range: 48..54, target: Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 56..107, is_async: false, decorator_list: [], name: Identifier { id: Name("outer"), range: 60..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 73..85, target: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("b"), ctx: Store, }, ), annotation: Yield( ExprYield { node_index: NodeIndex(None), range: 77..84, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 1, ), }, ), ), }, ), value: None, simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 90..107, target: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("c"), ctx: Store, }, ), annotation: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 94..106, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 108..143, is_async: true, decorator_list: [], name: Identifier { id: Name("outer"), range: 118..123, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 123..125, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 131..143, target: Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("d"), ctx: Store, }, ), annotation: Await( ExprAwait { node_index: NodeIndex(None), range: 135..142, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 141..142, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | a: (x := 1) | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation 3 | def outer(): 4 | b: (yield 1) | | 2 | a: (x := 1) 3 | def outer(): 4 | b: (yield 1) | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 5 | c: (yield from 1) 6 | async def outer(): | | 3 | def outer(): 4 | b: (yield 1) 5 | c: (yield from 1) | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 6 | async def outer(): 7 | d: (await 1) | | 5 | c: (yield from 1) 6 | async def outer(): 7 | d: (await 1) | ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation invalid_syntax@invalid_annotation_type_alias.py.snap000064400000000000000000000517531046102023000343450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_type_alias.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..406, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..26, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..20, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..19, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 11..18, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..18, value: Int( 1, ), }, ), ), }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 23..26, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 48..75, name: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 54..69, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 55..68, name: Identifier { id: Name("T"), range: 55..56, node_index: NodeIndex(None), }, bound: None, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 60..67, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 66..67, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 72..75, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 98..127, name: Name( ExprName { node_index: NodeIndex(None), range: 103..104, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 104..121, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 105..120, name: Identifier { id: Name("Ts"), range: 106..108, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 112..119, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 124..127, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 153..183, name: Name( ExprName { node_index: NodeIndex(None), range: 158..159, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 159..177, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 160..176, name: Identifier { id: Name("Ts"), range: 162..164, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 168..175, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 174..175, value: Int( 1, ), }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 180..183, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 205..223, name: Name( ExprName { node_index: NodeIndex(None), range: 210..211, id: Name("Y"), ctx: Store, }, ), type_params: None, value: Yield( ExprYield { node_index: NodeIndex(None), range: 215..222, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 221..222, value: Int( 1, ), }, ), ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 254..271, name: Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("Y"), ctx: Store, }, ), type_params: None, value: Named( ExprNamed { node_index: NodeIndex(None), range: 264..270, target: Name( ExprName { node_index: NodeIndex(None), range: 264..265, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 269..270, value: Int( 1, ), }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 308..334, name: Name( ExprName { node_index: NodeIndex(None), range: 313..314, id: Name("Y"), ctx: Store, }, ), type_params: Some( TypeParams { range: 314..328, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 315..327, name: Identifier { id: Name("T"), range: 315..316, node_index: NodeIndex(None), }, bound: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 319..326, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 325..326, value: Int( 1, ), }, ), }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 331..334, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 357..375, name: Name( ExprName { node_index: NodeIndex(None), range: 362..363, id: Name("Y"), ctx: Store, }, ), type_params: None, value: Await( ExprAwait { node_index: NodeIndex(None), range: 367..374, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 373..374, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | type X[T: (yield 1)] = int # TypeVar bound | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound 2 | type X[T = (yield 1)] = int # TypeVar default 3 | type X[*Ts = (yield 1)] = int # TypeVarTuple default | | 1 | type X[T: (yield 1)] = int # TypeVar bound 2 | type X[T = (yield 1)] = int # TypeVar default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default 3 | type X[*Ts = (yield 1)] = int # TypeVarTuple default 4 | type X[**Ts = (yield 1)] = int # ParamSpec default | | 1 | type X[T: (yield 1)] = int # TypeVar bound 2 | type X[T = (yield 1)] = int # TypeVar default 3 | type X[*Ts = (yield 1)] = int # TypeVarTuple default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVarTuple default 4 | type X[**Ts = (yield 1)] = int # ParamSpec default 5 | type Y = (yield 1) # yield in value | | 2 | type X[T = (yield 1)] = int # TypeVar default 3 | type X[*Ts = (yield 1)] = int # TypeVarTuple default 4 | type X[**Ts = (yield 1)] = int # ParamSpec default | ^^^^^^^ Syntax Error: yield expression cannot be used within a ParamSpec default 5 | type Y = (yield 1) # yield in value 6 | type Y = (x := 1) # named expr in value | | 3 | type X[*Ts = (yield 1)] = int # TypeVarTuple default 4 | type X[**Ts = (yield 1)] = int # ParamSpec default 5 | type Y = (yield 1) # yield in value | ^^^^^^^ Syntax Error: yield expression cannot be used within a type alias 6 | type Y = (x := 1) # named expr in value 7 | type Y[T: (await 1)] = int # await in bound | | 4 | type X[**Ts = (yield 1)] = int # ParamSpec default 5 | type Y = (yield 1) # yield in value 6 | type Y = (x := 1) # named expr in value | ^^^^^^ Syntax Error: named expression cannot be used within a type alias 7 | type Y[T: (await 1)] = int # await in bound 8 | type Y = (await 1) # await in value | | 5 | type Y = (yield 1) # yield in value 6 | type Y = (x := 1) # named expr in value 7 | type Y[T: (await 1)] = int # await in bound | ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar bound 8 | type Y = (await 1) # await in value | | 6 | type Y = (x := 1) # named expr in value 7 | type Y[T: (await 1)] = int # await in bound 8 | type Y = (await 1) # await in value | ^^^^^^^ Syntax Error: await expression cannot be used within a type alias invalid_syntax@invalid_byte_literal.py.snap000064400000000000000000000104461046102023000324320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_byte_literal.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..44, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 0..12, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 0..12, node_index: NodeIndex(None), value: [], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..26, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 13..26, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 13..26, node_index: NodeIndex(None), value: [], flags: BytesLiteralFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..43, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 27..43, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 27..43, node_index: NodeIndex(None), value: [], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | b'123a𝐁c' | ^ Syntax Error: bytes can only contain ASCII literal characters 2 | rb"a𝐁c123" 3 | b"""123a𝐁c""" | | 1 | b'123a𝐁c' 2 | rb"a𝐁c123" | ^ Syntax Error: bytes can only contain ASCII literal characters 3 | b"""123a𝐁c""" | | 1 | b'123a𝐁c' 2 | rb"a𝐁c123" 3 | b"""123a𝐁c""" | ^ Syntax Error: bytes can only contain ASCII literal characters invalid_syntax@invalid_del_target.py.snap000064400000000000000000000271331046102023000320660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_del_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..75, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..9, targets: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4..9, left: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 1, ), }, ), }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 10..22, targets: [ Dict( ExprDict { node_index: NodeIndex(None), range: 14..22, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 15..18, value: StringLiteralValue { inner: Single( StringLiteral { range: 15..18, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 1, ), }, ), }, ], }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 23..37, targets: [ Set( ExprSet { node_index: NodeIndex(None), range: 27..37, elts: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 28..31, value: StringLiteralValue { inner: Single( StringLiteral { range: 28..31, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 33..36, value: StringLiteralValue { inner: Single( StringLiteral { range: 33..36, node_index: NodeIndex(None), value: "y", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 38..74, targets: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 42..46, }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 48..52, value: true, }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 54..59, value: false, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..67, value: Float( 1.0, ), }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 69..74, value: StringLiteralValue { inner: Single( StringLiteral { range: 69..74, node_index: NodeIndex(None), value: "abc", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | del x + 1 | ^^^^^ Syntax Error: Invalid delete target 2 | del {'x': 1} 3 | del {'x', 'y'} | | 1 | del x + 1 2 | del {'x': 1} | ^^^^^^^^ Syntax Error: Invalid delete target 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | | 1 | del x + 1 2 | del {'x': 1} 3 | del {'x', 'y'} | ^^^^^^^^^^ Syntax Error: Invalid delete target 4 | del None, True, False, 1, 1.0, "abc" | | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^^^^ Syntax Error: Invalid delete target | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^^^^ Syntax Error: Invalid delete target | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^^^^^ Syntax Error: Invalid delete target | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^ Syntax Error: Invalid delete target | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^^^ Syntax Error: Invalid delete target | 2 | del {'x': 1} 3 | del {'x', 'y'} 4 | del None, True, False, 1, 1.0, "abc" | ^^^^^ Syntax Error: Invalid delete target invalid_syntax@invalid_fstring_literal_element.py.snap000064400000000000000000000101451046102023000346500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_fstring_literal_element.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..58, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..26, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..26, value: FStringValue { inner: Single( FString( FString { range: 0..26, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..25, node_index: NodeIndex(None), value: "", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..57, value: FString( ExprFString { node_index: NodeIndex(None), range: 27..57, value: FStringValue { inner: Single( FString( FString { range: 27..57, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 31..54, node_index: NodeIndex(None), value: "", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | f'hello \N{INVALID} world' | ^^^^^^^ Syntax Error: Got unexpected unicode 2 | f"""hello \N{INVALID} world""" | | 1 | f'hello \N{INVALID} world' 2 | f"""hello \N{INVALID} world""" | ^^^^^^^ Syntax Error: Got unexpected unicode invalid_syntax@invalid_future_feature.py.snap000064400000000000000000000124241046102023000327760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_future_feature.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..151, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..38, module: Some( Identifier { id: Name("__future__"), range: 5..15, node_index: NodeIndex(None), }, ), names: [ Alias { range: 23..38, node_index: NodeIndex(None), name: Identifier { id: Name("invalid_feature"), range: 23..38, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 39..90, module: Some( Identifier { id: Name("__future__"), range: 44..54, node_index: NodeIndex(None), }, ), names: [ Alias { range: 62..73, node_index: NodeIndex(None), name: Identifier { id: Name("annotations"), range: 62..73, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 75..90, node_index: NodeIndex(None), name: Identifier { id: Name("invalid_feature"), range: 75..90, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 91..150, module: Some( Identifier { id: Name("__future__"), range: 96..106, node_index: NodeIndex(None), }, ), names: [ Alias { range: 114..131, node_index: NodeIndex(None), name: Identifier { id: Name("invalid_feature_1"), range: 114..131, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 133..150, node_index: NodeIndex(None), name: Identifier { id: Name("invalid_feature_2"), range: 133..150, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | from __future__ import invalid_feature | ^^^^^^^^^^^^^^^ Syntax Error: Future feature `invalid_feature` is not defined 2 | from __future__ import annotations, invalid_feature 3 | from __future__ import invalid_feature_1, invalid_feature_2 | | 1 | from __future__ import invalid_feature 2 | from __future__ import annotations, invalid_feature | ^^^^^^^^^^^^^^^ Syntax Error: Future feature `invalid_feature` is not defined 3 | from __future__ import invalid_feature_1, invalid_feature_2 | | 1 | from __future__ import invalid_feature 2 | from __future__ import annotations, invalid_feature 3 | from __future__ import invalid_feature_1, invalid_feature_2 | ^^^^^^^^^^^^^^^^^ Syntax Error: Future feature `invalid_feature_1` is not defined | 1 | from __future__ import invalid_feature 2 | from __future__ import annotations, invalid_feature 3 | from __future__ import invalid_feature_1, invalid_feature_2 | ^^^^^^^^^^^^^^^^^ Syntax Error: Future feature `invalid_feature_2` is not defined invalid_syntax@invalid_match_pattern_target.py.snap000064400000000000000000000142031046102023000341450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_match_pattern_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..53, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..11, id: Name("value"), ctx: Load, }, ), cases: [ MatchCase { range: 17..33, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 22..28, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 22..23, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 22..23, value: Int( 1, ), }, ), }, ), ), name: Some( Identifier { id: Name("_"), range: 27..28, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 30..33, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 30..33, }, ), }, ), ], }, MatchCase { range: 38..53, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 43..48, keys: [], patterns: [], rest: Some( Identifier { id: Name("_"), range: 46..47, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 50..53, }, ), }, ), ], }, ], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 54..63, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 54..59, id: Name("after"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | match value: 2 | case 1 as _: ... | ^ Syntax Error: cannot use '_' as a target 3 | case {**_}: ... 4 | after = 1 | | 1 | match value: 2 | case 1 as _: ... 3 | case {**_}: ... | ^ Syntax Error: cannot use '_' as a target 4 | after = 1 | invalid_syntax@invalid_string_literal.py.snap000064400000000000000000000055751046102023000330040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/invalid_string_literal.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..56, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..25, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..25, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..25, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..55, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 26..55, value: StringLiteralValue { inner: Single( StringLiteral { range: 26..55, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | 'hello \N{INVALID} world' | ^^^^^^^ Syntax Error: Got unexpected unicode 2 | """hello \N{INVALID} world""" | | 1 | 'hello \N{INVALID} world' 2 | """hello \N{INVALID} world""" | ^^^^^^^ Syntax Error: Got unexpected unicode invalid_syntax@ipython_help_escape_command_error_recovery_1.py.snap000064400000000000000000000045501046102023000373330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ipython_help_escape_command_error_recovery_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..52, body: [ With( StmtWith { node_index: NodeIndex(None), range: 37..49, is_async: false, items: [ WithItem { range: 43..44, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("a"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 47..48, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("b"), ctx: Load, }, ), optional_vars: None, }, ], body: [], }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 50..51, kind: Help, value: "", }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"mode": "ipython"} 2 | with (a, ?b) | ^ Syntax Error: Expected `,`, found `?` 3 | ? | | 1 | # parse_options: {"mode": "ipython"} 2 | with (a, ?b) | ^ Syntax Error: Expected `:`, found newline 3 | ? | | 1 | # parse_options: {"mode": "ipython"} 2 | with (a, ?b) 3 | ? | ^ Syntax Error: Expected an indented block after `with` statement invalid_syntax@ipython_help_escape_command_error_recovery_2.py.snap000064400000000000000000000047011046102023000373320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ipython_help_escape_command_error_recovery_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..51, body: [ With( StmtWith { node_index: NodeIndex(None), range: 37..51, is_async: false, items: [ WithItem { range: 42..51, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 42..51, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [], }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"mode": "ipython"} 2 | with (a, ?b | ^ Syntax Error: Expected an expression or a ')' 3 | ? | | 1 | # parse_options: {"mode": "ipython"} 2 | with (a, ?b 3 | ? | ^ Syntax Error: Expected `,`, found `?` | 2 | with (a, ?b 3 | ? | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@ipython_help_escape_command_error_recovery_3.py.snap000064400000000000000000000063721046102023000373410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/ipython_help_escape_command_error_recovery_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..56, body: [ With( StmtWith { node_index: NodeIndex(None), range: 37..47, is_async: false, items: [ WithItem { range: 42..43, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("a"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 46..47, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("b"), ctx: Load, }, ), optional_vars: None, }, ], body: [], }, ), IpyEscapeCommand( StmtIpyEscapeCommand { node_index: NodeIndex(None), range: 48..49, kind: Help, value: "", }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 50..55, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"mode": "ipython"} 2 | with a, ?b | ^ Syntax Error: Expected `,`, found `?` 3 | ? 4 | x = 1 | | 1 | # parse_options: {"mode": "ipython"} 2 | with a, ?b | ^ Syntax Error: Expected `:`, found newline 3 | ? 4 | x = 1 | | 1 | # parse_options: {"mode": "ipython"} 2 | with a, ?b 3 | ? | ^ Syntax Error: Expected an indented block after `with` statement 4 | x = 1 | invalid_syntax@irrefutable_case_pattern.py.snap000064400000000000000000000463061046102023000333050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/irrefutable_case_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..317, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..61, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..26, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 18..21, pattern: None, name: Some( Identifier { id: Name("var"), range: 18..21, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..26, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 23..26, }, ), }, ), ], }, MatchCase { range: 50..61, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 55..56, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 62..102, subject: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 75..86, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 80..81, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..86, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 83..86, }, ), }, ), ], }, MatchCase { range: 91..102, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 96..97, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 96..97, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 99..102, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 99..102, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 125..222, subject: Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 138..160, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 143..155, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 143..147, pattern: None, name: Some( Identifier { id: Name("var1"), range: 143..147, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("var2"), range: 151..155, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 157..160, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 157..160, }, ), }, ), ], }, MatchCase { range: 211..222, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 216..217, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 216..217, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 219..222, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 219..222, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 223..316, subject: Name( ExprName { node_index: NodeIndex(None), range: 229..230, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 236..264, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 241..259, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 241..253, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 241..253, value: Name( ExprName { node_index: NodeIndex(None), range: 241..245, id: Name("enum"), ctx: Load, }, ), attr: Identifier { id: Name("variant"), range: 246..253, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 256..259, pattern: None, name: Some( Identifier { id: Name("var"), range: 256..259, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 261..264, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 261..264, }, ), }, ), ], }, MatchCase { range: 305..316, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 310..311, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 310..311, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 313..316, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 313..316, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match x: 2 | case var: ... # capture pattern | ^^^ Syntax Error: name capture `var` makes remaining patterns unreachable 3 | case 2: ... 4 | match x: | | 3 | case 2: ... 4 | match x: 5 | case _: ... | ^ Syntax Error: wildcard makes remaining patterns unreachable 6 | case 2: ... # wildcard pattern 7 | match x: | | 6 | case 2: ... # wildcard pattern 7 | match x: 8 | case var1 as var2: ... # as pattern with irrefutable left-hand side | ^^^^ Syntax Error: name capture `var1` makes remaining patterns unreachable 9 | case 2: ... 10 | match x: | | 9 | case 2: ... 10 | match x: 11 | case enum.variant | var: ... # or pattern with irrefutable part | ^^^ Syntax Error: name capture `var` makes remaining patterns unreachable 12 | case 2: ... | | 9 | case 2: ... 10 | match x: 11 | case enum.variant | var: ... # or pattern with irrefutable part | ^^^^^^^^^^^^^^^^^^ Syntax Error: alternative patterns bind different names 12 | case 2: ... | invalid_syntax@iter_unpack_return_py37.py.snap000064400000000000000000000163411046102023000330320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/iter_unpack_return_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..91, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..90, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 69..90, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 76..90, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 85..90, value: Name( ExprName { node_index: NodeIndex(None), range: 86..90, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.7"} 2 | rest = (4, 5, 6) 3 | def f(): return 1, 2, 3, *rest | ^^^^^ Syntax Error: Cannot use iterable unpacking in return statements on Python 3.7 (syntax was added in Python 3.8) invalid_syntax@iter_unpack_yield_py37.py.snap000064400000000000000000000365511046102023000326260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/iter_unpack_yield_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..128, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..89, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..89, value: Yield( ExprYield { node_index: NodeIndex(None), range: 69..89, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 75..89, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 84..89, value: Name( ExprName { node_index: NodeIndex(None), range: 85..89, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 90..127, is_async: false, decorator_list: [], name: Identifier { id: Name("h"), range: 94..95, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 95..97, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 99..127, value: Yield( ExprYield { node_index: NodeIndex(None), range: 99..127, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 105..127, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 1, ), }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 109..123, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 115..123, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 2, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 118..123, value: Name( ExprName { node_index: NodeIndex(None), range: 119..123, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 126..127, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.7"} 2 | rest = (4, 5, 6) 3 | def g(): yield 1, 2, 3, *rest | ^^^^^ Syntax Error: Cannot use iterable unpacking in yield expressions on Python 3.7 (syntax was added in Python 3.8) 4 | def h(): yield 1, (yield 2, *rest), 3 | | 2 | rest = (4, 5, 6) 3 | def g(): yield 1, 2, 3, *rest 4 | def h(): yield 1, (yield 2, *rest), 3 | ^^^^^ Syntax Error: Cannot use iterable unpacking in yield expressions on Python 3.7 (syntax was added in Python 3.8) invalid_syntax@lambda_body_with_starred_expr.py.snap000064400000000000000000000347211046102023000343210ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/lambda_body_with_starred_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..62, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..12, parameters: Some( Parameters { range: 7..8, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 7..8, node_index: NodeIndex(None), parameter: Parameter { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Starred( ExprStarred { node_index: NodeIndex(None), range: 10..12, value: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..26, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 13..26, elts: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 13..25, parameters: Some( Parameters { range: 20..21, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 20..21, node_index: NodeIndex(None), parameter: Parameter { range: 20..21, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 20..21, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Starred( ExprStarred { node_index: NodeIndex(None), range: 23..25, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..42, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 27..42, elts: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 27..39, parameters: Some( Parameters { range: 34..35, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 34..35, node_index: NodeIndex(None), parameter: Parameter { range: 34..35, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 34..35, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Starred( ExprStarred { node_index: NodeIndex(None), range: 37..39, value: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 43..61, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 43..61, parameters: Some( Parameters { range: 50..51, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 50..51, node_index: NodeIndex(None), parameter: Parameter { range: 50..51, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 50..51, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Starred( ExprStarred { node_index: NodeIndex(None), range: 53..61, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 54..61, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("z"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | lambda x: *y | ^^ Syntax Error: Starred expression cannot be used here 2 | lambda x: *y, 3 | lambda x: *y, z | | 1 | lambda x: *y 2 | lambda x: *y, | ^^ Syntax Error: Starred expression cannot be used here 3 | lambda x: *y, z 4 | lambda x: *y and z | | 1 | lambda x: *y 2 | lambda x: *y, 3 | lambda x: *y, z | ^^ Syntax Error: Starred expression cannot be used here 4 | lambda x: *y and z | | 2 | lambda x: *y, 3 | lambda x: *y, z 4 | lambda x: *y and z | ^^^^^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@lambda_body_with_yield_expr.py.snap000064400000000000000000000133321046102023000337560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/lambda_body_with_yield_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..17, parameters: Some( Parameters { range: 7..8, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 7..8, node_index: NodeIndex(None), parameter: Parameter { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Yield( ExprYield { node_index: NodeIndex(None), range: 10..17, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("y"), ctx: Load, }, ), ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..40, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 18..40, parameters: Some( Parameters { range: 25..26, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 25..26, node_index: NodeIndex(None), parameter: Parameter { range: 25..26, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 25..26, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 28..40, value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | lambda x: yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here 2 | lambda x: yield from y | | 1 | lambda x: yield y 2 | lambda x: yield from y | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@lazy_import_invalid_context_py315.py.snap000064400000000000000000000350251046102023000350310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/lazy_import_invalid_context_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..322, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 44..84, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 53..67, names: [ Alias { range: 65..67, node_index: NodeIndex(None), name: Identifier { id: Name("os"), range: 65..67, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 68..84, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 80..84, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 86..135, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 95..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("x"), ctx: Load, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 97..135, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 105..114, id: Name("Exception"), ctx: Load, }, ), ), name: None, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 120..135, names: [ Alias { range: 132..135, node_index: NodeIndex(None), name: Identifier { id: Name("sys"), range: 132..135, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 137..169, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 141..145, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 145..147, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 153..169, names: [ Alias { range: 165..169, node_index: NodeIndex(None), name: Identifier { id: Name("math"), range: 165..169, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 171..226, is_async: true, decorator_list: [], name: Identifier { id: Name("async_func"), range: 181..191, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 191..193, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 199..226, module: Some( Identifier { id: Name("json"), range: 209..213, node_index: NodeIndex(None), }, ), names: [ Alias { range: 221..226, node_index: NodeIndex(None), name: Identifier { id: Name("loads"), range: 221..226, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 228..265, decorator_list: [], name: Identifier { id: Name("MyClass"), range: 234..241, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 247..265, names: [ Alias { range: 259..265, node_index: NodeIndex(None), name: Identifier { id: Name("typing"), range: 259..265, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 267..321, is_async: false, decorator_list: [], name: Identifier { id: Name("outer"), range: 271..276, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 276..278, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 284..321, decorator_list: [], name: Identifier { id: Name("Inner"), range: 290..295, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 305..321, names: [ Alias { range: 317..321, node_index: NodeIndex(None), name: Identifier { id: Name("json"), range: 317..321, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.15"} 2 | try: 3 | lazy import os | ^^^^^^^^^^^^^^ Syntax Error: lazy import not allowed inside try/except blocks 4 | except: 5 | pass | | 8 | x 9 | except* Exception: 10 | lazy import sys | ^^^^^^^^^^^^^^^ Syntax Error: lazy import not allowed inside try/except blocks 11 | 12 | def func(): | | 12 | def func(): 13 | lazy import math | ^^^^^^^^^^^^^^^^ Syntax Error: lazy import not allowed inside functions 14 | 15 | async def async_func(): | | 15 | async def async_func(): 16 | lazy from json import loads | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: lazy from ... import not allowed inside functions 17 | 18 | class MyClass: | | 18 | class MyClass: 19 | lazy import typing | ^^^^^^^^^^^^^^^^^^ Syntax Error: lazy import not allowed inside classes 20 | 21 | def outer(): | | 21 | def outer(): 22 | class Inner: 23 | lazy import json | ^^^^^^^^^^^^^^^^ Syntax Error: lazy import not allowed inside classes invalid_syntax@lazy_import_invalid_from_py315.py.snap000064400000000000000000000123121046102023000343020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/lazy_import_invalid_from_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..146, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 44..65, module: Some( Identifier { id: Name("os"), range: 54..56, node_index: NodeIndex(None), }, ), names: [ Alias { range: 64..65, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 64..65, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 66..105, module: Some( Identifier { id: Name("__future__"), range: 76..86, node_index: NodeIndex(None), }, ), names: [ Alias { range: 94..105, node_index: NodeIndex(None), name: Identifier { id: Name("annotations"), range: 94..105, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 107..145, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 111..115, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 115..117, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 123..145, module: Some( Identifier { id: Name("sys"), range: 133..136, node_index: NodeIndex(None), }, ), names: [ Alias { range: 144..145, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 144..145, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.15"} 2 | lazy from os import * | ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: lazy from ... import * is not allowed 3 | lazy from __future__ import annotations | | 1 | # parse_options: {"target-version": "3.15"} 2 | lazy from os import * 3 | lazy from __future__ import annotations | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: lazy from __future__ import is not allowed 4 | 5 | def func(): | | 5 | def func(): 6 | lazy from sys import * | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: lazy from ... import not allowed inside functions | 5 | def func(): 6 | lazy from sys import * | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: `from sys import *` only allowed at module level invalid_syntax@lazy_import_stmt_py314.py.snap000064400000000000000000000045601046102023000326250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/lazy_import_stmt_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 44..59, names: [ Alias { range: 56..59, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 56..59, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 60..84, module: Some( Identifier { id: Name("bar"), range: 70..73, node_index: NodeIndex(None), }, ), names: [ Alias { range: 81..84, node_index: NodeIndex(None), name: Identifier { id: Name("baz"), range: 81..84, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | lazy import foo | ^^^^ Syntax Error: Cannot use `lazy` import statement on Python 3.14 (syntax was added in Python 3.15) 3 | lazy from bar import baz | | 1 | # parse_options: {"target-version": "3.14"} 2 | lazy import foo 3 | lazy from bar import baz | ^^^^ Syntax Error: Cannot use `lazy` import statement on Python 3.14 (syntax was added in Python 3.15) invalid_syntax@match_before_py310.py.snap000064400000000000000000000045321046102023000316160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_before_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..79, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 45..78, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 2, ), }, ), cases: [ MatchCase { range: 58..78, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 63..64, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 1, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 74..78, }, ), ], }, ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.9" } 2 | match 2: | ^^^^^ Syntax Error: Cannot use `match` statement on Python 3.9 (syntax was added in Python 3.10) 3 | case 1: 4 | pass | invalid_syntax@match_classify_as_keyword.py.snap000064400000000000000000000050541046102023000334640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_classify_as_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..33, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..32, subject: Yield( ExprYield { node_index: NodeIndex(None), range: 6..15, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("foo"), ctx: Load, }, ), ), }, ), cases: [ MatchCase { range: 21..32, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 26..27, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match yield foo: | ^^^^^^^^^ Syntax Error: Yield expression cannot be used here 2 | case _: ... | invalid_syntax@match_classify_as_keyword_or_identifier.py.snap000064400000000000000000000050061046102023000363630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_classify_as_keyword_or_identifier.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..39, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..38, subject: Starred( ExprStarred { node_index: NodeIndex(None), range: 6..10, value: Name( ExprName { node_index: NodeIndex(None), range: 7..10, id: Name("foo"), ctx: Load, }, ), ctx: Load, }, ), cases: [ MatchCase { range: 27..38, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 32..33, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 35..38, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 35..38, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match *foo: # Keyword | ^^^^ Syntax Error: Starred expression cannot be used here 2 | case _: ... | invalid_syntax@match_expected_colon.py.snap000064400000000000000000000060451046102023000324140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_expected_colon.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..29, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..28, subject: List( ExprList { node_index: NodeIndex(None), range: 6..12, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 2, ), }, ), ], ctx: Load, }, ), cases: [ MatchCase { range: 17..28, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 22..23, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match [1, 2] | ^ Syntax Error: Expected `:`, found newline 2 | case _: ... | invalid_syntax@match_stmt_expect_indented_block.py.snap000064400000000000000000000044211046102023000350000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_expect_indented_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..23, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..22, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 11..22, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 16..17, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match foo: 2 | case _: ... | ^^^^ Syntax Error: Expected an indented block after `match` statement | 1 | match foo: 2 | case _: ... | ^ Syntax Error: Expected dedent, found end of file invalid_syntax@match_stmt_expected_case_block.py.snap000064400000000000000000000105641046102023000344370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_expected_case_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..61, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..13, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 13..18, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..18, value: Int( 1, ), }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 19..32, subject: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Load, }, ), cases: [], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 32..60, subject: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("y"), ctx: Load, }, ), cases: [ MatchCase { range: 49..60, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 54..55, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match x: 2 | x = 1 | ^ Syntax Error: Expected `case` block 3 | match x: 4 | match y: | | 1 | match x: 2 | x = 1 3 | match x: | ^ Syntax Error: Expected a statement 4 | match y: 5 | case _: ... | | 2 | x = 1 3 | match x: 4 | match y: | ^^^^^ Syntax Error: Expected `case` block 5 | case _: ... | | 4 | match y: 5 | case _: ... | ^ Syntax Error: Expected a statement invalid_syntax@match_stmt_invalid_guard_expr.py.snap000064400000000000000000000230551046102023000343360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_invalid_guard_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..100, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..30, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..30, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 18..19, pattern: None, name: Some( Identifier { id: Name("y"), range: 18..19, node_index: NodeIndex(None), }, ), }, ), guard: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 23..25, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 27..30, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 27..30, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 31..63, subject: Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 44..63, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 49..50, pattern: None, name: Some( Identifier { id: Name("y"), range: 49..50, node_index: NodeIndex(None), }, ), }, ), guard: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 55..57, value: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 60..63, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 60..63, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 64..99, subject: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 77..99, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 82..83, pattern: None, name: Some( Identifier { id: Name("y"), range: 82..83, node_index: NodeIndex(None), }, ), }, ), guard: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 87..94, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("x"), ctx: Load, }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match x: 2 | case y if *a: ... | ^^ Syntax Error: Starred expression cannot be used here 3 | match x: 4 | case y if (*a): ... | | 2 | case y if *a: ... 3 | match x: 4 | case y if (*a): ... | ^^ Syntax Error: Starred expression cannot be used here 5 | match x: 6 | case y if yield x: ... | | 4 | case y if (*a): ... 5 | match x: 6 | case y if yield x: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@match_stmt_invalid_subject_expr.py.snap000064400000000000000000000222361046102023000346730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_invalid_subject_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..131, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..27, subject: Starred( ExprStarred { node_index: NodeIndex(None), range: 7..9, value: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), cases: [ MatchCase { range: 16..27, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 21..22, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 24..27, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 65..99, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 71..82, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 71..79, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 72..79, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 88..99, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 93..94, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 100..130, subject: Yield( ExprYield { node_index: NodeIndex(None), range: 106..113, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Load, }, ), ), }, ), cases: [ MatchCase { range: 119..130, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 124..125, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 127..130, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 127..130, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match (*x): | ^^ Syntax Error: Starred expression cannot be used here 2 | case _: ... 3 | # Starred expression precedence test | | 2 | case _: ... 3 | # Starred expression precedence test 4 | match *x and y, z: | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 5 | case _: ... 6 | match yield x: | | 4 | match *x and y, z: 5 | case _: ... 6 | match yield x: | ^^^^^^^ Syntax Error: Yield expression cannot be used here 7 | case _: ... | invalid_syntax@match_stmt_missing_guard_expr.py.snap000064400000000000000000000047361046102023000343660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_missing_guard_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..27, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..27, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 18..19, pattern: None, name: Some( Identifier { id: Name("y"), range: 18..19, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 24..27, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match x: 2 | case y if: ... | ^ Syntax Error: Expected an expression invalid_syntax@match_stmt_missing_pattern.py.snap000064400000000000000000000047321046102023000336770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_missing_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..23, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..23, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 17..17, value: Name( ExprName { node_index: NodeIndex(None), range: 17..17, id: Name(""), ctx: Invalid, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match x: 2 | case : ... | ^ Syntax Error: Expected a pattern invalid_syntax@match_stmt_no_newline_before_case.py.snap000064400000000000000000000044141046102023000351400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_no_newline_before_case.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..23, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..22, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 11..22, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 16..17, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match foo: case _: ... | ^^^^ Syntax Error: Expected newline, found `case` | 1 | match foo: case _: ... | ^ Syntax Error: Expected dedent, found end of file invalid_syntax@match_stmt_single_starred_subject.py.snap000064400000000000000000000047651046102023000352230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/match_stmt_single_starred_subject.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..27, subject: Starred( ExprStarred { node_index: NodeIndex(None), range: 6..10, value: Name( ExprName { node_index: NodeIndex(None), range: 7..10, id: Name("foo"), ctx: Load, }, ), ctx: Load, }, ), cases: [ MatchCase { range: 16..27, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 21..22, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 24..27, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match *foo: | ^^^^ Syntax Error: Starred expression cannot be used here 2 | case _: ... | invalid_syntax@mixed_bytes_and_non_bytes_literals.py.snap000064400000000000000000000224361046102023000353640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/mixed_bytes_and_non_bytes_literals.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..17, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 0..7, node_index: NodeIndex(None), value: "first", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 8..17, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "first", }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..36, value: FString( ExprFString { node_index: NodeIndex(None), range: 18..36, value: FStringValue { inner: Concatenated( [ FString( FString { range: 18..26, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 20..25, node_index: NodeIndex(None), value: "first", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 27..36, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 37..63, value: FString( ExprFString { node_index: NodeIndex(None), range: 37..63, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 37..44, node_index: NodeIndex(None), value: "first", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 45..54, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 47..53, node_index: NodeIndex(None), value: "second", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 55..63, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | 'first' b'second' | ^^^^^^^^^^^^^^^^^ Syntax Error: Bytes literal cannot be mixed with non-bytes literals 2 | f'first' b'second' 3 | 'first' f'second' b'third' | | 1 | 'first' b'second' 2 | f'first' b'second' | ^^^^^^^^^^^^^^^^^^ Syntax Error: Bytes literal cannot be mixed with non-bytes literals 3 | 'first' f'second' b'third' | | 1 | 'first' b'second' 2 | f'first' b'second' 3 | 'first' f'second' b'third' | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Bytes literal cannot be mixed with non-bytes literals invalid_syntax@multiple_assignment_in_case_pattern.py.snap000064400000000000000000001274421046102023000355530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/multiple_assignment_in_case_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..456, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..444, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 2, ), }, ), cases: [ MatchCase { range: 13..32, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 18..27, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 19..20, pattern: None, name: Some( Identifier { id: Name("y"), range: 19..20, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 22..23, pattern: None, name: Some( Identifier { id: Name("z"), range: 22..23, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 25..26, pattern: None, name: Some( Identifier { id: Name("y"), range: 25..26, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, MatchCase { range: 54..74, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 59..69, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 60..61, pattern: None, name: Some( Identifier { id: Name("y"), range: 60..61, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 63..64, pattern: None, name: Some( Identifier { id: Name("z"), range: 63..64, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 66..68, name: Some( Identifier { id: Name("y"), range: 67..68, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 71..74, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 71..74, }, ), }, ), ], }, MatchCase { range: 96..115, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 101..110, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 102..103, pattern: None, name: Some( Identifier { id: Name("y"), range: 102..103, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 105..106, pattern: None, name: Some( Identifier { id: Name("y"), range: 105..106, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 108..109, pattern: None, name: Some( Identifier { id: Name("y"), range: 108..109, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 112..115, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 112..115, }, ), }, ), ], }, MatchCase { range: 146..168, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 151..163, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 152..153, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 2, ), }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 155..156, pattern: None, name: Some( Identifier { id: Name("x"), range: 155..156, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 161..162, pattern: None, name: Some( Identifier { id: Name("x"), range: 161..162, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 165..168, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 165..168, }, ), }, ), ], }, MatchCase { range: 207..228, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 212..223, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..214, value: Int( 1, ), }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 216..217, pattern: None, name: Some( Identifier { id: Name("x"), range: 216..217, node_index: NodeIndex(None), }, ), }, ), ], rest: Some( Identifier { id: Name("x"), range: 221..222, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 225..228, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 225..228, }, ), }, ), ], }, MatchCase { range: 269..290, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 274..285, cls: Name( ExprName { node_index: NodeIndex(None), range: 274..279, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 279..285, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 280..281, pattern: None, name: Some( Identifier { id: Name("x"), range: 280..281, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 283..284, pattern: None, name: Some( Identifier { id: Name("x"), range: 283..284, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 287..290, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 287..290, }, ), }, ), ], }, MatchCase { range: 320..345, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 325..340, cls: Name( ExprName { node_index: NodeIndex(None), range: 325..330, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 330..340, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 331..334, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 331..332, node_index: NodeIndex(None), }, pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 333..334, pattern: None, name: Some( Identifier { id: Name("x"), range: 333..334, node_index: NodeIndex(None), }, ), }, ), }, PatternKeyword { range: 336..339, node_index: NodeIndex(None), attr: Identifier { id: Name("z"), range: 336..337, node_index: NodeIndex(None), }, pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 338..339, pattern: None, name: Some( Identifier { id: Name("x"), range: 338..339, node_index: NodeIndex(None), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 342..345, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 342..345, }, ), }, ), ], }, MatchCase { range: 372..412, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 377..407, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 377..380, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 378..379, pattern: None, name: Some( Identifier { id: Name("x"), range: 378..379, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 383..389, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 384..385, value: Int( 1, ), }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 387..388, pattern: None, name: Some( Identifier { id: Name("x"), range: 387..388, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 392..407, cls: Name( ExprName { node_index: NodeIndex(None), range: 392..397, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 397..407, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 398..401, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 398..399, node_index: NodeIndex(None), }, pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 400..401, pattern: None, name: Some( Identifier { id: Name("x"), range: 400..401, node_index: NodeIndex(None), }, ), }, ), }, PatternKeyword { range: 403..406, node_index: NodeIndex(None), attr: Identifier { id: Name("z"), range: 403..404, node_index: NodeIndex(None), }, pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 405..406, pattern: None, name: Some( Identifier { id: Name("x"), range: 405..406, node_index: NodeIndex(None), }, ), }, ), }, ], }, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 409..412, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 409..412, }, ), }, ), ], }, MatchCase { range: 428..444, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 433..439, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 433..434, pattern: None, name: Some( Identifier { id: Name("x"), range: 433..434, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("x"), range: 438..439, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 441..444, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 441..444, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match 2: 2 | case [y, z, y]: ... # MatchSequence | ^ Syntax Error: multiple assignments to name `y` in pattern 3 | case [y, z, *y]: ... # MatchSequence 4 | case [y, y, y]: ... # MatchSequence multiple | | 1 | match 2: 2 | case [y, z, y]: ... # MatchSequence 3 | case [y, z, *y]: ... # MatchSequence | ^ Syntax Error: multiple assignments to name `y` in pattern 4 | case [y, y, y]: ... # MatchSequence multiple 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern | | 2 | case [y, z, y]: ... # MatchSequence 3 | case [y, z, *y]: ... # MatchSequence 4 | case [y, y, y]: ... # MatchSequence multiple | ^ Syntax Error: multiple assignments to name `y` in pattern 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest | | 2 | case [y, z, y]: ... # MatchSequence 3 | case [y, z, *y]: ... # MatchSequence 4 | case [y, y, y]: ... # MatchSequence multiple | ^ Syntax Error: multiple assignments to name `y` in pattern 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest | | 3 | case [y, z, *y]: ... # MatchSequence 4 | case [y, y, y]: ... # MatchSequence multiple 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern | ^ Syntax Error: multiple assignments to name `x` in pattern 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest 7 | case Class(x, x): ... # MatchClass positional | | 4 | case [y, y, y]: ... # MatchSequence multiple 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest | ^ Syntax Error: multiple assignments to name `x` in pattern 7 | case Class(x, x): ... # MatchClass positional 8 | case Class(y=x, z=x): ... # MatchClass keyword | | 5 | case {1: x, 2: x}: ... # MatchMapping duplicate pattern 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest 7 | case Class(x, x): ... # MatchClass positional | ^ Syntax Error: multiple assignments to name `x` in pattern 8 | case Class(y=x, z=x): ... # MatchClass keyword 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr | | 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest 7 | case Class(x, x): ... # MatchClass positional 8 | case Class(y=x, z=x): ... # MatchClass keyword | ^ Syntax Error: multiple assignments to name `x` in pattern 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr 10 | case x as x: ... # MatchAs | | 7 | case Class(x, x): ... # MatchClass positional 8 | case Class(y=x, z=x): ... # MatchClass keyword 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr | ^ Syntax Error: multiple assignments to name `x` in pattern 10 | case x as x: ... # MatchAs | | 8 | case Class(y=x, z=x): ... # MatchClass keyword 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr 10 | case x as x: ... # MatchAs | ^ Syntax Error: multiple assignments to name `x` in pattern invalid_syntax@multiple_clauses_on_same_line.py.snap000064400000000000000000000361071046102023000343310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/multiple_clauses_on_same_line.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..258, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..41, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], elif_else_clauses: [ ElifElseClause { range: 14..30, node_index: NodeIndex(None), test: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 19..24, value: false, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 26..30, }, ), ], }, ElifElseClause { range: 31..41, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 37..41, }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 42..85, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 45..49, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 51..55, }, ), ], elif_else_clauses: [ ElifElseClause { range: 57..73, node_index: NodeIndex(None), test: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 62..67, value: false, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 69..73, }, ), ], }, ElifElseClause { range: 75..85, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 81..85, }, ), ], }, ], }, ), For( StmtFor { node_index: NodeIndex(None), range: 86..117, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 95..99, id: Name("iter"), ctx: Load, }, ), body: [ Break( StmtBreak { node_index: NodeIndex(None), range: 101..106, }, ), ], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 113..117, }, ), ], }, ), For( StmtFor { node_index: NodeIndex(None), range: 118..150, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 127..131, id: Name("iter"), ctx: Load, }, ), body: [ Break( StmtBreak { node_index: NodeIndex(None), range: 133..138, }, ), ], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 146..150, }, ), ], }, ), Try( StmtTry { node_index: NodeIndex(None), range: 151..202, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 156..160, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 161..177, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 168..171, id: Name("exc"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 173..177, }, ), ], }, ), ], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 184..188, }, ), ], finalbody: [ Pass( StmtPass { node_index: NodeIndex(None), range: 198..202, }, ), ], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 203..257, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 208..212, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 214..230, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 221..224, id: Name("exc"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 226..230, }, ), ], }, ), ], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 238..242, }, ), ], finalbody: [ Pass( StmtPass { node_index: NodeIndex(None), range: 253..257, }, ), ], is_star: false, }, ), ], }, ) ``` ## Errors | 1 | if True: pass elif False: pass else: pass | ^^^^ Syntax Error: Expected newline, found `elif` 2 | if True: pass; elif False: pass; else: pass 3 | for x in iter: break else: pass | | 1 | if True: pass elif False: pass else: pass | ^^^^ Syntax Error: Expected newline, found `else` 2 | if True: pass; elif False: pass; else: pass 3 | for x in iter: break else: pass | | 1 | if True: pass elif False: pass else: pass 2 | if True: pass; elif False: pass; else: pass | ^^^^ Syntax Error: Expected newline, found `elif` 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass | | 1 | if True: pass elif False: pass else: pass 2 | if True: pass; elif False: pass; else: pass | ^^^^ Syntax Error: Expected newline, found `else` 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass | | 1 | if True: pass elif False: pass else: pass 2 | if True: pass; elif False: pass; else: pass 3 | for x in iter: break else: pass | ^^^^ Syntax Error: Expected newline, found `else` 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass | | 2 | if True: pass; elif False: pass; else: pass 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass | ^^^^ Syntax Error: Expected newline, found `else` 5 | try: pass except exc: pass else: pass finally: pass 6 | try: pass; except exc: pass; else: pass; finally: pass | | 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass | ^^^^^^ Syntax Error: Expected newline, found `except` 6 | try: pass; except exc: pass; else: pass; finally: pass | | 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass | ^^^^ Syntax Error: Expected newline, found `else` 6 | try: pass; except exc: pass; else: pass; finally: pass | | 3 | for x in iter: break else: pass 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass | ^^^^^^^ Syntax Error: Expected newline, found `finally` 6 | try: pass; except exc: pass; else: pass; finally: pass | | 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass 6 | try: pass; except exc: pass; else: pass; finally: pass | ^^^^^^ Syntax Error: Expected newline, found `except` | 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass 6 | try: pass; except exc: pass; else: pass; finally: pass | ^^^^ Syntax Error: Expected newline, found `else` | 4 | for x in iter: break; else: pass 5 | try: pass except exc: pass else: pass finally: pass 6 | try: pass; except exc: pass; else: pass; finally: pass | ^^^^^^^ Syntax Error: Expected newline, found `finally` invalid_syntax@multiple_starred_assignment_target.py.snap000064400000000000000000000562031046102023000354230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/multiple_starred_assignment_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..17, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 0..8, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 5..7, value: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("b"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 11..17, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 12..13, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 15..16, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 18..35, targets: [ List( ExprList { node_index: NodeIndex(None), range: 18..26, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 19..21, value: Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 23..25, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("b"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 29..35, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..34, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 36..59, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 36..47, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 37..39, value: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 41..43, value: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("b"), ctx: Store, }, ), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("c"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 60..83, targets: [ List( ExprList { node_index: NodeIndex(None), range: 60..71, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 61..63, value: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 65..67, value: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("b"), ctx: Store, }, ), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 69..70, id: Name("c"), ctx: Store, }, ), ], ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 74..83, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 84..111, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 84..102, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 85..87, value: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 89..91, value: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("b"), ctx: Store, }, ), ctx: Store, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 93..101, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("c"), ctx: Store, }, ), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 98..100, value: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("d"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 105..111, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 106..107, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 109..110, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | (*a, *b) = (1, 2) | ^^^^^^^^ Syntax Error: Two starred expressions in assignment 2 | [*a, *b] = (1, 2) 3 | (*a, *b, c) = (1, 2, 3) | | 1 | (*a, *b) = (1, 2) 2 | [*a, *b] = (1, 2) | ^^^^^^^^ Syntax Error: Two starred expressions in assignment 3 | (*a, *b, c) = (1, 2, 3) 4 | [*a, *b, c] = (1, 2, 3) | | 1 | (*a, *b) = (1, 2) 2 | [*a, *b] = (1, 2) 3 | (*a, *b, c) = (1, 2, 3) | ^^^^^^^^^^^ Syntax Error: Two starred expressions in assignment 4 | [*a, *b, c] = (1, 2, 3) 5 | (*a, *b, (*c, *d)) = (1, 2) | | 2 | [*a, *b] = (1, 2) 3 | (*a, *b, c) = (1, 2, 3) 4 | [*a, *b, c] = (1, 2, 3) | ^^^^^^^^^^^ Syntax Error: Two starred expressions in assignment 5 | (*a, *b, (*c, *d)) = (1, 2) | | 3 | (*a, *b, c) = (1, 2, 3) 4 | [*a, *b, c] = (1, 2, 3) 5 | (*a, *b, (*c, *d)) = (1, 2) | ^^^^^^^^^^^^^^^^^^ Syntax Error: Two starred expressions in assignment | 3 | (*a, *b, c) = (1, 2, 3) 4 | [*a, *b, c] = (1, 2, 3) 5 | (*a, *b, (*c, *d)) = (1, 2) | ^^^^^^^^ Syntax Error: Two starred expressions in assignment invalid_syntax@multiple_starred_names_in_sequence_pattern.py.snap000064400000000000000000000114071046102023000371200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/multiple_starred_names_in_sequence_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..52, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 19..52, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 24..47, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 24..30, name: Some( Identifier { id: Name("first"), range: 25..30, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 32..39, name: Some( Identifier { id: Name("second"), range: 33..39, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 41..47, name: Some( Identifier { id: Name("third"), range: 42..47, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | match subject: 2 | case *first, *second, *third: ... | ^^^^^^^ Syntax Error: multiple starred names in sequence pattern | 1 | match subject: 2 | case *first, *second, *third: ... | ^^^^^^ Syntax Error: multiple starred names in sequence pattern invalid_syntax@named_expr_slice.py.snap000064400000000000000000000260031046102023000315420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/named_expr_slice.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..119, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 80..92, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 80..92, value: Name( ExprName { node_index: NodeIndex(None), range: 80..83, id: Name("lst"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 84..91, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 84..88, target: Name( ExprName { node_index: NodeIndex(None), range: 84..85, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 87..88, value: Int( 1, ), }, ), }, ), ), upper: Some( UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 89..91, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 90..91, value: Int( 1, ), }, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..100, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 93..100, value: Name( ExprName { node_index: NodeIndex(None), range: 93..96, id: Name("lst"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 97..100, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 97..98, value: Int( 1, ), }, ), ), upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("x"), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 102..103, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 102..103, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 105..114, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 105..114, value: Name( ExprName { node_index: NodeIndex(None), range: 105..108, id: Name("lst"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 109..114, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 109..110, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 111..112, value: Int( 3, ), }, ), ), step: Some( Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 116..117, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 116..117, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | # even after 3.9, an unparenthesized named expression is not allowed in a slice 2 | lst[x:=1:-1] | ^^^^ Syntax Error: Unparenthesized named expression cannot be used here 3 | lst[1:x:=1] 4 | lst[1:3:x:=1] | | 1 | # even after 3.9, an unparenthesized named expression is not allowed in a slice 2 | lst[x:=1:-1] 3 | lst[1:x:=1] | ^^ Syntax Error: Expected `]`, found `:=` 4 | lst[1:3:x:=1] | | 1 | # even after 3.9, an unparenthesized named expression is not allowed in a slice 2 | lst[x:=1:-1] 3 | lst[1:x:=1] | ^ Syntax Error: Expected a statement 4 | lst[1:3:x:=1] | | 1 | # even after 3.9, an unparenthesized named expression is not allowed in a slice 2 | lst[x:=1:-1] 3 | lst[1:x:=1] | ^ Syntax Error: Expected a statement 4 | lst[1:3:x:=1] | | 2 | lst[x:=1:-1] 3 | lst[1:x:=1] 4 | lst[1:3:x:=1] | ^^ Syntax Error: Expected `]`, found `:=` | 2 | lst[x:=1:-1] 3 | lst[1:x:=1] 4 | lst[1:3:x:=1] | ^ Syntax Error: Expected a statement | 2 | lst[x:=1:-1] 3 | lst[1:x:=1] 4 | lst[1:3:x:=1] | ^ Syntax Error: Expected a statement invalid_syntax@named_expr_slice_parse_error.py.snap000064400000000000000000000102621046102023000341450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/named_expr_slice_parse_error.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..130, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 117..129, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 117..129, value: Name( ExprName { node_index: NodeIndex(None), range: 117..120, id: Name("lst"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 121..128, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 121..125, target: Name( ExprName { node_index: NodeIndex(None), range: 121..122, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 124..125, value: Int( 1, ), }, ), }, ), ), upper: Some( UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 126..128, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 127..128, value: Int( 1, ), }, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | # before 3.9, only emit the parse error, not the unsupported syntax error 3 | lst[x:=1:-1] | ^^^^ Syntax Error: Unparenthesized named expression cannot be used here invalid_syntax@nested_async_comprehension_py310.py.snap000064400000000000000000001774721046102023000346260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nested_async_comprehension_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..467, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..111, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 54..55, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 55..57, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 59..111, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 66..111, elt: ListComp( ExprListComp { node_index: NodeIndex(None), range: 67..92, elt: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 70..91, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 85..91, func: Name( ExprName { node_index: NodeIndex(None), range: 85..88, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 88..91, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 93..110, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 102..110, func: Name( ExprName { node_index: NodeIndex(None), range: 102..107, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 107..110, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 108..109, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 122..192, is_async: true, decorator_list: [], name: Identifier { id: Name("g"), range: 132..133, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 133..135, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 137..192, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 144..192, elt: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 145..173, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 1, ), }, ), generators: [ Comprehension { range: 151..172, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 166..172, func: Name( ExprName { node_index: NodeIndex(None), range: 166..169, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 169..172, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 174..191, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 183..191, func: Name( ExprName { node_index: NodeIndex(None), range: 183..188, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 188..191, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 189..190, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 200..267, is_async: true, decorator_list: [], name: Identifier { id: Name("h"), range: 210..211, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 211..213, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 215..267, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 222..267, elt: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 223..248, elt: Name( ExprName { node_index: NodeIndex(None), range: 224..225, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 226..247, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 241..247, func: Name( ExprName { node_index: NodeIndex(None), range: 241..244, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 244..247, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 249..266, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 253..254, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 258..266, func: Name( ExprName { node_index: NodeIndex(None), range: 258..263, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 263..266, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 264..265, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 277..371, is_async: true, decorator_list: [], name: Identifier { id: Name("i"), range: 287..288, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 288..290, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 292..371, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 299..371, elt: Tuple( ExprTuple { node_index: NodeIndex(None), range: 300..352, elts: [ ListComp( ExprListComp { node_index: NodeIndex(None), range: 301..328, elt: Name( ExprName { node_index: NodeIndex(None), range: 302..303, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 304..327, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 314..315, id: Name("y"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 319..327, func: Name( ExprName { node_index: NodeIndex(None), range: 319..324, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 324..327, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 325..326, value: Int( 1, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), ListComp( ExprListComp { node_index: NodeIndex(None), range: 330..351, elt: Name( ExprName { node_index: NodeIndex(None), range: 331..332, id: Name("z"), ctx: Load, }, ), generators: [ Comprehension { range: 333..350, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 337..338, id: Name("z"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 342..350, func: Name( ExprName { node_index: NodeIndex(None), range: 342..347, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 347..350, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 348..349, value: Int( 2, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ], ctx: Load, parenthesized: true, }, ), generators: [ Comprehension { range: 353..370, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 357..358, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 362..370, func: Name( ExprName { node_index: NodeIndex(None), range: 362..367, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 367..370, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 368..369, value: Int( 5, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 372..466, is_async: true, decorator_list: [], name: Identifier { id: Name("j"), range: 382..383, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 383..385, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 387..466, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 394..466, elt: Tuple( ExprTuple { node_index: NodeIndex(None), range: 395..447, elts: [ ListComp( ExprListComp { node_index: NodeIndex(None), range: 396..417, elt: Name( ExprName { node_index: NodeIndex(None), range: 397..398, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 399..416, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 403..404, id: Name("y"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 408..416, func: Name( ExprName { node_index: NodeIndex(None), range: 408..413, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 413..416, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 414..415, value: Int( 1, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ListComp( ExprListComp { node_index: NodeIndex(None), range: 419..446, elt: Name( ExprName { node_index: NodeIndex(None), range: 420..421, id: Name("z"), ctx: Load, }, ), generators: [ Comprehension { range: 422..445, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 432..433, id: Name("z"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 437..445, func: Name( ExprName { node_index: NodeIndex(None), range: 437..442, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 442..445, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 443..444, value: Int( 2, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), ], ctx: Load, parenthesized: true, }, ), generators: [ Comprehension { range: 448..465, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 452..453, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 457..465, func: Name( ExprName { node_index: NodeIndex(None), range: 457..462, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 462..465, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 463..464, value: Int( 5, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | # parse_options: {"target-version": "3.10"} 2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list | ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11) 3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict 4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set | | 1 | # parse_options: {"target-version": "3.10"} 2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list 3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict | ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11) 4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set 5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] | | 2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list 3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict 4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set | ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11) 5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] 6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)] | | 3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict 4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set 5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] | ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11) 6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)] | | 4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set 5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)] 6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)] | ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11) invalid_syntax@nested_quote_in_format_spec_py312.py.snap000064400000000000000000000107711046102023000347530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nested_quote_in_format_spec_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..94, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..53, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..53, value: FStringValue { inner: Concatenated( [ FString( FString { range: 44..50, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..49, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..48, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 49..49, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 50..53, node_index: NodeIndex(None), value: "}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.12"} 2 | f"{1:""}" # this is a ParseError on all versions | ^ Syntax Error: f-string: expecting `}` invalid_syntax@node_range_with_gaps.py.snap000064400000000000000000000076471046102023000324240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/node_range_with_gaps.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..7, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 18..32, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 22..25, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 25..27, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 33..40, is_async: false, decorator_list: [], name: Identifier { id: Name("baz"), range: 37..40, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 40..40, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [], }, ), ], }, ) ``` ## Errors | 1 | def foo # comment | ^ Syntax Error: Expected `(`, found newline 2 | def bar(): ... 3 | def baz | | 1 | def foo # comment 2 | def bar(): ... | ^^^ Syntax Error: Expected `)`, found `def` 3 | def baz | | 1 | def foo # comment 2 | def bar(): ... 3 | def baz | ^ Syntax Error: Expected `(`, found newline | 2 | def bar(): ... 3 | def baz | ^ Syntax Error: Expected `)`, found end of file invalid_syntax@nonlocal_declaration_at_module_level.py.snap000064400000000000000000000031311046102023000356300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_declaration_at_module_level.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..25, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 0..10, names: [ Identifier { id: Name("x"), range: 9..10, node_index: NodeIndex(None), }, ], }, ), Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 11..24, names: [ Identifier { id: Name("x"), range: 20..21, node_index: NodeIndex(None), }, Identifier { id: Name("y"), range: 23..24, node_index: NodeIndex(None), }, ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | nonlocal x | ^^^^^^^^^^ Syntax Error: nonlocal declaration not allowed at module level 2 | nonlocal x, y | | 1 | nonlocal x 2 | nonlocal x, y | ^^^^^^^^^^^^^ Syntax Error: nonlocal declaration not allowed at module level invalid_syntax@nonlocal_stmt_empty.py.snap000064400000000000000000000031041046102023000323300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_empty.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..22, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..21, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 13..21, names: [], }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def _(): 2 | nonlocal | ^ Syntax Error: Nonlocal statement must have at least one name invalid_syntax@nonlocal_stmt_expression.py.snap000064400000000000000000000057361046102023000334060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..27, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 13..23, names: [ Identifier { id: Name("x"), range: 22..23, node_index: NodeIndex(None), }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 24..27, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..27, value: Int( 1, ), }, ), }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def _(): 2 | nonlocal x + 1 | ^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@nonlocal_stmt_trailing_comma.py.snap000064400000000000000000000067021046102023000341660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_trailing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..59, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..58, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 13..23, names: [], }, ), Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 28..39, names: [ Identifier { id: Name("x"), range: 37..38, node_index: NodeIndex(None), }, ], }, ), Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 44..58, names: [ Identifier { id: Name("x"), range: 53..54, node_index: NodeIndex(None), }, Identifier { id: Name("y"), range: 56..57, node_index: NodeIndex(None), }, ], }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def _(): 2 | nonlocal , | ^ Syntax Error: Expected an identifier 3 | nonlocal x, 4 | nonlocal x, y, | | 1 | def _(): 2 | nonlocal , | ^ Syntax Error: Nonlocal statement must have at least one name 3 | nonlocal x, 4 | nonlocal x, y, | | 1 | def _(): 2 | nonlocal , 3 | nonlocal x, | ^ Syntax Error: Trailing comma not allowed 4 | nonlocal x, y, | | 2 | nonlocal , 3 | nonlocal x, 4 | nonlocal x, y, | ^ Syntax Error: Trailing comma not allowed invalid_syntax@param_missing_annotation.py.snap000064400000000000000000000116371046102023000333330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_missing_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..35, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..16, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..11, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..10, node_index: NodeIndex(None), parameter: Parameter { range: 8..10, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 13..16, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 13..16, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 17..34, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 21..24, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 24..29, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 25..27, node_index: NodeIndex(None), parameter: Parameter { range: 25..27, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 25..26, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 31..34, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 31..34, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(x:): ... | ^ Syntax Error: Expected an expression 2 | def foo(x:,): ... | | 1 | def foo(x:): ... 2 | def foo(x:,): ... | ^ Syntax Error: Expected an expression invalid_syntax@param_missing_default.py.snap000064400000000000000000000126341046102023000326030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_missing_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..16, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..11, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..10, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 13..16, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 13..16, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 17..40, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 21..24, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 24..35, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 25..33, node_index: NodeIndex(None), parameter: Parameter { range: 25..31, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 25..26, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 28..31, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 37..40, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 37..40, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(x=): ... | ^ Syntax Error: Expected an expression 2 | def foo(x: int = ): ... | | 1 | def foo(x=): ... 2 | def foo(x: int = ): ... | ^ Syntax Error: Expected an expression invalid_syntax@param_with_invalid_annotation.py.snap000064400000000000000000000255341046102023000343440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_with_invalid_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..81, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..23, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..18, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..17, node_index: NodeIndex(None), parameter: Parameter { range: 8..17, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 8..11, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..17, value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 24..52, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 28..31, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 31..47, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 32..46, node_index: NodeIndex(None), parameter: Parameter { range: 32..46, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 32..35, node_index: NodeIndex(None), }, annotation: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 37..46, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("int"), ctx: Load, }, ), ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 53..80, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 57..60, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 60..75, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 61..67, node_index: NodeIndex(None), parameter: Parameter { range: 61..67, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 61..64, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("x"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 71..74, node_index: NodeIndex(None), parameter: Parameter { range: 71..74, node_index: NodeIndex(None), name: Identifier { id: Name("int"), range: 71..74, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 77..80, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 77..80, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(arg: *int): ... | ^^^^ Syntax Error: Starred expression cannot be used here 2 | def foo(arg: yield int): ... 3 | def foo(arg: x := int): ... | | 1 | def foo(arg: *int): ... 2 | def foo(arg: yield int): ... | ^^^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | def foo(arg: x := int): ... | | 1 | def foo(arg: *int): ... 2 | def foo(arg: yield int): ... 3 | def foo(arg: x := int): ... | ^^ Syntax Error: Expected `,`, found `:=` ## Semantic Syntax Errors | 1 | def foo(arg: *int): ... 2 | def foo(arg: yield int): ... | ^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 3 | def foo(arg: x := int): ... | invalid_syntax@param_with_invalid_default.py.snap000064400000000000000000000241251046102023000336110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_with_invalid_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..68, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..20, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..15, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..14, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 10..14, value: Name( ExprName { node_index: NodeIndex(None), range: 11..14, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 21..43, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 25..28, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 28..38, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 29..37, node_index: NodeIndex(None), parameter: Parameter { range: 29..30, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 29..30, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 32..36, value: Name( ExprName { node_index: NodeIndex(None), range: 33..36, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 40..43, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 40..43, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..67, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 51..62, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 52..61, node_index: NodeIndex(None), parameter: Parameter { range: 52..53, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 52..53, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 54..61, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("y"), ctx: Load, }, ), ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 64..67, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 64..67, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(x=*int): ... | ^^^^ Syntax Error: Starred expression cannot be used here 2 | def foo(x=(*int)): ... 3 | def foo(x=yield y): ... | | 1 | def foo(x=*int): ... 2 | def foo(x=(*int)): ... | ^^^^ Syntax Error: Starred expression cannot be used here 3 | def foo(x=yield y): ... | | 1 | def foo(x=*int): ... 2 | def foo(x=(*int)): ... 3 | def foo(x=yield y): ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@param_with_invalid_star_annotation.py.snap000064400000000000000000000367571046102023000354060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_with_invalid_star_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..150, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..22, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..17, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 8..16, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 9..13, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 15..16, value: Name( ExprName { node_index: NodeIndex(None), range: 16..16, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..57, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 27..30, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 30..52, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 31..51, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 32..36, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 39..50, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 40..50, value: Name( ExprName { node_index: NodeIndex(None), range: 40..45, id: Name("tuple"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 46..49, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 54..57, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 54..57, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 58..90, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 62..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..85, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 66..84, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 67..71, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 73..84, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 74..84, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 74..77, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 81..84, id: Name("str"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 87..90, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 87..90, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 91..120, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 95..98, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 98..115, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 99..114, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 100..104, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 106..114, value: Yield( ExprYield { node_index: NodeIndex(None), range: 107..114, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 117..120, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 117..120, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(*args: *): ... | ^ Syntax Error: Expected an expression 2 | def foo(*args: (*tuple[int])): ... 3 | def foo(*args: *int or str): ... | | 1 | def foo(*args: *): ... 2 | def foo(*args: (*tuple[int])): ... | ^^^^^^^^^^^ Syntax Error: Starred expression cannot be used here 3 | def foo(*args: *int or str): ... 4 | def foo(*args: *yield x): ... | | 1 | def foo(*args: *): ... 2 | def foo(*args: (*tuple[int])): ... 3 | def foo(*args: *int or str): ... | ^^^^^^^^^^ Syntax Error: Boolean expression cannot be used here 4 | def foo(*args: *yield x): ... 5 | # def foo(*args: **int): ... | | 2 | def foo(*args: (*tuple[int])): ... 3 | def foo(*args: *int or str): ... 4 | def foo(*args: *yield x): ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | # def foo(*args: **int): ... | ## Semantic Syntax Errors | 2 | def foo(*args: (*tuple[int])): ... 3 | def foo(*args: *int or str): ... 4 | def foo(*args: *yield x): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation 5 | # def foo(*args: **int): ... | invalid_syntax@param_with_star_annotation_py310.py.snap000064400000000000000000000065011046102023000346140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/param_with_star_annotation_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..69, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..68, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 51..63, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 52..62, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 53..57, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 59..62, value: Name( ExprName { node_index: NodeIndex(None), range: 60..62, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 65..68, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 65..68, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.10"} 2 | def foo(*args: *Ts): ... | ^^^ Syntax Error: Cannot use star annotation on Python 3.10 (syntax was added in Python 3.11) invalid_syntax@params_duplicate_names.py.snap000064400000000000000000000165271046102023000327530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_duplicate_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..42, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..41, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..36, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 11..15, node_index: NodeIndex(None), parameter: Parameter { range: 11..12, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 11..12, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..15, value: Int( 10, ), }, ), ), }, ], vararg: Some( Parameter { range: 17..19, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 18..19, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 21..22, node_index: NodeIndex(None), parameter: Parameter { range: 21..22, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 21..22, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 24..30, node_index: NodeIndex(None), parameter: Parameter { range: 24..30, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 24..25, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..30, id: Name("str"), ctx: Load, }, ), ), }, default: None, }, ], kwarg: Some( Parameter { range: 32..35, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 34..35, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 38..41, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 38..41, }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | def foo(a, a=10, *a, a, a: str, **a): ... | ^ Syntax Error: Duplicate parameter "a" | 1 | def foo(a, a=10, *a, a, a: str, **a): ... | ^ Syntax Error: Duplicate parameter "a" | 1 | def foo(a, a=10, *a, a, a: str, **a): ... | ^ Syntax Error: Duplicate parameter "a" | 1 | def foo(a, a=10, *a, a, a: str, **a): ... | ^ Syntax Error: Duplicate parameter "a" | 1 | def foo(a, a=10, *a, a, a: str, **a): ... | ^ Syntax Error: Duplicate parameter "a" invalid_syntax@params_expected_after_star_separator.py.snap000064400000000000000000000247141046102023000357060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_expected_after_star_separator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..98, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..15, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..10, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 12..15, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 12..15, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 16..32, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 20..23, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 23..27, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 33..51, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 37..40, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 40..46, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 41..42, node_index: NodeIndex(None), parameter: Parameter { range: 41..42, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 41..42, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 48..51, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 48..51, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 52..71, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 56..59, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 59..66, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 60..61, node_index: NodeIndex(None), parameter: Parameter { range: 60..61, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 60..61, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 68..71, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 68..71, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 72..97, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 76..79, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 79..92, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 83..91, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 85..91, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 94..97, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 94..97, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(*): ... | ^ Syntax Error: Expected one or more keyword parameter after `*` separator 2 | def foo(*,): ... 3 | def foo(a, *): ... | | 1 | def foo(*): ... 2 | def foo(*,): ... | ^ Syntax Error: Expected one or more keyword parameter after `*` separator 3 | def foo(a, *): ... 4 | def foo(a, *,): ... | | 1 | def foo(*): ... 2 | def foo(*,): ... 3 | def foo(a, *): ... | ^ Syntax Error: Expected one or more keyword parameter after `*` separator 4 | def foo(a, *,): ... 5 | def foo(*, **kwargs): ... | | 2 | def foo(*,): ... 3 | def foo(a, *): ... 4 | def foo(a, *,): ... | ^ Syntax Error: Expected one or more keyword parameter after `*` separator 5 | def foo(*, **kwargs): ... | | 3 | def foo(a, *): ... 4 | def foo(a, *,): ... 5 | def foo(*, **kwargs): ... | ^^^^^^^^ Syntax Error: Expected one or more keyword parameter after `*` separator invalid_syntax@params_follows_var_keyword_param.py.snap000064400000000000000000000127731046102023000350760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_follows_var_keyword_param.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..45, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..44, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..39, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 18..19, node_index: NodeIndex(None), parameter: Parameter { range: 18..19, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 18..19, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 24..28, node_index: NodeIndex(None), parameter: Parameter { range: 24..25, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 24..25, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..28, value: Int( 10, ), }, ), ), }, ], vararg: Some( Parameter { range: 33..38, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 34..38, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 8..16, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 10..16, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 41..44, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 41..44, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(**kwargs, a, /, b=10, *, *args): ... | ^ Syntax Error: Parameter cannot follow var-keyword parameter | 1 | def foo(**kwargs, a, /, b=10, *, *args): ... | ^ Syntax Error: Parameter cannot follow var-keyword parameter | 1 | def foo(**kwargs, a, /, b=10, *, *args): ... | ^ Syntax Error: Parameter cannot follow var-keyword parameter | 1 | def foo(**kwargs, a, /, b=10, *, *args): ... | ^ Syntax Error: Parameter cannot follow var-keyword parameter | 1 | def foo(**kwargs, a, /, b=10, *, *args): ... | ^ Syntax Error: Parameter cannot follow var-keyword parameter invalid_syntax@params_kwarg_after_star_separator.py.snap000064400000000000000000000045561046102023000352220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_kwarg_after_star_separator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..26, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..25, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..20, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 11..19, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 13..19, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 22..25, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 22..25, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(*, **kwargs): ... | ^^^^^^^^ Syntax Error: Expected one or more keyword parameter after `*` separator invalid_syntax@params_multiple_kwargs.py.snap000064400000000000000000000061751046102023000330250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_multiple_kwargs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..38, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..37, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..32, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 22..31, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs2"), range: 24..31, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 34..37, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 34..37, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a, **kwargs1, **kwargs2): ... | ^^ Syntax Error: Parameter cannot follow var-keyword parameter invalid_syntax@params_multiple_slash_separator.py.snap000064400000000000000000000164361046102023000347220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_multiple_slash_separator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..24, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..19, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 17..18, node_index: NodeIndex(None), parameter: Parameter { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 17..18, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 25..52, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 29..32, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 32..47, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 33..34, node_index: NodeIndex(None), parameter: Parameter { range: 33..34, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 33..34, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 39..40, node_index: NodeIndex(None), parameter: Parameter { range: 39..40, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 39..40, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 42..43, node_index: NodeIndex(None), parameter: Parameter { range: 42..43, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 42..43, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a, /, /, b): ... | ^ Syntax Error: Only one '/' separator allowed 2 | def foo(a, /, b, c, /): ... | | 1 | def foo(a, /, /, b): ... 2 | def foo(a, /, b, c, /): ... | ^ Syntax Error: Only one '/' separator allowed invalid_syntax@params_multiple_star_separator.py.snap000064400000000000000000000164351046102023000345600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_multiple_star_separator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..24, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..19, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 17..18, node_index: NodeIndex(None), parameter: Parameter { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 17..18, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 25..52, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 29..32, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 32..47, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 33..34, node_index: NodeIndex(None), parameter: Parameter { range: 33..34, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 33..34, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 39..40, node_index: NodeIndex(None), parameter: Parameter { range: 39..40, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 39..40, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 42..43, node_index: NodeIndex(None), parameter: Parameter { range: 42..43, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 42..43, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a, *, *, b): ... | ^ Syntax Error: Only one '*' separator allowed 2 | def foo(a, *, b, c, *): ... | | 1 | def foo(a, *, *, b): ... 2 | def foo(a, *, b, c, *): ... | ^ Syntax Error: Only one '*' separator allowed invalid_syntax@params_multiple_varargs.py.snap000064400000000000000000000302231046102023000331630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_multiple_varargs.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..136, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..28, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..23, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 14..19, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 15..19, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 21..22, node_index: NodeIndex(None), parameter: Parameter { range: 21..22, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 21..22, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 63..97, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 67..70, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 70..92, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 71..72, node_index: NodeIndex(None), parameter: Parameter { range: 71..72, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 71..72, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 74..80, node_index: NodeIndex(None), name: Identifier { id: Name("args1"), range: 75..80, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 90..91, node_index: NodeIndex(None), parameter: Parameter { range: 90..91, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 90..91, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 94..97, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 94..97, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 98..135, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 102..105, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 105..130, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 106..107, node_index: NodeIndex(None), parameter: Parameter { range: 106..107, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 106..107, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 109..115, node_index: NodeIndex(None), name: Identifier { id: Name("args1"), range: 110..115, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 117..118, node_index: NodeIndex(None), parameter: Parameter { range: 117..118, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 117..118, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 120..121, node_index: NodeIndex(None), parameter: Parameter { range: 120..121, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 120..121, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 132..135, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 132..135, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a, *, *args, b): ... | ^^^^^ Syntax Error: Only one '*' parameter allowed 2 | # def foo(a, *, b, c, *args): ... 3 | def foo(a, *args1, *args2, b): ... | | 1 | def foo(a, *, *args, b): ... 2 | # def foo(a, *, b, c, *args): ... 3 | def foo(a, *args1, *args2, b): ... | ^^^^^^ Syntax Error: Only one '*' parameter allowed 4 | def foo(a, *args1, b, c, *args2): ... | | 2 | # def foo(a, *, b, c, *args): ... 3 | def foo(a, *args1, *args2, b): ... 4 | def foo(a, *args1, b, c, *args2): ... | ^^^^^^ Syntax Error: Only one '*' parameter allowed invalid_syntax@params_no_arg_before_slash.py.snap000064400000000000000000000103321046102023000335630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_no_arg_before_slash.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..35, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..15, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..10, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 12..15, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 12..15, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 16..34, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 20..23, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 23..29, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 27..28, node_index: NodeIndex(None), parameter: Parameter { range: 27..28, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 27..28, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 31..34, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 31..34, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(/): ... | ^ Syntax Error: Position-only parameter separator not allowed as first parameter 2 | def foo(/, a): ... | | 1 | def foo(/): ... 2 | def foo(/, a): ... | ^ Syntax Error: Position-only parameter separator not allowed as first parameter invalid_syntax@params_non_default_after_default.py.snap000064400000000000000000000124271046102023000347740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_non_default_after_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..29, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..24, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..12, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..12, value: Int( 10, ), }, ), ), }, ParameterWithDefault { range: 14..15, node_index: NodeIndex(None), parameter: Parameter { range: 14..15, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 14..15, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 17..23, node_index: NodeIndex(None), parameter: Parameter { range: 17..23, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 17..18, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 20..23, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 26..29, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a=10, b, c: int): ... | ^ Syntax Error: Parameter without a default cannot follow a parameter with a default | 1 | def foo(a=10, b, c: int): ... | ^^^^^^ Syntax Error: Parameter without a default cannot follow a parameter with a default invalid_syntax@params_star_after_slash.py.snap000064400000000000000000000337351046102023000331420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_star_after_slash.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..105, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..19, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..14, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 8..10, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 9..10, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 16..19, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 16..19, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 20..48, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 24..27, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 27..43, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 28..29, node_index: NodeIndex(None), parameter: Parameter { range: 28..29, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 28..29, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: Some( Parameter { range: 31..36, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 32..36, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 38..39, node_index: NodeIndex(None), parameter: Parameter { range: 38..39, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 38..39, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 45..48, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 45..48, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 49..73, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 53..56, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 56..68, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 57..58, node_index: NodeIndex(None), parameter: Parameter { range: 57..58, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 57..58, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 66..67, node_index: NodeIndex(None), parameter: Parameter { range: 66..67, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 66..67, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 70..73, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 70..73, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 74..104, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 78..81, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 81..99, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 82..83, node_index: NodeIndex(None), parameter: Parameter { range: 82..83, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 82..83, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 88..89, node_index: NodeIndex(None), parameter: Parameter { range: 88..89, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 88..89, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 91..92, node_index: NodeIndex(None), parameter: Parameter { range: 91..92, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 91..92, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 97..98, node_index: NodeIndex(None), parameter: Parameter { range: 97..98, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 97..98, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 101..104, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 101..104, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(*a, /): ... | ^ Syntax Error: '/' parameter must appear before '*' parameter 2 | def foo(a, *args, b, /): ... 3 | def foo(a, *, /, b): ... | | 1 | def foo(*a, /): ... 2 | def foo(a, *args, b, /): ... | ^ Syntax Error: '/' parameter must appear before '*' parameter 3 | def foo(a, *, /, b): ... 4 | def foo(a, *, b, c, /, d): ... | | 1 | def foo(*a, /): ... 2 | def foo(a, *args, b, /): ... 3 | def foo(a, *, /, b): ... | ^ Syntax Error: '/' parameter must appear before '*' parameter 4 | def foo(a, *, b, c, /, d): ... | | 2 | def foo(a, *args, b, /): ... 3 | def foo(a, *, /, b): ... 4 | def foo(a, *, b, c, /, d): ... | ^ Syntax Error: '/' parameter must appear before '*' parameter invalid_syntax@params_star_separator_after_star_param.py.snap000064400000000000000000000206011046102023000362250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_star_separator_after_star_param.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..61, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..28, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..23, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 11..16, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 12..16, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 21..22, node_index: NodeIndex(None), parameter: Parameter { range: 21..22, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 21..22, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 29..60, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 33..36, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 36..55, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 37..38, node_index: NodeIndex(None), parameter: Parameter { range: 37..38, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 37..38, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 40..45, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 41..45, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 47..48, node_index: NodeIndex(None), parameter: Parameter { range: 47..48, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 47..48, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 50..51, node_index: NodeIndex(None), parameter: Parameter { range: 50..51, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 50..51, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def foo(a, *args, *, b): ... | ^ Syntax Error: Keyword-only parameter separator not allowed after '*' parameter 2 | def foo(a, *args, b, c, *): ... | | 1 | def foo(a, *args, *, b): ... 2 | def foo(a, *args, b, c, *): ... | ^ Syntax Error: Keyword-only parameter separator not allowed after '*' parameter invalid_syntax@params_var_keyword_with_default.py.snap000064400000000000000000000215711046102023000347040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_var_keyword_with_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..43, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..36, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..20, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 11..19, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 13..19, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..36, value: Dict( ExprDict { node_index: NodeIndex(None), range: 20..36, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 21..24, value: StringLiteralValue { inner: Single( StringLiteral { range: 21..24, node_index: NodeIndex(None), value: "b", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..27, value: Int( 1, ), }, ), }, DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 29..32, value: StringLiteralValue { inner: Single( StringLiteral { range: 29..32, node_index: NodeIndex(None), value: "c", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 34..35, value: Int( 2, ), }, ), }, ], }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 39..42, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 39..42, }, ), }, ), ], }, ) ``` ## Errors | 1 | def foo(a, **kwargs={'b': 1, 'c': 2}): ... | ^ Syntax Error: Parameter with `*` or `**` cannot have default value | 1 | def foo(a, **kwargs={'b': 1, 'c': 2}): ... | ^ Syntax Error: Expected `)`, found `{` | 1 | def foo(a, **kwargs={'b': 1, 'c': 2}): ... | ^ Syntax Error: Expected newline, found `)` | 1 | def foo(a, **kwargs={'b': 1, 'c': 2}): ... | ^ Syntax Error: Expected a statement invalid_syntax@params_var_positional_with_default.py.snap000064400000000000000000000121231046102023000353720ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/params_var_positional_with_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..23, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..17, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..9, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 11..16, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 12..16, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..23, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 17..23, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 26..29, }, ), }, ), ], }, ) ``` ## Errors | 1 | def foo(a, *args=(1, 2)): ... | ^ Syntax Error: Parameter with `*` or `**` cannot have default value | 1 | def foo(a, *args=(1, 2)): ... | ^ Syntax Error: Expected `)`, found `(` | 1 | def foo(a, *args=(1, 2)): ... | ^ Syntax Error: Expected newline, found `)` | 1 | def foo(a, *args=(1, 2)): ... | ^ Syntax Error: Expected a statement invalid_syntax@parenthesized_context_manager_py38.py.snap000064400000000000000000000212131046102023000352250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/parenthesized_context_manager_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..126, body: [ With( StmtWith { node_index: NodeIndex(None), range: 43..73, is_async: false, items: [ WithItem { range: 49..57, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 49..52, id: Name("foo"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Store, }, ), ), }, WithItem { range: 59..67, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 59..62, id: Name("bar"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 70..73, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 70..73, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 74..99, is_async: false, items: [ WithItem { range: 80..83, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 80..83, id: Name("foo"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 85..93, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 85..88, id: Name("bar"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 100..125, is_async: false, items: [ WithItem { range: 106..114, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 106..109, id: Name("foo"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("x"), ctx: Store, }, ), ), }, WithItem { range: 116..119, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 116..119, id: Name("bar"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 122..125, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 122..125, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | with (foo as x, bar as y): ... | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) 3 | with (foo, bar as y): ... 4 | with (foo as x, bar): ... | | 1 | # parse_options: {"target-version": "3.8"} 2 | with (foo as x, bar as y): ... 3 | with (foo, bar as y): ... | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) 4 | with (foo as x, bar): ... | | 2 | with (foo as x, bar as y): ... 3 | with (foo, bar as y): ... 4 | with (foo as x, bar): ... | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@parenthesized_kwarg_py38.py.snap000064400000000000000000000165041046102023000331710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/parenthesized_kwarg_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..77, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..51, value: Call( ExprCall { node_index: NodeIndex(None), range: 43..51, func: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 44..51, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 45..50, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 46..47, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 52..62, value: Call( ExprCall { node_index: NodeIndex(None), range: 52..62, func: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 53..62, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 54..61, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 55..56, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 60..61, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 63..76, value: Call( ExprCall { node_index: NodeIndex(None), range: 63..76, func: Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 64..76, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 66..75, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 68..69, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 74..75, value: Int( 1, ), }, ), }, ], }, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | f((a)=1) | ^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8) 3 | f((a) = 1) 4 | f( ( a ) = 1) | | 1 | # parse_options: {"target-version": "3.8"} 2 | f((a)=1) 3 | f((a) = 1) | ^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8) 4 | f( ( a ) = 1) | | 2 | f((a)=1) 3 | f((a) = 1) 4 | f( ( a ) = 1) | ^^^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8) invalid_syntax@pep701_f_string_py311.py.snap000064400000000000000000002674601046102023000321230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/pep701_f_string_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..562, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..74, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..74, value: FStringValue { inner: Single( FString( FString { range: 44..74, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 46..58, node_index: NodeIndex(None), value: "Magic wand: ", }, ), Interpolation( InterpolatedElement { range: 58..73, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 60..71, value: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 64..70, value: StringLiteralValue { inner: Single( StringLiteral { range: 64..70, node_index: NodeIndex(None), value: "wand", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..112, value: FString( ExprFString { node_index: NodeIndex(None), range: 95..112, value: FStringValue { inner: Single( FString( FString { range: 95..112, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 97..111, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 98..110, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 98..107, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 98..102, value: StringLiteralValue { inner: Single( StringLiteral { range: 98..102, node_index: NodeIndex(None), value: "\n", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("join"), range: 103..107, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 107..110, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("a"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..220, value: FString( ExprFString { node_index: NodeIndex(None), range: 148..220, value: FStringValue { inner: Single( FString( FString { range: 148..220, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 152..169, node_index: NodeIndex(None), value: "A complex trick: ", }, ), Interpolation( InterpolatedElement { range: 169..217, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 175..185, value: Name( ExprName { node_index: NodeIndex(None), range: 175..178, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 179..184, value: StringLiteralValue { inner: Single( StringLiteral { range: 179..184, node_index: NodeIndex(None), value: "bag", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 221..254, value: FString( ExprFString { node_index: NodeIndex(None), range: 221..254, value: FStringValue { inner: Single( FString( FString { range: 221..254, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 223..253, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 224..252, value: FStringValue { inner: Single( FString( FString { range: 224..252, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 226..251, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 227..250, value: FStringValue { inner: Single( FString( FString { range: 227..250, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 229..249, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 230..248, value: FStringValue { inner: Single( FString( FString { range: 230..248, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 232..247, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 233..246, value: FStringValue { inner: Single( FString( FString { range: 233..246, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 235..245, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 236..244, value: FStringValue { inner: Single( FString( FString { range: 236..244, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 238..243, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 239..242, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..240, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 1, ), }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 276..310, value: FString( ExprFString { node_index: NodeIndex(None), range: 276..310, value: FStringValue { inner: Single( FString( FString { range: 276..310, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 278..303, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 279..302, value: FStringValue { inner: Single( FString( FString { range: 279..302, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 283..293, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 284..292, value: StringLiteralValue { inner: Single( StringLiteral { range: 284..292, node_index: NodeIndex(None), value: "nested", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 293..299, node_index: NodeIndex(None), value: " inner", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 303..309, node_index: NodeIndex(None), value: " outer", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 336..348, value: FString( ExprFString { node_index: NodeIndex(None), range: 336..348, value: FStringValue { inner: Single( FString( FString { range: 336..348, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 338..347, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 344..345, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 349..372, value: FString( ExprFString { node_index: NodeIndex(None), range: 349..372, value: FStringValue { inner: Single( FString( FString { range: 349..372, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 351..356, node_index: NodeIndex(None), value: "test ", }, ), Interpolation( InterpolatedElement { range: 356..366, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 357..358, id: Name("a"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 366..371, node_index: NodeIndex(None), value: " more", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 416..435, value: FString( ExprFString { node_index: NodeIndex(None), range: 416..435, value: FStringValue { inner: Single( FString( FString { range: 416..435, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 420..432, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 421..431, value: FStringValue { inner: Single( FString( FString { range: 421..431, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 425..428, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 426..427, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 481..515, value: FString( ExprFString { node_index: NodeIndex(None), range: 481..515, value: FStringValue { inner: Single( FString( FString { range: 481..515, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 483..514, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 484..513, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 484..493, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 484..488, value: StringLiteralValue { inner: Single( StringLiteral { range: 484..488, node_index: NodeIndex(None), value: "\n", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("join"), range: 489..493, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 493..513, node_index: NodeIndex(None), args: [ List( ExprList { node_index: NodeIndex(None), range: 494..512, elts: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 495..499, value: StringLiteralValue { inner: Single( StringLiteral { range: 495..499, node_index: NodeIndex(None), value: "\t", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 501..505, value: StringLiteralValue { inner: Single( StringLiteral { range: 501..505, node_index: NodeIndex(None), value: "\u{b}", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 507..511, value: StringLiteralValue { inner: Single( StringLiteral { range: 507..511, node_index: NodeIndex(None), value: "\r", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | f'Magic wand: { bag['wand'] }' # nested quotes | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 3 | f"{'\n'.join(a)}" # escape sequence 4 | f'''A complex trick: { | | 1 | # parse_options: {"target-version": "3.11"} 2 | f'Magic wand: { bag['wand'] }' # nested quotes 3 | f"{'\n'.join(a)}" # escape sequence | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) 4 | f'''A complex trick: { 5 | bag['bag'] # comment | | 3 | f"{'\n'.join(a)}" # escape sequence 4 | f'''A complex trick: { 5 | bag['bag'] # comment | ^^^^^^^^^ Syntax Error: Cannot use comments in f-strings on Python 3.11 (syntax was added in Python 3.12) 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | | 5 | bag['bag'] # comment 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | | 5 | bag['bag'] # comment 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | | 5 | bag['bag'] # comment 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | | 5 | bag['bag'] # comment 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | | 5 | bag['bag'] # comment 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | | 6 | }''' 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 9 | f"{ 10 | 1 | | 7 | f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # arbitrary nesting 8 | f"{f'''{"nested"} inner'''} outer" # nested (triple) quotes 9 | f"{ | ^ Syntax Error: Cannot use line breaks in non-triple-quoted f-string replacement fields on Python 3.11 (syntax was added in Python 3.12) 10 | 1 11 | }" | | 10 | 1 11 | }" 12 | f"test {a \ | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote | | 12 | f"test {a \ 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote | ^^^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 15 | f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors | | 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote 15 | f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) | 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote 15 | f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) | 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote 15 | f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) | 13 | } more" # line continuation 14 | f"""{f"""{x}"""}""" # mark the whole triple quote 15 | f"{'\n'.join(['\t', '\v', '\r'])}" # multiple escape sequences, multiple errors | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) invalid_syntax@pep701_nested_interpolation_py311.py.snap000064400000000000000000000365741046102023000345410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/pep701_nested_interpolation_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..138, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 92..114, value: FString( ExprFString { node_index: NodeIndex(None), range: 92..114, value: FStringValue { inner: Single( FString( FString { range: 92..114, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 94..113, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 95..96, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 97..112, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 97..104, node_index: NodeIndex(None), value: " abcd \"", }, ), Interpolation( InterpolatedElement { range: 104..110, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 105..109, value: StringLiteralValue { inner: Single( StringLiteral { range: 105..109, node_index: NodeIndex(None), value: "aa", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 110..112, node_index: NodeIndex(None), value: "\" ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 115..137, value: FString( ExprFString { node_index: NodeIndex(None), range: 115..137, value: FStringValue { inner: Single( FString( FString { range: 115..137, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 117..136, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 120..135, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 120..127, node_index: NodeIndex(None), value: " abcd \"", }, ), Interpolation( InterpolatedElement { range: 127..133, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 128..132, value: StringLiteralValue { inner: Single( StringLiteral { range: 128..132, node_index: NodeIndex(None), value: "\n", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 133..135, node_index: NodeIndex(None), value: "\" ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | # nested interpolations also need to be checked 3 | f'{1: abcd "{'aa'}" }' | ^ Syntax Error: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12) 4 | f'{1: abcd "{"\n"}" }' | | 2 | # nested interpolations also need to be checked 3 | f'{1: abcd "{'aa'}" }' 4 | f'{1: abcd "{"\n"}" }' | ^ Syntax Error: Cannot use an escape sequence (backslash) in f-strings on Python 3.11 (syntax was added in Python 3.12) invalid_syntax@pep_798_invalid_dict_unpacking_comprehensions_py315.py.snap000064400000000000000000000376611046102023000402750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/pep_798_invalid_dict_unpacking_comprehensions_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..150, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..69, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 44..69, key: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 45..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("k"), ctx: Load, }, ), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("v"), ctx: Load, }, ), generators: [ Comprehension { range: 51..68, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 55..59, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("k"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("v"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 63..68, id: Name("items"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 70..95, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 70..95, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("k"), ctx: Load, }, ), ), value: Starred( ExprStarred { node_index: NodeIndex(None), range: 74..76, value: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("v"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 77..94, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 81..85, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("k"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 84..85, id: Name("v"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 89..94, id: Name("items"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 96..122, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 96..122, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("k"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("v"), ctx: Load, }, ), generators: [ Comprehension { range: 104..121, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 108..112, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("k"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("v"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 116..121, id: Name("items"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 123..149, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 123..149, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 124..125, id: Name("k"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("v"), ctx: Load, }, ), generators: [ Comprehension { range: 131..148, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 135..139, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("k"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 138..139, id: Name("v"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 143..148, id: Name("items"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.15"} 2 | {*k: v for k, v in items} | ^^ Syntax Error: Starred expression cannot be used here 3 | {k: *v for k, v in items} 4 | {**k: v for k, v in items} | | 1 | # parse_options: {"target-version": "3.15"} 2 | {*k: v for k, v in items} 3 | {k: *v for k, v in items} | ^^ Syntax Error: Starred expression cannot be used here 4 | {**k: v for k, v in items} 5 | {k: **v for k, v in items} | | 2 | {*k: v for k, v in items} 3 | {k: *v for k, v in items} 4 | {**k: v for k, v in items} | ^^^ Syntax Error: Starred expression cannot be used here 5 | {k: **v for k, v in items} | | 3 | {k: *v for k, v in items} 4 | {**k: v for k, v in items} 5 | {k: **v for k, v in items} | ^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@pep_798_unpacking_comprehensions_py314.py.snap000064400000000000000000000345531046102023000355600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/pep_798_unpacking_comprehensions_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..126, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..59, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 44..59, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 45..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 48..58, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..75, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 60..75, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 61..63, value: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 64..74, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..92, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 76..92, key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 81..91, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 85..86, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..108, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 93..108, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 97..107, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 109..125, value: Call( ExprCall { node_index: NodeIndex(None), range: 109..125, func: Name( ExprName { node_index: NodeIndex(None), range: 109..110, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 110..125, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 111..124, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 111..113, value: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 114..124, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 123..124, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | [*x for x in y] | ^^ Syntax Error: Cannot use iterable unpacking in a list comprehension on Python 3.14 (syntax was added in Python 3.15) 3 | {*x for x in y} 4 | {**x for x in y} | | 1 | # parse_options: {"target-version": "3.14"} 2 | [*x for x in y] 3 | {*x for x in y} | ^^ Syntax Error: Cannot use iterable unpacking in a set comprehension on Python 3.14 (syntax was added in Python 3.15) 4 | {**x for x in y} 5 | (*x for x in y) | | 2 | [*x for x in y] 3 | {*x for x in y} 4 | {**x for x in y} | ^^^ Syntax Error: Cannot use dictionary unpacking in a dict comprehension on Python 3.14 (syntax was added in Python 3.15) 5 | (*x for x in y) 6 | f(*x for x in y) | | 3 | {*x for x in y} 4 | {**x for x in y} 5 | (*x for x in y) | ^^ Syntax Error: Cannot use iterable unpacking in a generator expression on Python 3.14 (syntax was added in Python 3.15) 6 | f(*x for x in y) | | 4 | {**x for x in y} 5 | (*x for x in y) 6 | f(*x for x in y) | ^^ Syntax Error: Cannot use iterable unpacking in a generator expression on Python 3.14 (syntax was added in Python 3.15) ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/invalid_syntax@pos_only_py37.py.snap000064400000000000000000000311471046102023000310510ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/pos_only_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..136, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 43..61, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 47..50, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 50..56, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 51..52, node_index: NodeIndex(None), parameter: Parameter { range: 51..52, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 51..52, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 62..86, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 66..69, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 69..81, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 70..71, node_index: NodeIndex(None), parameter: Parameter { range: 70..71, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 70..71, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 76..77, node_index: NodeIndex(None), parameter: Parameter { range: 76..77, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 76..77, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..86, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 83..86, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 87..115, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 91..94, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 94..110, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 95..96, node_index: NodeIndex(None), parameter: Parameter { range: 95..96, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 95..96, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: Some( Parameter { range: 98..103, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 99..103, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 108..109, node_index: NodeIndex(None), parameter: Parameter { range: 108..109, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 108..109, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 112..115, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 112..115, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 116..135, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 120..123, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 123..130, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 124..125, node_index: NodeIndex(None), parameter: Parameter { range: 124..125, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 124..125, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 132..135, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 132..135, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.7"} 2 | def foo(a, /): ... 3 | def foo(a, /, b, /): ... | ^ Syntax Error: Only one '/' separator allowed 4 | def foo(a, *args, /, b): ... 5 | def foo(a, //): ... | | 2 | def foo(a, /): ... 3 | def foo(a, /, b, /): ... 4 | def foo(a, *args, /, b): ... | ^ Syntax Error: '/' parameter must appear before '*' parameter 5 | def foo(a, //): ... | | 3 | def foo(a, /, b, /): ... 4 | def foo(a, *args, /, b): ... 5 | def foo(a, //): ... | ^^ Syntax Error: Expected `,`, found `//` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.7"} 2 | def foo(a, /): ... | ^ Syntax Error: Cannot use positional-only parameter separator on Python 3.7 (syntax was added in Python 3.8) 3 | def foo(a, /, b, /): ... 4 | def foo(a, *args, /, b): ... | | 1 | # parse_options: {"target-version": "3.7"} 2 | def foo(a, /): ... 3 | def foo(a, /, b, /): ... | ^ Syntax Error: Cannot use positional-only parameter separator on Python 3.7 (syntax was added in Python 3.8) 4 | def foo(a, *args, /, b): ... 5 | def foo(a, //): ... | | 2 | def foo(a, /): ... 3 | def foo(a, /, b, /): ... 4 | def foo(a, *args, /, b): ... | ^ Syntax Error: Cannot use positional-only parameter separator on Python 3.7 (syntax was added in Python 3.8) 5 | def foo(a, //): ... | invalid_syntax@raise_stmt_from_without_exc.py.snap000064400000000000000000000031311046102023000340550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/raise_stmt_from_without_exc.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 0..14, exc: None, cause: Some( Name( ExprName { node_index: NodeIndex(None), range: 11..14, id: Name("exc"), ctx: Load, }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 15..30, exc: None, cause: Some( NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 26..30, }, ), ), }, ), ], }, ) ``` ## Errors | 1 | raise from exc | ^^^^ Syntax Error: Exception missing in `raise` statement with cause 2 | raise from None | | 1 | raise from exc 2 | raise from None | ^^^^ Syntax Error: Exception missing in `raise` statement with cause invalid_syntax@raise_stmt_invalid_cause.py.snap000064400000000000000000000112471046102023000333050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/raise_stmt_invalid_cause.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 0..15, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), ), cause: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..15, value: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 16..36, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), ), cause: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 29..36, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("y"), ctx: Load, }, ), ), }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 37..51, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("x"), ctx: Load, }, ), ), cause: Some( Name( ExprName { node_index: NodeIndex(None), range: 50..51, id: Name("y"), ctx: Load, }, ), ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 55..56, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | raise x from *y | ^^ Syntax Error: Starred expression cannot be used here 2 | raise x from yield y 3 | raise x from y := 1 | | 1 | raise x from *y 2 | raise x from yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | raise x from y := 1 | | 1 | raise x from *y 2 | raise x from yield y 3 | raise x from y := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@raise_stmt_invalid_exc.py.snap000064400000000000000000000070711046102023000327640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/raise_stmt_invalid_exc.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 0..8, exc: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 6..8, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 9..22, exc: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 15..22, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("x"), ctx: Load, }, ), ), }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 23..30, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), ), cause: None, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..35, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 34..35, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | raise *x | ^^ Syntax Error: Starred expression cannot be used here 2 | raise yield x 3 | raise x := 1 | | 1 | raise *x 2 | raise yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | raise x := 1 | | 1 | raise *x 2 | raise yield x 3 | raise x := 1 | ^^ Syntax Error: Expected a statement invalid_syntax@raise_stmt_unparenthesized_tuple_cause.py.snap000064400000000000000000000074231046102023000363010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/raise_stmt_unparenthesized_tuple_cause.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..34, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 0..15, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), ), cause: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 13..15, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 16..33, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), ), cause: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 29..33, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), ], }, ) ``` ## Errors | 1 | raise x from y, | ^^ Syntax Error: Unparenthesized tuple expression cannot be used here 2 | raise x from y, z | | 1 | raise x from y, 2 | raise x from y, z | ^^^^ Syntax Error: Unparenthesized tuple expression cannot be used here invalid_syntax@raise_stmt_unparenthesized_tuple_exc.py.snap000064400000000000000000000120401046102023000357470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/raise_stmt_unparenthesized_tuple_exc.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..38, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 0..8, exc: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 6..8, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 9..19, exc: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 15..19, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 20..37, exc: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 26..30, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), cause: Some( Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("z"), ctx: Load, }, ), ), }, ), ], }, ) ``` ## Errors | 1 | raise x, | ^^ Syntax Error: Unparenthesized tuple expression cannot be used here 2 | raise x, y 3 | raise x, y from z | | 1 | raise x, 2 | raise x, y | ^^^^ Syntax Error: Unparenthesized tuple expression cannot be used here 3 | raise x, y from z | | 1 | raise x, 2 | raise x, y 3 | raise x, y from z | ^^^^ Syntax Error: Unparenthesized tuple expression cannot be used here invalid_syntax@re_lex_logical_token.py.snap000064400000000000000000001166221046102023000324200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lex_logical_token.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..979, body: [ If( StmtIf { node_index: NodeIndex(None), range: 48..59, test: Call( ExprCall { node_index: NodeIndex(None), range: 51..59, func: Name( ExprName { node_index: NodeIndex(None), range: 51..55, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 55..59, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 56..59, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), body: [], elif_else_clauses: [], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..79, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 64..67, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 67..69, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 75..79, }, ), ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 113..152, test: Call( ExprCall { node_index: NodeIndex(None), range: 116..124, func: Name( ExprName { node_index: NodeIndex(None), range: 116..120, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 120..124, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 121..124, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 129..152, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 133..136, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 136..138, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 148..152, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 228..269, test: Call( ExprCall { node_index: NodeIndex(None), range: 231..239, func: Name( ExprName { node_index: NodeIndex(None), range: 231..235, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 235..239, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 236..239, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 246..269, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 250..253, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 253..255, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 265..269, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 344..392, test: Call( ExprCall { node_index: NodeIndex(None), range: 347..355, func: Name( ExprName { node_index: NodeIndex(None), range: 347..351, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 351..355, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 352..355, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 369..392, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 373..376, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 376..378, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 388..392, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 453..499, test: Call( ExprCall { node_index: NodeIndex(None), range: 456..471, func: Name( ExprName { node_index: NodeIndex(None), range: 456..460, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 460..471, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 461..464, id: Name("foo"), ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 466..471, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 467..468, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 470..471, id: Name("b"), ctx: Load, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 476..499, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 480..483, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 483..485, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 495..499, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 564..611, test: Call( ExprCall { node_index: NodeIndex(None), range: 567..583, func: Name( ExprName { node_index: NodeIndex(None), range: 567..571, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 571..583, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 572..575, id: Name("foo"), ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 577..582, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 578..579, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 581..582, id: Name("b"), ctx: Load, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 588..611, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 592..595, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 595..597, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 607..611, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 772..824, test: Call( ExprCall { node_index: NodeIndex(None), range: 775..796, func: Name( ExprName { node_index: NodeIndex(None), range: 775..779, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 779..796, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 780..783, id: Name("foo"), ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 785..794, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 786..787, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 793..794, id: Name("b"), ctx: Load, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 801..824, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 805..808, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 808..810, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 820..824, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 887..933, test: Call( ExprCall { node_index: NodeIndex(None), range: 890..905, func: Name( ExprName { node_index: NodeIndex(None), range: 890..894, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 894..905, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 895..905, value: FStringValue { inner: Single( FString( FString { range: 895..905, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 897..903, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 903..905, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 904..905, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 910..933, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 914..917, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 917..919, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 929..933, }, ), ], }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 936..956, test: Call( ExprCall { node_index: NodeIndex(None), range: 939..956, func: Name( ExprName { node_index: NodeIndex(None), range: 939..943, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 943..956, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 944..951, value: FStringValue { inner: Single( FString( FString { range: 944..951, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 946..951, node_index: NodeIndex(None), value: "hello", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), ], keywords: [], }, }, ), body: [], elif_else_clauses: [], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 956..979, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 960..963, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 963..965, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 975..979, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # No indentation before the function definition 2 | if call(foo | ^ Syntax Error: Expected `)`, found newline 3 | def bar(): 4 | pass | | 1 | # No indentation before the function definition 2 | if call(foo 3 | def bar(): | ^^^ Syntax Error: Expected an indented block after `if` statement 4 | pass | | 7 | # Indented function definition 8 | if call(foo | ^ Syntax Error: Expected `)`, found newline 9 | def bar(): 10 | pass | | 13 | # There are multiple non-logical newlines (blank lines) in the `if` body 14 | if call(foo | ^ Syntax Error: Expected `)`, found newline 15 | 16 | 17 | def bar(): | | 21 | # There are trailing whitespaces in the blank line inside the `if` body 22 | if call(foo | ^ Syntax Error: Expected `)`, found newline 23 | 24 | def bar(): 25 | pass | | 28 | # The lexer is nested with multiple levels of parentheses 29 | if call(foo, [a, b 30 | def bar(): | ^^^ Syntax Error: Expected `]`, found `def` 31 | pass | | 28 | # The lexer is nested with multiple levels of parentheses 29 | if call(foo, [a, b | ^ Syntax Error: Expected `)`, found newline 30 | def bar(): 31 | pass | | 34 | # The outer parenthesis is closed but the inner bracket isn't 35 | if call(foo, [a, b) | ^ Syntax Error: Expected `]`, found `)` 36 | def bar(): 37 | pass | | 34 | # The outer parenthesis is closed but the inner bracket isn't 35 | if call(foo, [a, b) | ^ Syntax Error: Expected `:`, found newline 36 | def bar(): 37 | pass | | 42 | if call(foo, [a, 43 | b 44 | ) | ^ Syntax Error: Expected `]`, found `)` 45 | def bar(): 46 | pass | | 42 | if call(foo, [a, 43 | b 44 | ) | ^ Syntax Error: Expected `:`, found newline 45 | def bar(): 46 | pass | | 49 | # F-strings uses normal list parsing, so test those as well 50 | if call(f"hello {x | ^ Syntax Error: f-string: unterminated string 51 | def bar(): 52 | pass | | 49 | # F-strings uses normal list parsing, so test those as well 50 | if call(f"hello {x 51 | def bar(): | ^^^ Syntax Error: f-string: expecting `}` 52 | pass | | 49 | # F-strings uses normal list parsing, so test those as well 50 | if call(f"hello {x | ^ Syntax Error: Expected `)`, found newline 51 | def bar(): 52 | pass | | 55 | if call(f"hello | ^^^^^ Syntax Error: f-string: unterminated string 56 | def bar(): 57 | pass | | 55 | if call(f"hello | ^ Syntax Error: Expected FStringEnd, found newline 56 | def bar(): 57 | pass | | 55 | if call(f"hello 56 | def bar(): | ^^^^ Syntax Error: Expected `,`, found indent 57 | pass | | 55 | if call(f"hello 56 | def bar(): | ^^^ Syntax Error: Expected `)`, found `def` 57 | pass | | 55 | if call(f"hello 56 | def bar(): 57 | pass | ^ Syntax Error: Expected a statement invalid_syntax@re_lex_logical_token_mac_eol.py.snap000064400000000000000000000120411046102023000340650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lex_logical_token_mac_eol.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..46, test: Call( ExprCall { node_index: NodeIndex(None), range: 3..18, func: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 7..18, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 8..11, id: Name("foo"), ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 13..18, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("b"), ctx: Load, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..46, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 27..30, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 30..32, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 42..46, }, ), ], }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if call(foo, [a, b␍ def bar():␍ pass | ^^^ Syntax Error: Expected `]`, found `def` | 1 | if call(foo, [a, b␍ def bar():␍ pass | ^ Syntax Error: Expected `)`, found newline invalid_syntax@re_lex_logical_token_windows_eol.py.snap000064400000000000000000000120421046102023000350200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lex_logical_token_windows_eol.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..50, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..48, test: Call( ExprCall { node_index: NodeIndex(None), range: 3..18, func: Name( ExprName { node_index: NodeIndex(None), range: 3..7, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 7..18, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 8..11, id: Name("foo"), ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 13..18, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("b"), ctx: Load, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 24..48, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 28..31, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 31..33, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 44..48, }, ), ], }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if call(foo, [a, b 2 | def bar(): | ^^^ Syntax Error: Expected `]`, found `def` 3 | pass | | 1 | if call(foo, [a, b | ^ Syntax Error: Expected `)`, found newline 2 | def bar(): 3 | pass | invalid_syntax@re_lexing__fstring_format_spec_1.py.snap000064400000000000000000000572531046102023000347250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/fstring_format_spec_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..298, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 162..192, value: FString( ExprFString { node_index: NodeIndex(None), range: 162..192, value: FStringValue { inner: Single( FString( FString { range: 162..192, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 164..171, node_index: NodeIndex(None), value: "middle ", }, ), Interpolation( InterpolatedElement { range: 171..191, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 172..180, value: StringLiteralValue { inner: Single( StringLiteral { range: 172..180, node_index: NodeIndex(None), value: "string", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 181..191, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 181..191, node_index: NodeIndex(None), value: " ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 192..198, value: Name( ExprName { node_index: NodeIndex(None), range: 192..198, id: Name("format"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 199..203, value: Name( ExprName { node_index: NodeIndex(None), range: 199..203, id: Name("spec"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 203..205, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 203..205, value: StringLiteralValue { inner: Single( StringLiteral { range: 203..205, node_index: NodeIndex(None), value: "}", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: true, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 207..228, value: FString( ExprFString { node_index: NodeIndex(None), range: 207..228, value: FStringValue { inner: Single( FString( FString { range: 207..228, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 209..216, node_index: NodeIndex(None), value: "middle ", }, ), Interpolation( InterpolatedElement { range: 216..228, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 217..225, value: StringLiteralValue { inner: Single( StringLiteral { range: 217..225, node_index: NodeIndex(None), value: "string", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 226..228, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 226..228, node_index: NodeIndex(None), value: "\\", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 237..250, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 237..250, value: StringLiteralValue { inner: Single( StringLiteral { range: 237..250, node_index: NodeIndex(None), value: "format spec", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 253..285, value: FString( ExprFString { node_index: NodeIndex(None), range: 253..285, value: FStringValue { inner: Single( FString( FString { range: 253..285, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 255..262, node_index: NodeIndex(None), value: "middle ", }, ), Interpolation( InterpolatedElement { range: 262..284, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 263..271, value: StringLiteralValue { inner: Single( StringLiteral { range: 263..271, node_index: NodeIndex(None), value: "string", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 272..284, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 272..284, node_index: NodeIndex(None), value: "\\ ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 285..291, value: Name( ExprName { node_index: NodeIndex(None), range: 285..291, id: Name("format"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 292..296, value: Name( ExprName { node_index: NodeIndex(None), range: 292..296, id: Name("spec"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 296..298, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 296..298, value: StringLiteralValue { inner: Single( StringLiteral { range: 296..298, node_index: NodeIndex(None), value: "}", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: true, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 5 | f'middle {'string':\ 6 | 'format spec'} | ^ Syntax Error: f-string: expecting `}` 7 | 8 | f'middle {'string':\\ | | 5 | f'middle {'string':\ 6 | 'format spec'} | ^^^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons 7 | 8 | f'middle {'string':\\ | | 5 | f'middle {'string':\ 6 | 'format spec'} | ^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons 7 | 8 | f'middle {'string':\\ | | 5 | f'middle {'string':\ 6 | 'format spec'} | ^^ Syntax Error: missing closing quote in string literal 7 | 8 | f'middle {'string':\\ | | 6 | 'format spec'} 7 | 8 | f'middle {'string':\\ | ^^ Syntax Error: f-string: newlines are not allowed in format specifiers when using single quotes 9 | 'format spec'} | | 6 | 'format spec'} 7 | 8 | f'middle {'string':\\ | ^ Syntax Error: f-string: expecting `}` 9 | 'format spec'} 10 | 11 | f'middle {'string':\\\ | | 8 | f'middle {'string':\\ 9 | 'format spec'} | ^^^^^^^^ Syntax Error: Unexpected indentation 10 | 11 | f'middle {'string':\\\ | | 8 | f'middle {'string':\\ 9 | 'format spec'} | ^ Syntax Error: Expected a statement 10 | 11 | f'middle {'string':\\\ | | 8 | f'middle {'string':\\ 9 | 'format spec'} | ^ Syntax Error: Expected a statement 10 | 11 | f'middle {'string':\\\ 12 | 'format spec'} | | 11 | f'middle {'string':\\\ 12 | 'format spec'} | ^ Syntax Error: f-string: expecting `}` | 11 | f'middle {'string':\\\ 12 | 'format spec'} | ^^^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 11 | f'middle {'string':\\\ 12 | 'format spec'} | ^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 11 | f'middle {'string':\\\ 12 | 'format spec'} | ^^ Syntax Error: missing closing quote in string literal invalid_syntax@re_lexing__line_continuation_1.py.snap000064400000000000000000000072051046102023000344000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/line_continuation_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..13, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..13, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("b"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 16..35, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 20..23, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 23..25, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 31..35, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | call(a, b, \\\ | ^ Syntax Error: Expected a newline after line continuation character 2 | 3 | def bar(): | | 1 | call(a, b, \\\ | ^ Syntax Error: Expected a newline after line continuation character 2 | 3 | def bar(): | | 1 | call(a, b, \\\ 2 | | ^ Syntax Error: Expected `)`, found newline 3 | def bar(): 4 | pass | invalid_syntax@re_lexing__line_continuation_windows_eol.py.snap000064400000000000000000000066441046102023000365770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/line_continuation_windows_eol.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..10, func: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 4..10, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("b"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 26..46, is_async: false, decorator_list: [], name: Identifier { id: Name("bar"), range: 30..33, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 33..35, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 42..46, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | call(a, b, # comment \ | ^ Syntax Error: Expected `)`, found newline 2 | 3 | def bar(): 4 | pass | invalid_syntax@re_lexing__triple_quoted_fstring_1.py.snap000064400000000000000000000075631046102023000353020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/triple_quoted_fstring_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..198, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 166..178, value: FString( ExprFString { node_index: NodeIndex(None), range: 166..178, value: FStringValue { inner: Single( FString( FString { range: 166..178, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 170..176, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 176..178, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 177..178, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: true, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 3 | # https://github.com/astral-sh/ruff/issues/11929 4 | 5 | f"""hello {x # comment | ___________________________^ 6 | | y = 1 | |_____^ Syntax Error: f-string: unterminated triple-quoted string | 5 | f"""hello {x # comment 6 | y = 1 | ^ Syntax Error: f-string: expecting `}` | 3 | # https://github.com/astral-sh/ruff/issues/11929 4 | 5 | f"""hello {x # comment | ___________________________^ 6 | | y = 1 | |_____^ Syntax Error: Expected FStringEnd, found FStringMiddle | 5 | f"""hello {x # comment 6 | y = 1 | ^ Syntax Error: Expected a statement invalid_syntax@re_lexing__triple_quoted_fstring_2.py.snap000064400000000000000000000077771046102023000353120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/triple_quoted_fstring_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..183, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 167..183, value: FString( ExprFString { node_index: NodeIndex(None), range: 167..183, value: FStringValue { inner: Single( FString( FString { range: 167..183, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 171..180, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 172..175, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 176..180, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 176..180, node_index: NodeIndex(None), value: ".3f\n", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` ## Errors | 5 | f'''{foo:.3f 6 | ''' | ^^^ Syntax Error: f-string: expecting `}` invalid_syntax@re_lexing__triple_quoted_fstring_3.py.snap000064400000000000000000000142611046102023000352750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/re_lexing/triple_quoted_fstring_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..262, body: [ If( StmtIf { node_index: NodeIndex(None), range: 231..262, test: Call( ExprCall { node_index: NodeIndex(None), range: 234..253, func: Name( ExprName { node_index: NodeIndex(None), range: 234..238, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 238..253, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 239..253, value: FStringValue { inner: Single( FString( FString { range: 239..253, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 243..250, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 244..245, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 246..250, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 246..250, node_index: NodeIndex(None), value: ".3f\n", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), ], keywords: [], }, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 258..262, }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 5 | if call(f'''{x:.3f 6 | ''' | ^^^ Syntax Error: f-string: expecting `}` 7 | pass | | 5 | if call(f'''{x:.3f 6 | ''' | ^ Syntax Error: Expected `)`, found newline 7 | pass | invalid_syntax@re_lexing__ty_1828.py.snap000064400000000000000000000235251046102023000315600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 66..93, target: Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("c"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 70..73, id: Name("int"), ctx: Load, }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 76..93, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 1, ), }, ), Subscript( ExprSubscript { node_index: NodeIndex(None), range: 78..90, value: FString( ExprFString { node_index: NodeIndex(None), range: 78..85, value: FStringValue { inner: Single( FString( FString { range: 78..85, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 82..85, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("d"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "d", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: true, }, }, ), ), }, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 87..90, lower: None, upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 87..90, id: Name("def"), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 91..93, func: Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("a"), ctx: Load, }, ), arguments: Arguments { range: 92..93, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ], ctx: Load, parenthesized: false, }, ), ), simple: false, }, ), ], }, ) ``` ## Errors | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ | ^ Syntax Error: Expected `)`, found `:` 3 | def a( 4 | class A: | | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ | ^ Syntax Error: f-string: expecting `}` 3 | def a( 4 | class A: | | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ 3 | def a( | ^^^ Syntax Error: Expected `:`, found `def` 4 | class A: 5 | pass | | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ 3 | def a( | ^ Syntax Error: Expected `]`, found name 4 | class A: 5 | pass | | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ 3 | def a( | _______^ 4 | | class A: 5 | | pass | |_________^ Syntax Error: f-string: unterminated triple-quoted string | 2 | (c: int = 1,f"""{d=[ 3 | def a( 4 | class A: | ^^^^^ Syntax Error: Expected `)`, found `class` 5 | pass | | 1 | # Regression test for https://github.com/astral-sh/ty/issues/1828 2 | (c: int = 1,f"""{d=[ 3 | def a( | _______^ 4 | | class A: 5 | | pass | |_________^ Syntax Error: Expected a statement | 4 | class A: 5 | pass | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@rebound_comprehension_variable.py.snap000064400000000000000000001471301046102023000345020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/rebound_comprehension_variable.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..342, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..28, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 0..28, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 2..8, target: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 10..27, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 19..27, func: Name( ExprName { node_index: NodeIndex(None), range: 19..24, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 24..27, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 29..57, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 29..57, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 31..37, target: Name( ExprName { node_index: NodeIndex(None), range: 31..32, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..37, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 39..56, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 48..56, func: Name( ExprName { node_index: NodeIndex(None), range: 48..53, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 53..56, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..91, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 58..91, key: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 60..66, target: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 0, ), }, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 69..72, id: Name("val"), ctx: Load, }, ), generators: [ Comprehension { range: 73..90, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 82..90, func: Name( ExprName { node_index: NodeIndex(None), range: 82..87, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 87..90, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..125, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 92..125, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 93..96, id: Name("key"), ctx: Load, }, ), ), value: Named( ExprNamed { node_index: NodeIndex(None), range: 99..105, target: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..105, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 107..124, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 116..124, func: Name( ExprName { node_index: NodeIndex(None), range: 116..121, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 121..124, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 126..154, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 126..154, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 128..134, target: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 133..134, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 136..153, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 145..153, func: Name( ExprName { node_index: NodeIndex(None), range: 145..150, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 150..153, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 151..152, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 155..185, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 155..185, elt: List( ExprList { node_index: NodeIndex(None), range: 156..166, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 158..164, target: Name( ExprName { node_index: NodeIndex(None), range: 158..159, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 163..164, value: Int( 0, ), }, ), }, ), ], ctx: Load, }, ), generators: [ Comprehension { range: 167..184, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 176..184, func: Name( ExprName { node_index: NodeIndex(None), range: 176..181, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 181..184, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 182..183, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 186..233, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 186..233, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 188..194, target: Name( ExprName { node_index: NodeIndex(None), range: 188..189, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 193..194, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 196..214, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 200..201, id: Name("b"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 205..214, func: Name( ExprName { node_index: NodeIndex(None), range: 205..210, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 211..214, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 212..213, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, Comprehension { range: 215..232, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 219..220, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 224..232, func: Name( ExprName { node_index: NodeIndex(None), range: 224..229, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 229..232, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 230..231, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 234..281, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 234..281, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 236..242, target: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 244..262, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 248..249, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 253..262, func: Name( ExprName { node_index: NodeIndex(None), range: 253..258, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 259..262, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 260..261, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, Comprehension { range: 263..280, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 267..268, id: Name("b"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 272..280, func: Name( ExprName { node_index: NodeIndex(None), range: 272..277, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 277..280, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 278..279, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 282..341, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 282..341, elt: Tuple( ExprTuple { node_index: NodeIndex(None), range: 283..303, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 285..291, target: Name( ExprName { node_index: NodeIndex(None), range: 285..286, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 290..291, value: Int( 0, ), }, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 295..301, target: Name( ExprName { node_index: NodeIndex(None), range: 295..296, id: Name("b"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 300..301, value: Int( 1, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), generators: [ Comprehension { range: 304..322, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 308..309, id: Name("a"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 313..322, func: Name( ExprName { node_index: NodeIndex(None), range: 313..318, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 319..322, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 320..321, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, Comprehension { range: 323..340, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 327..328, id: Name("b"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 332..340, func: Name( ExprName { node_index: NodeIndex(None), range: 332..337, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 337..340, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 338..339, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | [(a := 0) for a in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable 2 | {(a := 0) for a in range(0)} 3 | {(a := 0): val for a in range(0)} | | 1 | [(a := 0) for a in range(0)] 2 | {(a := 0) for a in range(0)} | ^ Syntax Error: assignment expression cannot rebind comprehension variable 3 | {(a := 0): val for a in range(0)} 4 | {key: (a := 0) for a in range(0)} | | 1 | [(a := 0) for a in range(0)] 2 | {(a := 0) for a in range(0)} 3 | {(a := 0): val for a in range(0)} | ^ Syntax Error: assignment expression cannot rebind comprehension variable 4 | {key: (a := 0) for a in range(0)} 5 | ((a := 0) for a in range(0)) | | 2 | {(a := 0) for a in range(0)} 3 | {(a := 0): val for a in range(0)} 4 | {key: (a := 0) for a in range(0)} | ^ Syntax Error: assignment expression cannot rebind comprehension variable 5 | ((a := 0) for a in range(0)) 6 | [[(a := 0)] for a in range(0)] | | 3 | {(a := 0): val for a in range(0)} 4 | {key: (a := 0) for a in range(0)} 5 | ((a := 0) for a in range(0)) | ^ Syntax Error: assignment expression cannot rebind comprehension variable 6 | [[(a := 0)] for a in range(0)] 7 | [(a := 0) for b in range (0) for a in range(0)] | | 4 | {key: (a := 0) for a in range(0)} 5 | ((a := 0) for a in range(0)) 6 | [[(a := 0)] for a in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable 7 | [(a := 0) for b in range (0) for a in range(0)] 8 | [(a := 0) for a in range (0) for b in range(0)] | | 5 | ((a := 0) for a in range(0)) 6 | [[(a := 0)] for a in range(0)] 7 | [(a := 0) for b in range (0) for a in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable 8 | [(a := 0) for a in range (0) for b in range(0)] 9 | [((a := 0), (b := 1)) for a in range (0) for b in range(0)] | | 6 | [[(a := 0)] for a in range(0)] 7 | [(a := 0) for b in range (0) for a in range(0)] 8 | [(a := 0) for a in range (0) for b in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable 9 | [((a := 0), (b := 1)) for a in range (0) for b in range(0)] | | 7 | [(a := 0) for b in range (0) for a in range(0)] 8 | [(a := 0) for a in range (0) for b in range(0)] 9 | [((a := 0), (b := 1)) for a in range (0) for b in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable | 7 | [(a := 0) for b in range (0) for a in range(0)] 8 | [(a := 0) for a in range (0) for b in range(0)] 9 | [((a := 0), (b := 1)) for a in range (0) for b in range(0)] | ^ Syntax Error: assignment expression cannot rebind comprehension variable invalid_syntax@return_stmt_invalid_expr.py.snap000064400000000000000000000155671046102023000334100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/return_stmt_invalid_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..74, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 0..8, value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 7..8, value: Name( ExprName { node_index: NodeIndex(None), range: 8..8, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 9..23, value: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 16..23, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 24..43, value: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 31..43, value: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 44..52, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("x"), ctx: Load, }, ), ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 56..57, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 56..57, value: Int( 1, ), }, ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 58..73, value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 65..73, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 66..73, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ), }, ), ], }, ) ``` ## Errors | 1 | return * | ^ Syntax Error: Expected an expression 2 | return yield x 3 | return yield from x 4 | return x := 1 | | 1 | return * 2 | return yield x | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | return yield from x 4 | return x := 1 | | 1 | return * 2 | return yield x 3 | return yield from x | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | return x := 1 5 | return *x and y | | 2 | return yield x 3 | return yield from x 4 | return x := 1 | ^^ Syntax Error: Expected a statement 5 | return *x and y | | 3 | return yield from x 4 | return x := 1 5 | return *x and y | ^^^^^^^ Syntax Error: Boolean expression cannot be used here ## Semantic Syntax Errors | 1 | return * | ^ Syntax Error: Starred expression cannot be used here 2 | return yield x 3 | return yield from x | | 3 | return yield from x 4 | return x := 1 5 | return *x and y | ^^^^^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@simple_and_compound_stmt_on_same_line.py.snap000064400000000000000000000043761046102023000360500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/simple_and_compound_stmt_on_same_line.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..17, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..1, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 3..16, test: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("b"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..16, value: Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("b"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | a; if b: pass; b | ^^ Syntax Error: Compound statements are not allowed on the same line as simple statements invalid_syntax@simple_and_compound_stmt_on_same_line_in_block.py.snap000064400000000000000000000072401046102023000377010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/simple_and_compound_stmt_on_same_line_in_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..59, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..13, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 14..28, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 17..22, value: false, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 24..28, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 29..42, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 32..36, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 38..42, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 44..58, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 47..52, value: false, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 54..58, }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if True: pass if False: pass | ^^ Syntax Error: Compound statements are not allowed on the same line as simple statements 2 | if True: pass; if False: pass | | 1 | if True: pass if False: pass 2 | if True: pass; if False: pass | ^^ Syntax Error: Compound statements are not allowed on the same line as simple statements invalid_syntax@simple_stmts_on_same_line.py.snap000064400000000000000000000116251046102023000335000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/simple_stmts_on_same_line.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..1, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 2..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("b"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 4..9, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4..9, left: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("b"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..15, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 10..15, left: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("c"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("d"), ctx: Load, }, ), }, ), }, ), Break( StmtBreak { node_index: NodeIndex(None), range: 16..21, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 23..31, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 32..36, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 38..46, }, ), Break( StmtBreak { node_index: NodeIndex(None), range: 47..52, }, ), ], }, ) ``` ## Errors | 1 | a b | ^ Syntax Error: Simple statements must be separated by newlines or semicolons 2 | a + b c + d 3 | break; continue pass; continue break | | 1 | a b 2 | a + b c + d | ^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | break; continue pass; continue break | | 1 | a b 2 | a + b c + d 3 | break; continue pass; continue break | ^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 1 | a b 2 | a + b c + d 3 | break; continue pass; continue break | ^^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@simple_stmts_on_same_line_in_block.py.snap000064400000000000000000000045031046102023000353350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/simple_stmts_on_same_line_in_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..45, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Break( StmtBreak { node_index: NodeIndex(None), range: 9..14, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 16..24, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 25..29, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 31..39, }, ), Break( StmtBreak { node_index: NodeIndex(None), range: 40..45, }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 1 | if True: break; continue pass; continue break | ^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons | 1 | if True: break; continue pass; continue break | ^^^^^ Syntax Error: Simple statements must be separated by newlines or semicolons invalid_syntax@single_star_for.py.snap000064400000000000000000000077131046102023000314300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/single_star_for.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..35, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..16, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("_"), ctx: Store, }, ), iter: Starred( ExprStarred { node_index: NodeIndex(None), range: 9..11, value: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 13..16, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 13..16, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 17..34, is_async: false, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 21..23, value: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 27..29, id: Name("xs"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 31..34, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 31..34, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | for _ in *x: ... | ^^ Syntax Error: Starred expression cannot be used here 2 | for *x in xs: ... | | 1 | for _ in *x: ... 2 | for *x in xs: ... | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@single_star_return.py.snap000064400000000000000000000047051046102023000321570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/single_star_return.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..19, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..18, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 9..18, value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 16..18, value: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | def f(): return *x | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@single_star_yield.py.snap000064400000000000000000000055511046102023000317460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/single_star_yield.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..18, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..17, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..17, value: Yield( ExprYield { node_index: NodeIndex(None), range: 9..17, value: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 15..17, value: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | def f(): yield *x | ^^ Syntax Error: Starred expression cannot be used here invalid_syntax@single_starred_assignment_target.py.snap000064400000000000000000000041101046102023000350370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/single_starred_assignment_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..9, targets: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 0..2, value: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 5..9, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | *a = (1,) | ^^ Syntax Error: starred assignment target must be in a list or tuple invalid_syntax@star_index_py310.py.snap000064400000000000000000000537561046102023000313540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/star_index_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..293, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..55, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 44..55, value: Name( ExprName { node_index: NodeIndex(None), range: 44..47, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 48..54, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 48..54, value: Name( ExprName { node_index: NodeIndex(None), range: 49..54, id: Name("index"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 72..112, decorator_list: [], name: Identifier { id: Name("Array"), range: 78..83, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 83..107, node_index: NodeIndex(None), args: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 84..106, value: Name( ExprName { node_index: NodeIndex(None), range: 84..91, id: Name("Generic"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 92..105, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 92..97, id: Name("DType"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 99..105, value: Name( ExprName { node_index: NodeIndex(None), range: 100..105, id: Name("Shape"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 109..112, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..161, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 148..161, value: Name( ExprName { node_index: NodeIndex(None), range: 148..151, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 152..160, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 152..153, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 155..157, value: Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 159..160, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 185..198, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 185..198, value: Name( ExprName { node_index: NodeIndex(None), range: 185..188, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 189..197, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 192..193, id: Name("b"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 195..197, value: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("c"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 222..233, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 222..233, value: Name( ExprName { node_index: NodeIndex(None), range: 222..225, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 226..232, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 226..228, value: Name( ExprName { node_index: NodeIndex(None), range: 227..228, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 230..232, value: Name( ExprName { node_index: NodeIndex(None), range: 231..232, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 254..271, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 254..271, value: Name( ExprName { node_index: NodeIndex(None), range: 254..259, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 260..270, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 260..263, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 260..261, value: Int( 3, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 262..263, value: Int( 5, ), }, ), ), step: None, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 265..270, value: Name( ExprName { node_index: NodeIndex(None), range: 266..270, id: Name("idxs"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.10"} 2 | lst[*index] # simple index | ^^^^^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 3 | class Array(Generic[DType, *Shape]): ... # motivating example from the PEP 4 | lst[a, *b, c] # different positions | | 1 | # parse_options: {"target-version": "3.10"} 2 | lst[*index] # simple index 3 | class Array(Generic[DType, *Shape]): ... # motivating example from the PEP | ^^^^^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 4 | lst[a, *b, c] # different positions 5 | lst[a, b, *c] # different positions | | 2 | lst[*index] # simple index 3 | class Array(Generic[DType, *Shape]): ... # motivating example from the PEP 4 | lst[a, *b, c] # different positions | ^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 5 | lst[a, b, *c] # different positions 6 | lst[*a, *b] # multiple unpacks | | 3 | class Array(Generic[DType, *Shape]): ... # motivating example from the PEP 4 | lst[a, *b, c] # different positions 5 | lst[a, b, *c] # different positions | ^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 6 | lst[*a, *b] # multiple unpacks 7 | array[3:5, *idxs] # mixed with slices | | 4 | lst[a, *b, c] # different positions 5 | lst[a, b, *c] # different positions 6 | lst[*a, *b] # multiple unpacks | ^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 7 | array[3:5, *idxs] # mixed with slices | | 4 | lst[a, *b, c] # different positions 5 | lst[a, b, *c] # different positions 6 | lst[*a, *b] # multiple unpacks | ^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) 7 | array[3:5, *idxs] # mixed with slices | | 5 | lst[a, b, *c] # different positions 6 | lst[*a, *b] # multiple unpacks 7 | array[3:5, *idxs] # mixed with slices | ^^^^^ Syntax Error: Cannot use star expression in index on Python 3.10 (syntax was added in Python 3.11) ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/invalid_syntax@star_slices.py.snap000064400000000000000000000070321046102023000306340ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/star_slices.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..19, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..18, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..18, value: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("array"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 6..17, lower: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 6..12, value: Name( ExprName { node_index: NodeIndex(None), range: 7..12, id: Name("start"), ctx: Load, }, ), ctx: Load, }, ), ), upper: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..17, value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("end"), ctx: Load, }, ), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | array[*start:*end] | ^^^^^^ Syntax Error: Starred expression cannot be used here | 1 | array[*start:*end] | ^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@starred_comprehension_target.py.snap000064400000000000000000000054401046102023000342060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/starred_comprehension_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..27, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 0..27, elt: Name( ExprName { node_index: NodeIndex(None), range: 1..5, id: Name("item"), ctx: Load, }, ), generators: [ Comprehension { range: 6..26, node_index: NodeIndex(None), target: Starred( ExprStarred { node_index: NodeIndex(None), range: 10..16, value: Name( ExprName { node_index: NodeIndex(None), range: 11..16, id: Name("items"), ctx: Store, }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 20..26, id: Name("source"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | [item for *items in source] | ^^^^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@starred_list_comp_py314.py.snap000064400000000000000000000054651046102023000327270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/starred_list_comp_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..60, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..59, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 44..59, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 45..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 48..58, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | [*x for x in y] | ^^ Syntax Error: Cannot use iterable unpacking in a list comprehension on Python 3.14 (syntax was added in Python 3.15) invalid_syntax@starred_starred_expression.py.snap000064400000000000000000000123151046102023000337110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/starred_starred_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..26, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..12, func: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 5..12, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 6..11, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 8..11, value: List( ExprList { node_index: NodeIndex(None), range: 9..11, elts: [], ctx: Load, }, ), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..25, value: Call( ExprCall { node_index: NodeIndex(None), range: 13..25, func: Name( ExprName { node_index: NodeIndex(None), range: 13..18, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 18..25, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 19..24, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 21..24, value: List( ExprList { node_index: NodeIndex(None), range: 22..24, elts: [], ctx: Load, }, ), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ## Errors | 1 | print(* 2 | *[]) | ^^^ Syntax Error: Starred expression cannot be used here 3 | print(* *[]) | | 1 | print(* 2 | *[]) 3 | print(* *[]) | ^^^ Syntax Error: Starred expression cannot be used here invalid_syntax@statements__function_type_parameters.py.snap000064400000000000000000000425131046102023000357640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/function_type_parameters.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..988, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 796..824, is_async: false, decorator_list: [], name: Identifier { id: Name("keyword"), range: 800..807, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 807..817, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 808..809, name: Identifier { id: Name("A"), range: 808..809, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 811..816, name: Identifier { id: Name("await"), range: 811..816, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 817..819, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 821..824, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 821..824, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 826..862, is_async: false, decorator_list: [], name: Identifier { id: Name("not_a_type_param"), range: 830..846, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 846..855, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 847..848, name: Identifier { id: Name("A"), range: 847..848, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 853..854, name: Identifier { id: Name("B"), range: 853..854, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 855..857, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 859..862, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 859..862, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 864..896, is_async: false, decorator_list: [], name: Identifier { id: Name("multiple_commas"), range: 868..883, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 883..889, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 884..885, name: Identifier { id: Name("A"), range: 884..885, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 887..888, name: Identifier { id: Name("B"), range: 887..888, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 889..891, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 893..896, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 893..896, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 898..938, is_async: false, decorator_list: [], name: Identifier { id: Name("multiple_trailing_commas"), range: 902..926, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 926..931, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 927..928, name: Identifier { id: Name("A"), range: 927..928, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 931..933, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 935..938, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 935..938, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 940..979, is_async: false, decorator_list: [], name: Identifier { id: Name("multiple_commas_and_recovery"), range: 944..972, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 972..976, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 973..974, name: Identifier { id: Name("A"), range: 973..974, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 976..976, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 976..979, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 976..979, value: Int( 100, ), }, ), }, ), ], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 980..987, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 980..982, elts: [], ctx: Store, parenthesized: true, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 984..987, }, ), value: None, simple: false, }, ), ], }, ) ``` ## Errors | 9 | # on following lines. 10 | 11 | def keyword[A, await](): ... | ^^^^^ Syntax Error: Expected an identifier, but found a keyword `await` that cannot be used here 12 | 13 | def not_a_type_param[A, |, B](): ... | | 11 | def keyword[A, await](): ... 12 | 13 | def not_a_type_param[A, |, B](): ... | ^ Syntax Error: Expected `,`, found `|` 14 | 15 | def multiple_commas[A,,B](): ... | | 11 | def keyword[A, await](): ... 12 | 13 | def not_a_type_param[A, |, B](): ... | ^ Syntax Error: Expected a type parameter or the end of the type parameter list 14 | 15 | def multiple_commas[A,,B](): ... | | 13 | def not_a_type_param[A, |, B](): ... 14 | 15 | def multiple_commas[A,,B](): ... | ^ Syntax Error: Expected a type parameter or the end of the type parameter list 16 | 17 | def multiple_trailing_commas[A,,](): ... | | 15 | def multiple_commas[A,,B](): ... 16 | 17 | def multiple_trailing_commas[A,,](): ... | ^ Syntax Error: Expected a type parameter or the end of the type parameter list 18 | 19 | def multiple_commas_and_recovery[A,,100](): ... | | 17 | def multiple_trailing_commas[A,,](): ... 18 | 19 | def multiple_commas_and_recovery[A,,100](): ... | ^ Syntax Error: Expected a type parameter or the end of the type parameter list | 17 | def multiple_trailing_commas[A,,](): ... 18 | 19 | def multiple_commas_and_recovery[A,,100](): ... | ^^^ Syntax Error: Expected `]`, found int | 17 | def multiple_trailing_commas[A,,](): ... 18 | 19 | def multiple_commas_and_recovery[A,,100](): ... | ^ Syntax Error: Expected newline, found `]` | 17 | def multiple_trailing_commas[A,,](): ... 18 | 19 | def multiple_commas_and_recovery[A,,100](): ... | ^^ Syntax Error: Only single target (not tuple) can be annotated invalid_syntax@statements__if_extra_closing_parentheses.py.snap000064400000000000000000000035321046102023000365710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/if_extra_closing_parentheses.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..110, body: [ If( StmtIf { node_index: NodeIndex(None), range: 90..97, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 93..97, value: true, }, ), body: [], elif_else_clauses: [], }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 105..109, }, ), ], }, ) ``` ## Errors | 1 | # FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) 2 | if True)): | ^ Syntax Error: Expected `:`, found `)` 3 | pass | | 1 | # FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) 2 | if True)): | ^ Syntax Error: Expected a statement 3 | pass | | 1 | # FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) 2 | if True)): | ^ Syntax Error: Expected a statement 3 | pass | | 1 | # FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) 2 | if True)): | ^ Syntax Error: Expected a statement 3 | pass | | 1 | # FIXME(micha): This creates two syntax errors instead of just one (and overlapping ones) 2 | if True)): 3 | pass | ^^^^ Syntax Error: Unexpected indentation invalid_syntax@statements__if_extra_indent.py.snap000064400000000000000000000547101046102023000340170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/if_extra_indent.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..905, body: [ If( StmtIf { node_index: NodeIndex(None), range: 69..110, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 72..76, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 82..86, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..100, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 95..100, left: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("b"), ctx: Load, }, ), }, ), }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 106..110, }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 112..118, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("a"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 116..118, value: Int( 10, ), }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 158..248, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 161..165, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 171..184, value: Name( ExprName { node_index: NodeIndex(None), range: 171..184, id: Name("before_nested"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..205, value: Name( ExprName { node_index: NodeIndex(None), range: 193..205, id: Name("first_nested"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 218..231, value: Name( ExprName { node_index: NodeIndex(None), range: 218..231, id: Name("second_nested"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 236..248, value: Name( ExprName { node_index: NodeIndex(None), range: 236..248, id: Name("after_nested"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 250..264, value: Name( ExprName { node_index: NodeIndex(None), range: 250..264, id: Name("outside_nested"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 325..449, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 328..332, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 338..353, value: Name( ExprName { node_index: NodeIndex(None), range: 338..353, id: Name("before_compound"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 362..403, test: Name( ExprName { node_index: NodeIndex(None), range: 365..374, id: Name("condition"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 388..403, value: Name( ExprName { node_index: NodeIndex(None), range: 388..403, id: Name("nested_compound"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 412..430, value: Name( ExprName { node_index: NodeIndex(None), range: 412..430, id: Name("recovered_compound"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 435..449, value: Name( ExprName { node_index: NodeIndex(None), range: 435..449, id: Name("after_compound"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 451..467, value: Name( ExprName { node_index: NodeIndex(None), range: 451..467, id: Name("outside_compound"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 536..641, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 539..543, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 549..563, value: Name( ExprName { node_index: NodeIndex(None), range: 549..563, id: Name("before_regions"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 572..584, value: Name( ExprName { node_index: NodeIndex(None), range: 572..584, id: Name("first_region"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 589..602, value: Name( ExprName { node_index: NodeIndex(None), range: 589..602, id: Name("middle_region"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 611..624, value: Name( ExprName { node_index: NodeIndex(None), range: 611..624, id: Name("second_region"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 629..641, value: Name( ExprName { node_index: NodeIndex(None), range: 629..641, id: Name("after_region"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 643..658, value: Name( ExprName { node_index: NodeIndex(None), range: 643..658, id: Name("outside_regions"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 734..793, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 737..741, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 747..759, value: Name( ExprName { node_index: NodeIndex(None), range: 747..759, id: Name("before_error"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 768..777, value: Call( ExprCall { node_index: NodeIndex(None), range: 768..777, func: Name( ExprName { node_index: NodeIndex(None), range: 768..774, id: Name("broken"), ctx: Load, }, ), arguments: Arguments { range: 774..777, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 782..793, value: Name( ExprName { node_index: NodeIndex(None), range: 782..793, id: Name("after_error"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 795..808, value: Name( ExprName { node_index: NodeIndex(None), range: 795..808, id: Name("outside_error"), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 863..904, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 866..870, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 876..886, value: Name( ExprName { node_index: NodeIndex(None), range: 876..886, id: Name("before_eof"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 895..904, value: Name( ExprName { node_index: NodeIndex(None), range: 895..904, id: Name("final_eof"), ctx: Load, }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ## Errors | 2 | if True: 3 | pass 4 | a + b | ^^^^^^^^ Syntax Error: Unexpected indentation 5 | 6 | pass | | 11 | if True: 12 | before_nested 13 | first_nested | ^^^^^^^^ Syntax Error: Unexpected indentation 14 | second_nested 15 | after_nested | | 12 | before_nested 13 | first_nested 14 | second_nested | ^^^^^^^^^^^^ Syntax Error: Unexpected indentation 15 | after_nested | | 20 | if True: 21 | before_compound 22 | if condition: | ^^^^^^^^ Syntax Error: Unexpected indentation 23 | nested_compound 24 | recovered_compound | | 30 | if True: 31 | before_regions 32 | first_region | ^^^^^^^^ Syntax Error: Unexpected indentation 33 | middle_region 34 | second_region | | 32 | first_region 33 | middle_region 34 | second_region | ^^^^^^^^ Syntax Error: Unexpected indentation 35 | after_region | | 40 | if True: 41 | before_error 42 | broken(,) | ^^^^^^^^ Syntax Error: Unexpected indentation 43 | after_error | | 40 | if True: 41 | before_error 42 | broken(,) | ^ Syntax Error: Expected an expression or a ')' 43 | after_error | | 48 | if True: 49 | before_eof 50 | final_eof | ^^^^^^^^ Syntax Error: Unexpected indentation invalid_syntax@statements__invalid_assignment_targets.py.snap000064400000000000000000002276121046102023000362670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/invalid_assignment_targets.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..788, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 201..206, targets: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 5, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 205..206, value: Int( 3, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 208..214, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 208..209, value: Int( 5, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..214, value: Int( 3, ), }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 216..228, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 217..218, value: Int( 5, ), }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 221..224, id: Name("int"), ctx: Load, }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 227..228, value: Int( 3, ), }, ), ), simple: false, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 303..314, targets: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 303..309, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 303..304, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 308..309, id: Name("y"), ctx: Load, }, ), ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 312..314, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 315..328, targets: [ Named( ExprNamed { node_index: NodeIndex(None), range: 316..322, target: Name( ExprName { node_index: NodeIndex(None), range: 316..317, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 321..322, value: Int( 5, ), }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 326..328, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 329..339, targets: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 329..334, left: Name( ExprName { node_index: NodeIndex(None), range: 329..330, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 333..334, id: Name("y"), ctx: Load, }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 337..339, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 340..347, targets: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 340..342, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 341..342, id: Name("x"), ctx: Store, }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 345..347, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 348..366, targets: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 349..360, parameters: Some( Parameters { range: 356..357, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 356..357, node_index: NodeIndex(None), parameter: Parameter { range: 356..357, node_index: NodeIndex(None), name: Identifier { id: Name("_"), range: 356..357, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 359..360, value: Int( 1, ), }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 364..366, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 367..385, targets: [ If( ExprIf { node_index: NodeIndex(None), range: 367..380, test: Name( ExprName { node_index: NodeIndex(None), range: 372..373, id: Name("b"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 367..368, id: Name("a"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 379..380, id: Name("c"), ctx: Load, }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 383..385, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 386..399, targets: [ Dict( ExprDict { node_index: NodeIndex(None), range: 386..394, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 387..390, value: StringLiteralValue { inner: Single( StringLiteral { range: 387..390, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 392..393, value: Int( 5, ), }, ), }, ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 397..399, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 400..408, targets: [ Set( ExprSet { node_index: NodeIndex(None), range: 400..403, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 401..402, id: Name("a"), ctx: Load, }, ), ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 406..408, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 409..429, targets: [ ListComp( ExprListComp { node_index: NodeIndex(None), range: 409..424, elt: Name( ExprName { node_index: NodeIndex(None), range: 410..411, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 412..423, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 416..417, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 421..423, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 427..429, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 430..450, targets: [ SetComp( ExprSetComp { node_index: NodeIndex(None), range: 430..445, elt: Name( ExprName { node_index: NodeIndex(None), range: 431..432, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 433..444, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 437..438, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 442..444, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 448..450, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 451..478, targets: [ DictComp( ExprDictComp { node_index: NodeIndex(None), range: 451..473, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 452..453, id: Name("x"), ctx: Load, }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 455..460, left: Name( ExprName { node_index: NodeIndex(None), range: 455..456, id: Name("x"), ctx: Load, }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 459..460, value: Int( 2, ), }, ), }, ), generators: [ Comprehension { range: 461..472, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 465..466, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 470..472, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 476..478, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 479..499, targets: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 479..494, elt: Name( ExprName { node_index: NodeIndex(None), range: 480..481, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 482..493, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 486..487, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 491..493, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 497..499, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 500..512, targets: [ Await( ExprAwait { node_index: NodeIndex(None), range: 500..507, value: Name( ExprName { node_index: NodeIndex(None), range: 506..507, id: Name("x"), ctx: Load, }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 510..512, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 513..527, targets: [ Yield( ExprYield { node_index: NodeIndex(None), range: 514..521, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 520..521, id: Name("x"), ctx: Load, }, ), ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 525..527, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 528..548, targets: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 529..542, value: Name( ExprName { node_index: NodeIndex(None), range: 540..542, id: Name("xs"), ctx: Load, }, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 546..548, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 549..563, targets: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 549..558, left: Name( ExprName { node_index: NodeIndex(None), range: 549..550, id: Name("a"), ctx: Load, }, ), ops: [ Lt, Lt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 553..554, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 557..558, id: Name("c"), ctx: Load, }, ), ], }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 561..563, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 564..574, targets: [ Call( ExprCall { node_index: NodeIndex(None), range: 564..569, func: Name( ExprName { node_index: NodeIndex(None), range: 564..567, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 567..569, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 572..574, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 576..590, targets: [ FString( ExprFString { node_index: NodeIndex(None), range: 576..585, value: FStringValue { inner: Single( FString( FString { range: 576..585, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 578..584, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 579..583, id: Name("quux"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 588..590, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 591..614, targets: [ FString( ExprFString { node_index: NodeIndex(None), range: 591..609, value: FStringValue { inner: Single( FString( FString { range: 591..609, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 593..598, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 594..597, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 598..603, node_index: NodeIndex(None), value: " and ", }, ), Interpolation( InterpolatedElement { range: 603..608, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 604..607, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 612..614, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 616..626, targets: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 616..621, value: StringLiteralValue { inner: Single( StringLiteral { range: 616..621, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 624..626, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 627..638, targets: [ BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 627..633, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 627..633, node_index: NodeIndex(None), value: [ 102, 111, 111, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 636..638, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 639..647, targets: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 639..642, value: Int( 123, ), }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 645..647, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 648..657, targets: [ BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 648..652, value: true, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 655..657, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 658..667, targets: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 658..662, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 665..667, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 668..676, targets: [ EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 668..671, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 674..676, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 677..688, targets: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 677..683, value: Call( ExprCall { node_index: NodeIndex(None), range: 678..683, func: Name( ExprName { node_index: NodeIndex(None), range: 678..681, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 681..683, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 686..688, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 689..717, targets: [ List( ExprList { node_index: NodeIndex(None), range: 689..702, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 690..691, id: Name("x"), ctx: Store, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 693..698, func: Name( ExprName { node_index: NodeIndex(None), range: 693..696, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 696..698, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), Name( ExprName { node_index: NodeIndex(None), range: 700..701, id: Name("y"), ctx: Store, }, ), ], ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 705..717, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 706..708, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 710..712, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 714..716, value: Int( 42, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 718..758, targets: [ List( ExprList { node_index: NodeIndex(None), range: 718..737, elts: [ List( ExprList { node_index: NodeIndex(None), range: 719..725, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 720..721, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 723..724, id: Name("b"), ctx: Store, }, ), ], ctx: Store, }, ), List( ExprList { node_index: NodeIndex(None), range: 727..733, elts: [ List( ExprList { node_index: NodeIndex(None), range: 728..732, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 729..731, value: Int( 42, ), }, ), ], ctx: Store, }, ), ], ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 735..736, id: Name("d"), ctx: Store, }, ), ], ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 740..758, elts: [ List( ExprList { node_index: NodeIndex(None), range: 741..747, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 742..743, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 745..746, value: Int( 2, ), }, ), ], ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 749..754, elts: [ List( ExprList { node_index: NodeIndex(None), range: 750..753, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 751..752, value: Int( 3, ), }, ), ], ctx: Load, }, ), ], ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 756..757, value: Int( 4, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 759..787, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 759..772, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 760..761, id: Name("x"), ctx: Store, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 763..768, func: Name( ExprName { node_index: NodeIndex(None), range: 763..766, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 766..768, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), Name( ExprName { node_index: NodeIndex(None), range: 770..771, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 775..787, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 776..778, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 780..782, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 784..786, value: Int( 42, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Errors | 3 | # rejected by the parser. e.g., `5 = 3`, `5 += 3`, `(5): int = 3`. 4 | 5 | 5 = 3 | ^ Syntax Error: Invalid assignment target 6 | 7 | 5 += 3 | | 5 | 5 = 3 6 | 7 | 5 += 3 | ^ Syntax Error: Invalid augmented assignment target 8 | 9 | (5): int = 3 | | 7 | 5 += 3 8 | 9 | (5): int = 3 | ^ Syntax Error: Invalid annotated assignment target 10 | 11 | # Now we exhaustively test all possible cases where assignment can fail. | | 11 | # Now we exhaustively test all possible cases where assignment can fail. 12 | x or y = 42 | ^^^^^^ Syntax Error: Invalid assignment target 13 | (x := 5) = 42 14 | x + y = 42 | | 11 | # Now we exhaustively test all possible cases where assignment can fail. 12 | x or y = 42 13 | (x := 5) = 42 | ^^^^^^ Syntax Error: Invalid assignment target 14 | x + y = 42 15 | -x = 42 | | 12 | x or y = 42 13 | (x := 5) = 42 14 | x + y = 42 | ^^^^^ Syntax Error: Invalid assignment target 15 | -x = 42 16 | (lambda _: 1) = 42 | | 13 | (x := 5) = 42 14 | x + y = 42 15 | -x = 42 | ^^ Syntax Error: Invalid assignment target 16 | (lambda _: 1) = 42 17 | a if b else c = 42 | | 14 | x + y = 42 15 | -x = 42 16 | (lambda _: 1) = 42 | ^^^^^^^^^^^ Syntax Error: Invalid assignment target 17 | a if b else c = 42 18 | {"a": 5} = 42 | | 15 | -x = 42 16 | (lambda _: 1) = 42 17 | a if b else c = 42 | ^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 18 | {"a": 5} = 42 19 | {a} = 42 | | 16 | (lambda _: 1) = 42 17 | a if b else c = 42 18 | {"a": 5} = 42 | ^^^^^^^^ Syntax Error: Invalid assignment target 19 | {a} = 42 20 | [x for x in xs] = 42 | | 17 | a if b else c = 42 18 | {"a": 5} = 42 19 | {a} = 42 | ^^^ Syntax Error: Invalid assignment target 20 | [x for x in xs] = 42 21 | {x for x in xs} = 42 | | 18 | {"a": 5} = 42 19 | {a} = 42 20 | [x for x in xs] = 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 21 | {x for x in xs} = 42 22 | {x: x * 2 for x in xs} = 42 | | 19 | {a} = 42 20 | [x for x in xs] = 42 21 | {x for x in xs} = 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 22 | {x: x * 2 for x in xs} = 42 23 | (x for x in xs) = 42 | | 20 | [x for x in xs] = 42 21 | {x for x in xs} = 42 22 | {x: x * 2 for x in xs} = 42 | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 23 | (x for x in xs) = 42 24 | await x = 42 | | 21 | {x for x in xs} = 42 22 | {x: x * 2 for x in xs} = 42 23 | (x for x in xs) = 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 24 | await x = 42 25 | (yield x) = 42 | | 22 | {x: x * 2 for x in xs} = 42 23 | (x for x in xs) = 42 24 | await x = 42 | ^^^^^^^ Syntax Error: Invalid assignment target 25 | (yield x) = 42 26 | (yield from xs) = 42 | | 23 | (x for x in xs) = 42 24 | await x = 42 25 | (yield x) = 42 | ^^^^^^^ Syntax Error: Invalid assignment target 26 | (yield from xs) = 42 27 | a < b < c = 42 | | 24 | await x = 42 25 | (yield x) = 42 26 | (yield from xs) = 42 | ^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 27 | a < b < c = 42 28 | foo() = 42 | | 25 | (yield x) = 42 26 | (yield from xs) = 42 27 | a < b < c = 42 | ^^^^^^^^^ Syntax Error: Invalid assignment target 28 | foo() = 42 | | 26 | (yield from xs) = 42 27 | a < b < c = 42 28 | foo() = 42 | ^^^^^ Syntax Error: Invalid assignment target 29 | 30 | f"{quux}" = 42 | | 28 | foo() = 42 29 | 30 | f"{quux}" = 42 | ^^^^^^^^^ Syntax Error: Invalid assignment target 31 | f"{foo} and {bar}" = 42 | | 30 | f"{quux}" = 42 31 | f"{foo} and {bar}" = 42 | ^^^^^^^^^^^^^^^^^^ Syntax Error: Invalid assignment target 32 | 33 | "foo" = 42 | | 31 | f"{foo} and {bar}" = 42 32 | 33 | "foo" = 42 | ^^^^^ Syntax Error: Invalid assignment target 34 | b"foo" = 42 35 | 123 = 42 | | 33 | "foo" = 42 34 | b"foo" = 42 | ^^^^^^ Syntax Error: Invalid assignment target 35 | 123 = 42 36 | True = 42 | | 33 | "foo" = 42 34 | b"foo" = 42 35 | 123 = 42 | ^^^ Syntax Error: Invalid assignment target 36 | True = 42 37 | None = 42 | | 34 | b"foo" = 42 35 | 123 = 42 36 | True = 42 | ^^^^ Syntax Error: Invalid assignment target 37 | None = 42 38 | ... = 42 | | 35 | 123 = 42 36 | True = 42 37 | None = 42 | ^^^^ Syntax Error: Invalid assignment target 38 | ... = 42 39 | *foo() = 42 | | 36 | True = 42 37 | None = 42 38 | ... = 42 | ^^^ Syntax Error: Invalid assignment target 39 | *foo() = 42 40 | [x, foo(), y] = [42, 42, 42] | | 37 | None = 42 38 | ... = 42 39 | *foo() = 42 | ^^^^^ Syntax Error: Invalid assignment target 40 | [x, foo(), y] = [42, 42, 42] 41 | [[a, b], [[42]], d] = [[1, 2], [[3]], 4] | | 38 | ... = 42 39 | *foo() = 42 40 | [x, foo(), y] = [42, 42, 42] | ^^^^^ Syntax Error: Invalid assignment target 41 | [[a, b], [[42]], d] = [[1, 2], [[3]], 4] 42 | (x, foo(), y) = (42, 42, 42) | | 39 | *foo() = 42 40 | [x, foo(), y] = [42, 42, 42] 41 | [[a, b], [[42]], d] = [[1, 2], [[3]], 4] | ^^ Syntax Error: Invalid assignment target 42 | (x, foo(), y) = (42, 42, 42) | | 40 | [x, foo(), y] = [42, 42, 42] 41 | [[a, b], [[42]], d] = [[1, 2], [[3]], 4] 42 | (x, foo(), y) = (42, 42, 42) | ^^^^^ Syntax Error: Invalid assignment target ## Semantic Syntax Errors | 37 | None = 42 38 | ... = 42 39 | *foo() = 42 | ^^^^^^ Syntax Error: starred assignment target must be in a list or tuple 40 | [x, foo(), y] = [42, 42, 42] 41 | [[a, b], [[42]], d] = [[1, 2], [[3]], 4] | invalid_syntax@statements__invalid_augmented_assignment_target.py.snap000064400000000000000000002113761046102023000401350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/invalid_augmented_assignment_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..611, body: [ AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 97..109, target: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 97..103, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("y"), ctx: Load, }, ), ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 107..109, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 110..124, target: Named( ExprNamed { node_index: NodeIndex(None), range: 111..117, target: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 116..117, value: Int( 5, ), }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..124, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 125..136, target: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 125..130, left: Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("y"), ctx: Load, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 134..136, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 137..145, target: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 137..139, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 138..139, id: Name("x"), ctx: Store, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..145, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 146..165, target: Lambda( ExprLambda { node_index: NodeIndex(None), range: 147..158, parameters: Some( Parameters { range: 154..155, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 154..155, node_index: NodeIndex(None), parameter: Parameter { range: 154..155, node_index: NodeIndex(None), name: Identifier { id: Name("_"), range: 154..155, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 157..158, value: Int( 1, ), }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 163..165, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 166..185, target: If( ExprIf { node_index: NodeIndex(None), range: 166..179, test: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("b"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("a"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("c"), ctx: Load, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 183..185, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 186..200, target: Dict( ExprDict { node_index: NodeIndex(None), range: 186..194, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 187..190, value: StringLiteralValue { inner: Single( StringLiteral { range: 187..190, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 192..193, value: Int( 5, ), }, ), }, ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 198..200, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 201..210, target: Set( ExprSet { node_index: NodeIndex(None), range: 201..204, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("a"), ctx: Load, }, ), ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 208..210, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 211..232, target: ListComp( ExprListComp { node_index: NodeIndex(None), range: 211..226, elt: Name( ExprName { node_index: NodeIndex(None), range: 212..213, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 214..225, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 218..219, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 223..225, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 230..232, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 233..254, target: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 233..248, elt: Name( ExprName { node_index: NodeIndex(None), range: 234..235, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 236..247, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 240..241, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 245..247, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 252..254, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 255..283, target: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 255..277, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 256..257, id: Name("x"), ctx: Load, }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 259..264, left: Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("x"), ctx: Load, }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 263..264, value: Int( 2, ), }, ), }, ), generators: [ Comprehension { range: 265..276, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 269..270, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 274..276, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 281..283, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 284..305, target: Generator( ExprGenerator { node_index: NodeIndex(None), range: 284..299, elt: Name( ExprName { node_index: NodeIndex(None), range: 285..286, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 287..298, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 291..292, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 296..298, id: Name("xs"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 303..305, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 306..319, target: Await( ExprAwait { node_index: NodeIndex(None), range: 306..313, value: Name( ExprName { node_index: NodeIndex(None), range: 312..313, id: Name("x"), ctx: Load, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 317..319, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 320..335, target: Yield( ExprYield { node_index: NodeIndex(None), range: 321..328, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 327..328, id: Name("x"), ctx: Load, }, ), ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 333..335, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 336..357, target: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 337..350, value: Name( ExprName { node_index: NodeIndex(None), range: 348..350, id: Name("xs"), ctx: Load, }, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 355..357, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 358..373, target: Compare( ExprCompare { node_index: NodeIndex(None), range: 358..367, left: Name( ExprName { node_index: NodeIndex(None), range: 358..359, id: Name("a"), ctx: Load, }, ), ops: [ Lt, Lt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 362..363, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 366..367, id: Name("c"), ctx: Load, }, ), ], }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 371..373, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 374..385, target: Call( ExprCall { node_index: NodeIndex(None), range: 374..379, func: Name( ExprName { node_index: NodeIndex(None), range: 374..377, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 377..379, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 383..385, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 387..402, target: FString( ExprFString { node_index: NodeIndex(None), range: 387..396, value: FStringValue { inner: Single( FString( FString { range: 387..396, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 389..395, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 390..394, id: Name("quux"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 400..402, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 403..427, target: FString( ExprFString { node_index: NodeIndex(None), range: 403..421, value: FStringValue { inner: Single( FString( FString { range: 403..421, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 405..410, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 406..409, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 410..415, node_index: NodeIndex(None), value: " and ", }, ), Interpolation( InterpolatedElement { range: 415..420, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 416..419, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 425..427, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 429..440, target: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 429..434, value: StringLiteralValue { inner: Single( StringLiteral { range: 429..434, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 438..440, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 441..453, target: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 441..447, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 441..447, node_index: NodeIndex(None), value: [ 102, 111, 111, ], flags: BytesLiteralFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 451..453, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 454..463, target: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 454..457, value: Int( 123, ), }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 461..463, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 464..474, target: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 464..468, value: true, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 472..474, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 475..485, target: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 475..479, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 483..485, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 486..495, target: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 486..489, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 493..495, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 496..508, target: Starred( ExprStarred { node_index: NodeIndex(None), range: 496..502, value: Call( ExprCall { node_index: NodeIndex(None), range: 497..502, func: Name( ExprName { node_index: NodeIndex(None), range: 497..500, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 500..502, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ctx: Store, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 506..508, value: Int( 42, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 509..538, target: List( ExprList { node_index: NodeIndex(None), range: 509..522, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 510..511, id: Name("x"), ctx: Store, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 513..518, func: Name( ExprName { node_index: NodeIndex(None), range: 513..516, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 516..518, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), Name( ExprName { node_index: NodeIndex(None), range: 520..521, id: Name("y"), ctx: Store, }, ), ], ctx: Store, }, ), op: Add, value: List( ExprList { node_index: NodeIndex(None), range: 526..538, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 527..529, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 531..533, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 535..537, value: Int( 42, ), }, ), ], ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 539..580, target: List( ExprList { node_index: NodeIndex(None), range: 539..558, elts: [ List( ExprList { node_index: NodeIndex(None), range: 540..546, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 541..542, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 544..545, id: Name("b"), ctx: Store, }, ), ], ctx: Store, }, ), List( ExprList { node_index: NodeIndex(None), range: 548..554, elts: [ List( ExprList { node_index: NodeIndex(None), range: 549..553, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 550..552, value: Int( 42, ), }, ), ], ctx: Store, }, ), ], ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 556..557, id: Name("d"), ctx: Store, }, ), ], ctx: Store, }, ), op: Add, value: List( ExprList { node_index: NodeIndex(None), range: 562..580, elts: [ List( ExprList { node_index: NodeIndex(None), range: 563..569, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 564..565, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 567..568, value: Int( 2, ), }, ), ], ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 571..576, elts: [ List( ExprList { node_index: NodeIndex(None), range: 572..575, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 573..574, value: Int( 3, ), }, ), ], ctx: Load, }, ), ], ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 578..579, value: Int( 4, ), }, ), ], ctx: Load, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 581..610, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 581..594, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 582..583, id: Name("x"), ctx: Store, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 585..590, func: Name( ExprName { node_index: NodeIndex(None), range: 585..588, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 588..590, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), Name( ExprName { node_index: NodeIndex(None), range: 592..593, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), op: Add, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 598..610, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 599..601, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 603..605, value: Int( 42, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 607..609, value: Int( 42, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ## Errors | 2 | # assignment targets. 3 | 4 | x or y += 42 | ^^^^^^ Syntax Error: Invalid augmented assignment target 5 | (x := 5) += 42 6 | x + y += 42 | | 4 | x or y += 42 5 | (x := 5) += 42 | ^^^^^^ Syntax Error: Invalid augmented assignment target 6 | x + y += 42 7 | -x += 42 | | 4 | x or y += 42 5 | (x := 5) += 42 6 | x + y += 42 | ^^^^^ Syntax Error: Invalid augmented assignment target 7 | -x += 42 8 | (lambda _: 1) += 42 | | 5 | (x := 5) += 42 6 | x + y += 42 7 | -x += 42 | ^^ Syntax Error: Invalid augmented assignment target 8 | (lambda _: 1) += 42 9 | a if b else c += 42 | | 6 | x + y += 42 7 | -x += 42 8 | (lambda _: 1) += 42 | ^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 9 | a if b else c += 42 10 | {"a": 5} += 42 | | 7 | -x += 42 8 | (lambda _: 1) += 42 9 | a if b else c += 42 | ^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 10 | {"a": 5} += 42 11 | {a} += 42 | | 8 | (lambda _: 1) += 42 9 | a if b else c += 42 10 | {"a": 5} += 42 | ^^^^^^^^ Syntax Error: Invalid augmented assignment target 11 | {a} += 42 12 | [x for x in xs] += 42 | | 9 | a if b else c += 42 10 | {"a": 5} += 42 11 | {a} += 42 | ^^^ Syntax Error: Invalid augmented assignment target 12 | [x for x in xs] += 42 13 | {x for x in xs} += 42 | | 10 | {"a": 5} += 42 11 | {a} += 42 12 | [x for x in xs] += 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 13 | {x for x in xs} += 42 14 | {x: x * 2 for x in xs} += 42 | | 11 | {a} += 42 12 | [x for x in xs] += 42 13 | {x for x in xs} += 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 14 | {x: x * 2 for x in xs} += 42 15 | (x for x in xs) += 42 | | 12 | [x for x in xs] += 42 13 | {x for x in xs} += 42 14 | {x: x * 2 for x in xs} += 42 | ^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 15 | (x for x in xs) += 42 16 | await x += 42 | | 13 | {x for x in xs} += 42 14 | {x: x * 2 for x in xs} += 42 15 | (x for x in xs) += 42 | ^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 16 | await x += 42 17 | (yield x) += 42 | | 14 | {x: x * 2 for x in xs} += 42 15 | (x for x in xs) += 42 16 | await x += 42 | ^^^^^^^ Syntax Error: Invalid augmented assignment target 17 | (yield x) += 42 18 | (yield from xs) += 42 | | 15 | (x for x in xs) += 42 16 | await x += 42 17 | (yield x) += 42 | ^^^^^^^ Syntax Error: Invalid augmented assignment target 18 | (yield from xs) += 42 19 | a < b < c += 42 | | 16 | await x += 42 17 | (yield x) += 42 18 | (yield from xs) += 42 | ^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 19 | a < b < c += 42 20 | foo() += 42 | | 17 | (yield x) += 42 18 | (yield from xs) += 42 19 | a < b < c += 42 | ^^^^^^^^^ Syntax Error: Invalid augmented assignment target 20 | foo() += 42 | | 18 | (yield from xs) += 42 19 | a < b < c += 42 20 | foo() += 42 | ^^^^^ Syntax Error: Invalid augmented assignment target 21 | 22 | f"{quux}" += 42 | | 20 | foo() += 42 21 | 22 | f"{quux}" += 42 | ^^^^^^^^^ Syntax Error: Invalid augmented assignment target 23 | f"{foo} and {bar}" += 42 | | 22 | f"{quux}" += 42 23 | f"{foo} and {bar}" += 42 | ^^^^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 24 | 25 | "foo" += 42 | | 23 | f"{foo} and {bar}" += 42 24 | 25 | "foo" += 42 | ^^^^^ Syntax Error: Invalid augmented assignment target 26 | b"foo" += 42 27 | 123 += 42 | | 25 | "foo" += 42 26 | b"foo" += 42 | ^^^^^^ Syntax Error: Invalid augmented assignment target 27 | 123 += 42 28 | True += 42 | | 25 | "foo" += 42 26 | b"foo" += 42 27 | 123 += 42 | ^^^ Syntax Error: Invalid augmented assignment target 28 | True += 42 29 | None += 42 | | 26 | b"foo" += 42 27 | 123 += 42 28 | True += 42 | ^^^^ Syntax Error: Invalid augmented assignment target 29 | None += 42 30 | ... += 42 | | 27 | 123 += 42 28 | True += 42 29 | None += 42 | ^^^^ Syntax Error: Invalid augmented assignment target 30 | ... += 42 31 | *foo() += 42 | | 28 | True += 42 29 | None += 42 30 | ... += 42 | ^^^ Syntax Error: Invalid augmented assignment target 31 | *foo() += 42 32 | [x, foo(), y] += [42, 42, 42] | | 29 | None += 42 30 | ... += 42 31 | *foo() += 42 | ^^^^^^ Syntax Error: Invalid augmented assignment target 32 | [x, foo(), y] += [42, 42, 42] 33 | [[a, b], [[42]], d] += [[1, 2], [[3]], 4] | | 30 | ... += 42 31 | *foo() += 42 32 | [x, foo(), y] += [42, 42, 42] | ^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 33 | [[a, b], [[42]], d] += [[1, 2], [[3]], 4] 34 | (x, foo(), y) += (42, 42, 42) | | 31 | *foo() += 42 32 | [x, foo(), y] += [42, 42, 42] 33 | [[a, b], [[42]], d] += [[1, 2], [[3]], 4] | ^^^^^^^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target 34 | (x, foo(), y) += (42, 42, 42) | | 32 | [x, foo(), y] += [42, 42, 42] 33 | [[a, b], [[42]], d] += [[1, 2], [[3]], 4] 34 | (x, foo(), y) += (42, 42, 42) | ^^^^^^^^^^^^^ Syntax Error: Invalid augmented assignment target invalid_syntax@statements__match__as_pattern_0.py.snap000064400000000000000000000106541046102023000345460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_0.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..198, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..197, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 127..197, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 132..146, cls: Name( ExprName { node_index: NodeIndex(None), range: 133..139, id: Name(""), ctx: Invalid, }, ), arguments: PatternArguments { range: 140..146, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 141..142, pattern: None, name: Some( Identifier { id: Name("a"), range: 141..142, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 144..145, pattern: None, name: Some( Identifier { id: Name("b"), range: 144..145, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 193..197, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 3 | # class pattern 4 | # v 5 | case (x as y)(a, b): | ^^^^^^ Syntax Error: Invalid value for a class pattern 6 | # ^^^^^^ 7 | # as-pattern | invalid_syntax@statements__match__as_pattern_1.py.snap000064400000000000000000000065151046102023000345500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..210, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..209, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 140..209, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 145..158, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 145..158, left: Name( ExprName { node_index: NodeIndex(None), range: 146..152, id: Name(""), ctx: Invalid, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 156..158, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 205..209, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 3 | # complex literal pattern 4 | # v 5 | case (x as y) + 1j: | ^^^^^^ Syntax Error: Expected a real number in complex literal pattern 6 | # ^^^^^^ 7 | # as-pattern | invalid_syntax@statements__match__as_pattern_2.py.snap000064400000000000000000000127721046102023000345530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..190, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..176, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 159..176, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 164..170, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 164..165, pattern: None, name: Some( Identifier { id: Name("x"), range: 164..165, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("y"), range: 169..170, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 171..176, target: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 171..175, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 173..175, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 176..176, id: Name(""), ctx: Invalid, }, ), value: None, simple: false, }, ), ], }, ], }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 185..189, }, ), ], }, ) ``` ## Errors | 2 | # This `as` pattern is unparenthesied so the parser never takes the path 3 | # where it might be confused as a complex literal pattern. 4 | case x as y + 1j: | ^ Syntax Error: Expected `:`, found `+` 5 | pass | | 2 | # This `as` pattern is unparenthesied so the parser never takes the path 3 | # where it might be confused as a complex literal pattern. 4 | case x as y + 1j: | ^ Syntax Error: Expected an expression 5 | pass | | 3 | # where it might be confused as a complex literal pattern. 4 | case x as y + 1j: 5 | pass | ^^^^^^^^ Syntax Error: Expected dedent, found indent | 4 | case x as y + 1j: 5 | pass | ^ Syntax Error: Expected a statement invalid_syntax@statements__match__as_pattern_3.py.snap000064400000000000000000000144411046102023000345470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_3.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..136, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..120, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 103..120, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 108..117, cls: Dict( ExprDict { node_index: NodeIndex(None), range: 108..109, items: [], }, ), arguments: PatternArguments { range: 109..117, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 110..116, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 110..111, pattern: None, name: Some( Identifier { id: Name("x"), range: 110..111, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("y"), range: 115..116, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 119..120, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), }, ), ], }, ], }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 131..135, }, ), ], }, ) ``` ## Errors | 2 | # Not in the mapping start token set, so the list parsing bails 3 | # v 4 | case {(x as y): 1}: | ^ Syntax Error: Expected `}`, found `(` 5 | pass | | 2 | # Not in the mapping start token set, so the list parsing bails 3 | # v 4 | case {(x as y): 1}: | ^ Syntax Error: Invalid value for a class pattern 5 | pass | | 2 | # Not in the mapping start token set, so the list parsing bails 3 | # v 4 | case {(x as y): 1}: | ^ Syntax Error: Expected newline, found `}` 5 | pass | | 2 | # Not in the mapping start token set, so the list parsing bails 3 | # v 4 | case {(x as y): 1}: | ^ Syntax Error: Expected a statement 5 | pass | | 2 | # Not in the mapping start token set, so the list parsing bails 3 | # v 4 | case {(x as y): 1}: | ^ Syntax Error: Expected a statement 5 | pass | | 3 | # v 4 | case {(x as y): 1}: 5 | pass | ^^^^^^^^ Syntax Error: Unexpected indentation | 4 | case {(x as y): 1}: 5 | pass | ^ Syntax Error: Expected a statement invalid_syntax@statements__match__as_pattern_4.py.snap000064400000000000000000000123771046102023000345560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/as_pattern_4.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..187, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..186, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 156..186, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 161..172, keys: [ Name( ExprName { node_index: NodeIndex(None), range: 162..163, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 167..168, id: Name("y"), ctx: Store, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 164..166, pattern: None, name: Some( Identifier { id: Name("as"), range: 164..166, node_index: NodeIndex(None), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 170..171, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 170..171, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 182..186, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 2 | # This `as` pattern is unparenthesized so the parser never takes the path 3 | # where it might be confused as a mapping key pattern. 4 | case {x as y: 1}: | ^ Syntax Error: Invalid mapping pattern key 5 | pass | | 2 | # This `as` pattern is unparenthesized so the parser never takes the path 3 | # where it might be confused as a mapping key pattern. 4 | case {x as y: 1}: | ^^ Syntax Error: Expected `:`, found `as` 5 | pass | | 2 | # This `as` pattern is unparenthesized so the parser never takes the path 3 | # where it might be confused as a mapping key pattern. 4 | case {x as y: 1}: | ^ Syntax Error: Expected `,`, found name 5 | pass | invalid_syntax@statements__match__invalid_class_pattern.py.snap000064400000000000000000000530251046102023000365360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/invalid_class_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..383, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 44..285, subject: Name( ExprName { node_index: NodeIndex(None), range: 50..57, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 63..97, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 68..83, cls: Name( ExprName { node_index: NodeIndex(None), range: 68..71, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 71..83, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 72..82, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 80..80, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 81..82, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 93..97, }, ), ], }, MatchCase { range: 102..135, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 107..121, cls: Name( ExprName { node_index: NodeIndex(None), range: 107..110, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 110..121, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 111..120, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 118..118, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 119..120, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 131..135, }, ), ], }, MatchCase { range: 140..174, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 145..160, cls: Name( ExprName { node_index: NodeIndex(None), range: 145..148, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 148..160, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 149..159, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 157..157, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 158..159, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 170..174, }, ), ], }, MatchCase { range: 179..217, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 184..203, cls: Name( ExprName { node_index: NodeIndex(None), range: 184..187, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 187..203, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 188..202, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 200..200, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 201..202, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 213..217, }, ), ], }, MatchCase { range: 222..249, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 227..235, cls: Name( ExprName { node_index: NodeIndex(None), range: 227..230, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 230..235, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 231..234, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 233..233, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 233..234, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 233..234, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 245..249, }, ), ], }, MatchCase { range: 254..285, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 259..271, cls: Name( ExprName { node_index: NodeIndex(None), range: 259..262, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 262..271, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 263..270, node_index: NodeIndex(None), attr: Identifier { id: Name(""), range: 269..269, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 269..270, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 269..270, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 281..285, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | # Invalid keyword pattern in class argument 2 | match subject: 3 | case Foo(x as y = 1): | ^^^^^^ Syntax Error: Expected an identifier for the keyword pattern 4 | pass 5 | case Foo(x | y = 1): | | 3 | case Foo(x as y = 1): 4 | pass 5 | case Foo(x | y = 1): | ^^^^^ Syntax Error: Expected an identifier for the keyword pattern 6 | pass 7 | case Foo([x, y] = 1): | | 5 | case Foo(x | y = 1): 6 | pass 7 | case Foo([x, y] = 1): | ^^^^^^ Syntax Error: Expected an identifier for the keyword pattern 8 | pass 9 | case Foo({False: 0} = 1): | | 7 | case Foo([x, y] = 1): 8 | pass 9 | case Foo({False: 0} = 1): | ^^^^^^^^^^ Syntax Error: Expected an identifier for the keyword pattern 10 | pass 11 | case Foo(1=1): | | 9 | case Foo({False: 0} = 1): 10 | pass 11 | case Foo(1=1): | ^ Syntax Error: Expected an identifier for the keyword pattern 12 | pass 13 | case Foo(Bar()=1): | | 11 | case Foo(1=1): 12 | pass 13 | case Foo(Bar()=1): | ^^^^^ Syntax Error: Expected an identifier for the keyword pattern 14 | pass 15 | # Positional pattern cannot follow keyword pattern | invalid_syntax@statements__match__invalid_lhs_or_rhs_pattern.py.snap000064400000000000000000001725141046102023000376000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/invalid_lhs_or_rhs_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..695, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..332, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..25, id: Name("invalid_lhs_pattern"), ctx: Load, }, ), cases: [ MatchCase { range: 31..60, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 36..46, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 36..46, left: Call( ExprCall { node_index: NodeIndex(None), range: 36..41, func: Name( ExprName { node_index: NodeIndex(None), range: 36..39, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 39..41, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..46, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 56..60, }, ), ], }, MatchCase { range: 65..90, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 70..76, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 70..76, left: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Store, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 74..76, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 86..90, }, ), ], }, MatchCase { range: 95..120, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 100..106, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 100..106, left: Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("_"), ctx: Store, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..106, value: Complex { real: 0.0, imag: 3.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 116..120, }, ), ], }, MatchCase { range: 125..156, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 130..142, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 130..142, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 131..136, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 131..132, value: Int( 1, ), }, ), op: BitOr, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 2, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 140..142, value: Complex { real: 0.0, imag: 4.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 152..156, }, ), ], }, MatchCase { range: 161..191, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 166..177, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 166..177, left: List( ExprList { node_index: NodeIndex(None), range: 166..172, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 167..168, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 170..171, value: Int( 2, ), }, ), ], ctx: Store, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 175..177, value: Complex { real: 0.0, imag: 5.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 187..191, }, ), ], }, MatchCase { range: 196..229, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 201..215, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 201..215, left: Dict( ExprDict { node_index: NodeIndex(None), range: 201..210, items: [ DictItem { key: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 202..206, value: true, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 208..209, value: Int( 1, ), }, ), }, ], }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..215, value: Complex { real: 0.0, imag: 6.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 225..229, }, ), ], }, MatchCase { range: 234..260, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 239..246, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 239..246, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..241, value: Complex { real: 0.0, imag: 1.0, }, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 244..246, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 256..260, }, ), ], }, MatchCase { range: 265..292, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 270..278, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 270..278, left: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 270..273, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 271..273, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 276..278, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 288..292, }, ), ], }, MatchCase { range: 297..332, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 302..318, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 302..318, left: Call( ExprCall { node_index: NodeIndex(None), range: 302..313, func: Name( ExprName { node_index: NodeIndex(None), range: 302..305, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 305..313, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 306..312, id: Name(""), ctx: Invalid, }, ), ], keywords: [], }, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 316..318, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 328..332, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 334..625, subject: Name( ExprName { node_index: NodeIndex(None), range: 340..359, id: Name("invalid_rhs_pattern"), ctx: Load, }, ), cases: [ MatchCase { range: 365..393, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 370..379, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 370..379, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 370..371, value: Int( 1, ), }, ), op: Add, right: Call( ExprCall { node_index: NodeIndex(None), range: 374..379, func: Name( ExprName { node_index: NodeIndex(None), range: 374..377, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 377..379, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 389..393, }, ), ], }, MatchCase { range: 398..422, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 403..408, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 403..408, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 403..404, value: Int( 2, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 407..408, id: Name("x"), ctx: Store, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 418..422, }, ), ], }, MatchCase { range: 427..451, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 432..437, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 432..437, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 432..433, value: Int( 3, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 436..437, id: Name("_"), ctx: Store, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 447..451, }, ), ], }, MatchCase { range: 456..486, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 461..472, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 461..472, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 461..462, value: Int( 4, ), }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 466..471, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 466..467, value: Int( 1, ), }, ), op: BitOr, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 470..471, value: Int( 2, ), }, ), }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 482..486, }, ), ], }, MatchCase { range: 491..520, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 496..506, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 496..506, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 496..497, value: Int( 5, ), }, ), op: Add, right: List( ExprList { node_index: NodeIndex(None), range: 500..506, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 501..502, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 504..505, value: Int( 2, ), }, ), ], ctx: Store, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 516..520, }, ), ], }, MatchCase { range: 525..557, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 530..543, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 530..543, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 530..531, value: Int( 6, ), }, ), op: Add, right: Dict( ExprDict { node_index: NodeIndex(None), range: 534..543, items: [ DictItem { key: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 535..539, value: true, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 541..542, value: Int( 1, ), }, ), }, ], }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 553..557, }, ), ], }, MatchCase { range: 562..586, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 567..572, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 567..572, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 567..568, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 571..572, value: Int( 2, ), }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 582..586, }, ), ], }, MatchCase { range: 591..625, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 596..611, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 596..611, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 596..597, value: Int( 1, ), }, ), op: Add, right: Call( ExprCall { node_index: NodeIndex(None), range: 600..611, func: Name( ExprName { node_index: NodeIndex(None), range: 600..603, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 603..611, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 604..610, id: Name(""), ctx: Invalid, }, ), ], keywords: [], }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 621..625, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 627..694, subject: Name( ExprName { node_index: NodeIndex(None), range: 633..656, id: Name("invalid_lhs_rhs_pattern"), ctx: Load, }, ), cases: [ MatchCase { range: 662..694, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 667..680, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 667..680, left: Call( ExprCall { node_index: NodeIndex(None), range: 667..672, func: Name( ExprName { node_index: NodeIndex(None), range: 667..670, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 670..672, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), op: Add, right: Call( ExprCall { node_index: NodeIndex(None), range: 675..680, func: Name( ExprName { node_index: NodeIndex(None), range: 675..678, id: Name("Bar"), ctx: Load, }, ), arguments: Arguments { range: 678..680, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 690..694, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | match invalid_lhs_pattern: 2 | case Foo() + 1j: | ^^^^^ Syntax Error: Expected a real number in complex literal pattern 3 | pass 4 | case x + 2j: | | 2 | case Foo() + 1j: 3 | pass 4 | case x + 2j: | ^ Syntax Error: Expected a real number in complex literal pattern 5 | pass 6 | case _ + 3j: | | 4 | case x + 2j: 5 | pass 6 | case _ + 3j: | ^ Syntax Error: Expected a real number in complex literal pattern 7 | pass 8 | case (1 | 2) + 4j: | | 6 | case _ + 3j: 7 | pass 8 | case (1 | 2) + 4j: | ^^^^^ Syntax Error: Expected a real number in complex literal pattern 9 | pass 10 | case [1, 2] + 5j: | | 8 | case (1 | 2) + 4j: 9 | pass 10 | case [1, 2] + 5j: | ^^^^^^ Syntax Error: Expected a real number in complex literal pattern 11 | pass 12 | case {True: 1} + 6j: | | 10 | case [1, 2] + 5j: 11 | pass 12 | case {True: 1} + 6j: | ^^^^^^^^^ Syntax Error: Expected a real number in complex literal pattern 13 | pass 14 | case 1j + 2j: | | 12 | case {True: 1} + 6j: 13 | pass 14 | case 1j + 2j: | ^^ Syntax Error: Expected a real number in complex literal pattern 15 | pass 16 | case -1j + 2j: | | 14 | case 1j + 2j: 15 | pass 16 | case -1j + 2j: | ^^^ Syntax Error: Expected a real number in complex literal pattern 17 | pass 18 | case Foo(a as b) + 1j: | | 16 | case -1j + 2j: 17 | pass 18 | case Foo(a as b) + 1j: | ^^^^^^^^^^^ Syntax Error: Expected a real number in complex literal pattern 19 | pass | | 21 | match invalid_rhs_pattern: 22 | case 1 + Foo(): | ^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 23 | pass 24 | case 2 + x: | | 22 | case 1 + Foo(): 23 | pass 24 | case 2 + x: | ^ Syntax Error: Expected an imaginary number in complex literal pattern 25 | pass 26 | case 3 + _: | | 24 | case 2 + x: 25 | pass 26 | case 3 + _: | ^ Syntax Error: Expected an imaginary number in complex literal pattern 27 | pass 28 | case 4 + (1 | 2): | | 26 | case 3 + _: 27 | pass 28 | case 4 + (1 | 2): | ^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 29 | pass 30 | case 5 + [1, 2]: | | 28 | case 4 + (1 | 2): 29 | pass 30 | case 5 + [1, 2]: | ^^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 31 | pass 32 | case 6 + {True: 1}: | | 30 | case 5 + [1, 2]: 31 | pass 32 | case 6 + {True: 1}: | ^^^^^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 33 | pass 34 | case 1 + 2: | | 32 | case 6 + {True: 1}: 33 | pass 34 | case 1 + 2: | ^ Syntax Error: Expected an imaginary number in complex literal pattern 35 | pass 36 | case 1 + Foo(a as b): | | 34 | case 1 + 2: 35 | pass 36 | case 1 + Foo(a as b): | ^^^^^^^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 37 | pass | | 39 | match invalid_lhs_rhs_pattern: 40 | case Foo() + Bar(): | ^^^^^ Syntax Error: Expected a real number in complex literal pattern 41 | pass | | 39 | match invalid_lhs_rhs_pattern: 40 | case Foo() + Bar(): | ^^^^^ Syntax Error: Expected an imaginary number in complex literal pattern 41 | pass | invalid_syntax@statements__match__invalid_mapping_pattern.py.snap000064400000000000000000000721461046102023000370710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/invalid_mapping_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..509, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 61..209, subject: Name( ExprName { node_index: NodeIndex(None), range: 67..74, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 80..105, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 85..91, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 86..90, value: Name( ExprName { node_index: NodeIndex(None), range: 87..90, id: Name("key"), ctx: Store, }, ), ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 90..90, value: Name( ExprName { node_index: NodeIndex(None), range: 90..90, id: Name(""), ctx: Invalid, }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 101..105, }, ), ], }, MatchCase { range: 110..138, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 115..124, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 116..120, value: Name( ExprName { node_index: NodeIndex(None), range: 117..120, id: Name("key"), ctx: Store, }, ), ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 122..123, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 134..138, }, ), ], }, MatchCase { range: 143..170, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 148..156, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 149..153, value: Name( ExprName { node_index: NodeIndex(None), range: 150..153, id: Name("key"), ctx: Store, }, ), ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 154..155, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 154..155, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 166..170, }, ), ], }, MatchCase { range: 175..209, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 180..195, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 181..185, value: Name( ExprName { node_index: NodeIndex(None), range: 182..185, id: Name("key"), ctx: Store, }, ), ctx: Store, }, ), NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 187..191, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 185..185, value: Name( ExprName { node_index: NodeIndex(None), range: 185..185, id: Name(""), ctx: Invalid, }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 193..194, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 193..194, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 205..209, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 305..462, subject: Name( ExprName { node_index: NodeIndex(None), range: 311..318, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 324..360, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 329..346, keys: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 338..342, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 344..345, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 344..345, value: Int( 1, ), }, ), }, ), ], rest: Some( Identifier { id: Name("rest"), range: 332..336, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 356..360, }, ), ], }, MatchCase { range: 365..411, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 370..397, keys: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 389..393, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 395..396, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 395..396, value: Int( 1, ), }, ), }, ), ], rest: Some( Identifier { id: Name("rest2"), range: 382..387, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 407..411, }, ), ], }, MatchCase { range: 416..462, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 421..448, keys: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 431..435, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 437..438, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 437..438, value: Int( 1, ), }, ), }, ), ], rest: Some( Identifier { id: Name("rest2"), range: 442..447, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 458..462, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 464..509, subject: Name( ExprName { node_index: NodeIndex(None), range: 470..477, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 483..509, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 488..504, keys: [ Call( ExprCall { node_index: NodeIndex(None), range: 489..500, func: Name( ExprName { node_index: NodeIndex(None), range: 489..492, id: Name("Foo"), ctx: Load, }, ), arguments: Arguments { range: 492..500, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 493..499, id: Name(""), ctx: Invalid, }, ), ], keywords: [], }, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 502..503, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 502..503, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 506..509, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 506..509, }, ), }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | # Starred expression is not allowed as a mapping pattern key 2 | match subject: 3 | case {*key}: | ^^^^ Syntax Error: Star pattern cannot be used here 4 | pass 5 | case {*key: 1}: | | 1 | # Starred expression is not allowed as a mapping pattern key 2 | match subject: 3 | case {*key}: | ^ Syntax Error: Expected `:`, found `}` 4 | pass 5 | case {*key: 1}: | | 3 | case {*key}: 4 | pass 5 | case {*key: 1}: | ^^^^ Syntax Error: Star pattern cannot be used here 6 | pass 7 | case {*key 1}: | | 5 | case {*key: 1}: 6 | pass 7 | case {*key 1}: | ^^^^ Syntax Error: Star pattern cannot be used here 8 | pass 9 | case {*key, None: 1}: | | 5 | case {*key: 1}: 6 | pass 7 | case {*key 1}: | ^ Syntax Error: Expected `:`, found int 8 | pass 9 | case {*key, None: 1}: | | 7 | case {*key 1}: 8 | pass 9 | case {*key, None: 1}: | ^^^^ Syntax Error: Star pattern cannot be used here 10 | pass | | 7 | case {*key 1}: 8 | pass 9 | case {*key, None: 1}: | ^ Syntax Error: Expected `:`, found `,` 10 | pass | | 13 | # Multiple double star patterns are not allowed 14 | match subject: 15 | case {**rest, None: 1}: | ^^^^^^^ Syntax Error: Pattern cannot follow a double star pattern 16 | pass 17 | case {**rest1, **rest2, None: 1}: | | 15 | case {**rest, None: 1}: 16 | pass 17 | case {**rest1, **rest2, None: 1}: | ^^^^^^^ Syntax Error: Only one double star pattern is allowed 18 | pass 19 | case {**rest1, None: 1, **rest2}: | | 15 | case {**rest, None: 1}: 16 | pass 17 | case {**rest1, **rest2, None: 1}: | ^^^^^^^ Syntax Error: Pattern cannot follow a double star pattern 18 | pass 19 | case {**rest1, None: 1, **rest2}: | | 17 | case {**rest1, **rest2, None: 1}: 18 | pass 19 | case {**rest1, None: 1, **rest2}: | ^^^^^^^ Syntax Error: Pattern cannot follow a double star pattern 20 | pass | | 17 | case {**rest1, **rest2, None: 1}: 18 | pass 19 | case {**rest1, None: 1, **rest2}: | ^^^^^^^ Syntax Error: Only one double star pattern is allowed 20 | pass | | 22 | match subject: 23 | case {Foo(a as b): 1}: ... | ^^^^^^^^^^^ Syntax Error: Invalid mapping pattern key invalid_syntax@statements__match__star_pattern_usage.py.snap000064400000000000000000000763401046102023000360650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/star_pattern_usage.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..526, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 57..407, subject: Name( ExprName { node_index: NodeIndex(None), range: 63..70, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 76..97, node_index: NodeIndex(None), pattern: MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 81..83, name: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 93..97, }, ), ], }, MatchCase { range: 102..128, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 107..114, pattern: Some( MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 107..109, name: None, }, ), ), name: Some( Identifier { id: Name("x"), range: 113..114, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 124..128, }, ), ], }, MatchCase { range: 133..156, node_index: NodeIndex(None), pattern: MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 138..142, name: Some( Identifier { id: Name("foo"), range: 139..142, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 152..156, }, ), ], }, MatchCase { range: 161..188, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 166..174, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 166..170, name: Some( Identifier { id: Name("foo"), range: 167..170, node_index: NodeIndex(None), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 173..174, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 173..174, value: Int( 1, ), }, ), }, ), ], }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 184..188, }, ), ], }, MatchCase { range: 193..220, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 198..206, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 198..199, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 198..199, value: Int( 1, ), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 202..206, name: Some( Identifier { id: Name("foo"), range: 203..206, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 216..220, }, ), ], }, MatchCase { range: 225..251, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 230..237, cls: Name( ExprName { node_index: NodeIndex(None), range: 230..233, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 233..237, node_index: NodeIndex(None), patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 234..236, name: None, }, ), ], keywords: [], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 247..251, }, ), ], }, MatchCase { range: 256..284, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 261..270, cls: Name( ExprName { node_index: NodeIndex(None), range: 261..264, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 264..270, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 265..269, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 265..266, node_index: NodeIndex(None), }, pattern: MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 267..269, name: None, }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 280..284, }, ), ], }, MatchCase { range: 289..312, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 294..298, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 295..297, value: Name( ExprName { node_index: NodeIndex(None), range: 296..297, id: Name("_"), ctx: Store, }, ), ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 297..297, value: Name( ExprName { node_index: NodeIndex(None), range: 297..297, id: Name(""), ctx: Invalid, }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 308..312, }, ), ], }, MatchCase { range: 317..343, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 322..329, keys: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 323..325, value: Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("_"), ctx: Store, }, ), ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 327..328, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 327..328, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 339..343, }, ), ], }, MatchCase { range: 348..377, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 353..363, keys: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 354..358, }, ), ], patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 360..362, name: None, }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 373..377, }, ), ], }, MatchCase { range: 382..407, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 387..393, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 387..393, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 387..388, value: Int( 1, ), }, ), op: Add, right: Starred( ExprStarred { node_index: NodeIndex(None), range: 391..393, value: Name( ExprName { node_index: NodeIndex(None), range: 392..393, id: Name("_"), ctx: Store, }, ), ctx: Store, }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 403..407, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 465..525, subject: Name( ExprName { node_index: NodeIndex(None), range: 471..478, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 484..525, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 489..511, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 490..495, name: Some( Identifier { id: Name("head"), range: 491..495, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 497..503, pattern: None, name: Some( Identifier { id: Name("middle"), range: 497..503, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 505..510, name: Some( Identifier { id: Name("tail"), range: 506..510, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 521..525, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | # Star pattern is only allowed inside a sequence pattern 2 | match subject: 3 | case *_: | ^^ Syntax Error: Star pattern cannot be used here 4 | pass 5 | case *_ as x: | | 3 | case *_: 4 | pass 5 | case *_ as x: | ^^ Syntax Error: Star pattern cannot be used here 6 | pass 7 | case *foo: | | 5 | case *_ as x: 6 | pass 7 | case *foo: | ^^^^ Syntax Error: Star pattern cannot be used here 8 | pass 9 | case *foo | 1: | | 7 | case *foo: 8 | pass 9 | case *foo | 1: | ^^^^ Syntax Error: Star pattern cannot be used here 10 | pass 11 | case 1 | *foo: | | 9 | case *foo | 1: 10 | pass 11 | case 1 | *foo: | ^^^^ Syntax Error: Star pattern cannot be used here 12 | pass 13 | case Foo(*_): | | 11 | case 1 | *foo: 12 | pass 13 | case Foo(*_): | ^^ Syntax Error: Star pattern cannot be used here 14 | pass 15 | case Foo(x=*_): | | 13 | case Foo(*_): 14 | pass 15 | case Foo(x=*_): | ^^ Syntax Error: Star pattern cannot be used here 16 | pass 17 | case {*_}: | | 15 | case Foo(x=*_): 16 | pass 17 | case {*_}: | ^^ Syntax Error: Star pattern cannot be used here 18 | pass 19 | case {*_: 1}: | | 15 | case Foo(x=*_): 16 | pass 17 | case {*_}: | ^ Syntax Error: Expected `:`, found `}` 18 | pass 19 | case {*_: 1}: | | 17 | case {*_}: 18 | pass 19 | case {*_: 1}: | ^^ Syntax Error: Star pattern cannot be used here 20 | pass 21 | case {None: *_}: | | 19 | case {*_: 1}: 20 | pass 21 | case {None: *_}: | ^^ Syntax Error: Star pattern cannot be used here 22 | pass 23 | case 1 + *_: | | 21 | case {None: *_}: 22 | pass 23 | case 1 + *_: | ^^ Syntax Error: Star pattern cannot be used here 24 | pass | ## Semantic Syntax Errors | 7 | case *foo: 8 | pass 9 | case *foo | 1: | ^^^^^^^^ Syntax Error: alternative patterns bind different names 10 | pass 11 | case 1 | *foo: | | 9 | case *foo | 1: 10 | pass 11 | case 1 | *foo: | ^^^^^^^^ Syntax Error: alternative patterns bind different names 12 | pass 13 | case Foo(*_): | | 26 | # Sequence pattern can contain at most one star pattern 27 | match subject: 28 | case [*head, middle, *tail]: | ^^^^^ Syntax Error: multiple starred names in sequence pattern 29 | pass | invalid_syntax@statements__match__unary_add_usage.py.snap000064400000000000000000000574071046102023000353300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/match/unary_add_usage.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..269, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 74..268, subject: Name( ExprName { node_index: NodeIndex(None), range: 80..87, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 93..114, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 98..100, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 98..100, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 99..100, value: Int( 1, ), }, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 110..114, }, ), ], }, MatchCase { range: 119..149, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 124..135, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 124..125, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 124..125, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 128..130, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 128..130, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 129..130, value: Int( 2, ), }, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 133..135, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 133..135, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 134..135, value: Int( 3, ), }, ), }, ), }, ), ], }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 145..149, }, ), ], }, MatchCase { range: 154..184, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 159..170, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 160..161, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..161, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 163..165, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 163..165, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 2, ), }, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 167..169, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 167..169, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 168..169, value: Int( 3, ), }, ), }, ), }, ), ], }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 180..184, }, ), ], }, MatchCase { range: 189..223, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 194..209, cls: Name( ExprName { node_index: NodeIndex(None), range: 194..197, id: Name("Foo"), ctx: Load, }, ), arguments: PatternArguments { range: 197..209, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 198..202, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 198..199, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 200..202, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 200..202, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 1, ), }, ), }, ), }, ), }, PatternKeyword { range: 204..208, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 204..205, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 206..208, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 206..208, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 207..208, value: Int( 2, ), }, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 219..223, }, ), ], }, MatchCase { range: 228..268, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 233..254, keys: [ BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 234..238, value: true, }, ), BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 244..249, value: false, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 240..242, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 240..242, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 1, ), }, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 251..253, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 251..253, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 252..253, value: Int( 2, ), }, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 264..268, }, ), ], }, ], }, ), ], }, ) ``` ## Errors | 1 | # Unary addition isn't allowed but we parse it for better error recovery. 2 | match subject: 3 | case +1: | ^^ Syntax Error: Unary '+' is not allowed as a literal pattern 4 | pass 5 | case 1 | +2 | -3: | | 3 | case +1: 4 | pass 5 | case 1 | +2 | -3: | ^^ Syntax Error: Unary '+' is not allowed as a literal pattern 6 | pass 7 | case [1, +2, -3]: | | 5 | case 1 | +2 | -3: 6 | pass 7 | case [1, +2, -3]: | ^^ Syntax Error: Unary '+' is not allowed as a literal pattern 8 | pass 9 | case Foo(x=+1, y=-2): | | 7 | case [1, +2, -3]: 8 | pass 9 | case Foo(x=+1, y=-2): | ^^ Syntax Error: Unary '+' is not allowed as a literal pattern 10 | pass 11 | case {True: +1, False: -2}: | | 9 | case Foo(x=+1, y=-2): 10 | pass 11 | case {True: +1, False: -2}: | ^^ Syntax Error: Unary '+' is not allowed as a literal pattern 12 | pass | invalid_syntax@statements__with__ambiguous_lpar_with_items.py.snap000064400000000000000000002313561046102023000373170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/with/ambiguous_lpar_with_items.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..950, body: [ With( StmtWith { node_index: NodeIndex(None), range: 163..188, is_async: false, items: [ WithItem { range: 168..182, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 168..182, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 169..174, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 176..181, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 185..188, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 185..188, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 189..219, is_async: false, items: [ WithItem { range: 194..208, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 194..208, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 195..200, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 202..207, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 213..214, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 213..214, id: Name("f"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 216..219, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 216..219, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 220..252, is_async: false, items: [ WithItem { range: 225..239, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 225..239, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 226..231, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 233..238, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 241..246, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 241..246, id: Name("item3"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 249..252, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 249..252, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 253..270, is_async: false, items: [ WithItem { range: 258..265, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 259..264, value: Name( ExprName { node_index: NodeIndex(None), range: 260..264, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 267..270, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 267..270, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 271..293, is_async: false, items: [ WithItem { range: 276..288, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 277..282, value: Name( ExprName { node_index: NodeIndex(None), range: 278..282, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 290..293, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 290..293, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 294..321, is_async: false, items: [ WithItem { range: 300..315, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 300..310, target: Name( ExprName { node_index: NodeIndex(None), range: 300..304, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 308..310, value: Int( 10, ), }, ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 314..315, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 318..321, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 318..321, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 322..357, is_async: false, items: [ WithItem { range: 328..333, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 328..333, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 335..351, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 335..346, target: Name( ExprName { node_index: NodeIndex(None), range: 335..340, id: Name("item2"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 344..346, value: Int( 10, ), }, ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 350..351, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 354..357, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 354..357, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 358..396, is_async: false, items: [ WithItem { range: 363..384, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 363..384, elt: Name( ExprName { node_index: NodeIndex(None), range: 364..365, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 366..384, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 370..371, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 375..384, func: Name( ExprName { node_index: NodeIndex(None), range: 375..380, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 380..384, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 381..383, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 386..390, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 386..390, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 393..396, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 393..396, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 397..410, is_async: false, items: [ WithItem { range: 402..410, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 402..410, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 403..407, id: Name("item"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 409..410, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 411..429, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 415..416, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 420..429, func: Name( ExprName { node_index: NodeIndex(None), range: 420..425, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 425..429, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 426..428, value: Int( 10, ), }, ), ], keywords: [], }, }, ), body: [], orelse: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 432..435, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 432..435, }, ), }, ), With( StmtWith { node_index: NodeIndex(None), range: 496..515, is_async: false, items: [ WithItem { range: 502..509, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 503..508, value: Name( ExprName { node_index: NodeIndex(None), range: 504..508, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 512..515, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 512..515, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 517..551, is_async: false, items: [ WithItem { range: 522..539, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 522..539, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 523..525, value: Name( ExprName { node_index: NodeIndex(None), range: 524..525, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 526..539, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 530..531, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 535..539, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 541..545, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 541..545, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 548..551, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 548..551, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 552..567, is_async: false, items: [ WithItem { range: 557..567, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 557..567, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 558..563, id: Name("item1"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 565..567, value: Name( ExprName { node_index: NodeIndex(None), range: 566..567, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 568..588, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 572..573, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 577..588, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 577..581, id: Name("iter"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 583..588, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [], orelse: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 591..594, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 591..594, }, ), }, ), With( StmtWith { node_index: NodeIndex(None), range: 595..617, is_async: false, items: [ WithItem { range: 601..607, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 601..602, id: Name("x"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 606..607, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 609..611, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 609..611, value: Name( ExprName { node_index: NodeIndex(None), range: 610..611, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 614..617, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 614..617, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 618..640, is_async: false, items: [ WithItem { range: 624..626, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 624..626, value: Name( ExprName { node_index: NodeIndex(None), range: 625..626, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 628..634, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 628..629, id: Name("y"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 633..634, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 637..640, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 637..640, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 641..663, is_async: false, items: [ WithItem { range: 646..658, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 646..658, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 647..648, id: Name("x"), ctx: Load, }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 650..657, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 656..657, id: Name("y"), ctx: Load, }, ), ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 660..663, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 660..663, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 664..689, is_async: false, items: [ WithItem { range: 669..684, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 669..684, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 670..671, id: Name("x"), ctx: Load, }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 673..683, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 679..683, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 679..680, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 682..683, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 686..689, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 686..689, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 690..717, is_async: false, items: [ WithItem { range: 695..712, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 695..712, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 696..697, id: Name("x"), ctx: Load, }, ), YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 699..711, value: Name( ExprName { node_index: NodeIndex(None), range: 710..711, id: Name("y"), ctx: Load, }, ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 714..717, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 714..717, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 718..734, is_async: false, items: [ WithItem { range: 724..730, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 724..725, id: Name("x"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 729..730, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 732..733, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 732..733, id: Name("y"), ctx: Load, }, ), optional_vars: None, }, ], body: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 738..744, target: Name( ExprName { node_index: NodeIndex(None), range: 738..739, id: Name("f"), ctx: Store, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 741..744, }, ), value: None, simple: true, }, ), With( StmtWith { node_index: NodeIndex(None), range: 745..777, is_async: false, items: [ WithItem { range: 750..771, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 750..766, elt: Name( ExprName { node_index: NodeIndex(None), range: 751..752, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 753..766, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 757..758, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 762..766, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 770..771, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 774..777, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 774..777, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 837..854, is_async: false, items: [ WithItem { range: 843..853, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 844..848, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 852..853, id: Name("f"), ctx: Store, }, ), ), }, ], body: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 857..860, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 857..860, }, ), }, ), With( StmtWith { node_index: NodeIndex(None), range: 862..878, is_async: false, items: [ WithItem { range: 868..877, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 868..872, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 876..877, id: Name("f"), ctx: Store, }, ), ), }, ], body: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 880..886, target: Name( ExprName { node_index: NodeIndex(None), range: 880..881, id: Name("x"), ctx: Store, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 883..886, }, ), value: None, simple: true, }, ), With( StmtWith { node_index: NodeIndex(None), range: 887..904, is_async: false, items: [ WithItem { range: 893..903, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 893..897, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 901..903, id: Name("f1"), ctx: Store, }, ), ), }, ], body: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 908..915, target: Name( ExprName { node_index: NodeIndex(None), range: 908..910, id: Name("f2"), ctx: Store, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 912..915, }, ), value: None, simple: true, }, ), With( StmtWith { node_index: NodeIndex(None), range: 916..950, is_async: false, items: [ WithItem { range: 922..932, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 922..927, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 931..932, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 934..944, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 934..944, target: Name( ExprName { node_index: NodeIndex(None), range: 934..939, id: Name("item2"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 943..944, value: Int( 0, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 947..950, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 947..950, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 2 | # These cases should raise the correct syntax error and recover properly. 3 | 4 | with (item1, item2),: ... | ^ Syntax Error: Trailing comma not allowed 5 | with (item1, item2), as f: ... 6 | with (item1, item2), item3,: ... | | 4 | with (item1, item2),: ... 5 | with (item1, item2), as f: ... | ^^ Syntax Error: Expected `,`, found `as` 6 | with (item1, item2), item3,: ... 7 | with (*item): ... | | 4 | with (item1, item2),: ... 5 | with (item1, item2), as f: ... 6 | with (item1, item2), item3,: ... | ^ Syntax Error: Trailing comma not allowed 7 | with (*item): ... 8 | with (*item) as f: ... | | 5 | with (item1, item2), as f: ... 6 | with (item1, item2), item3,: ... 7 | with (*item): ... | ^^^^^ Syntax Error: Starred expression cannot be used here 8 | with (*item) as f: ... 9 | with (item := 10 as f): ... | | 6 | with (item1, item2), item3,: ... 7 | with (*item): ... 8 | with (*item) as f: ... | ^^^^^ Syntax Error: Starred expression cannot be used here 9 | with (item := 10 as f): ... 10 | with (item1, item2 := 10 as f): ... | | 7 | with (*item): ... 8 | with (*item) as f: ... 9 | with (item := 10 as f): ... | ^^^^^^^^^^ Syntax Error: Unparenthesized named expression cannot be used here 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... | | 8 | with (*item) as f: ... 9 | with (item := 10 as f): ... 10 | with (item1, item2 := 10 as f): ... | ^^^^^^^^^^^ Syntax Error: Unparenthesized named expression cannot be used here 11 | with (x for x in range(10), item): ... 12 | with (item, x for x in range(10)): ... | | 9 | with (item := 10 as f): ... 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... | ^ Syntax Error: Expected `)`, found `,` 12 | with (item, x for x in range(10)): ... | | 9 | with (item := 10 as f): ... 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... | ^ Syntax Error: Expected `,`, found `)` 12 | with (item, x for x in range(10)): ... | | 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... 12 | with (item, x for x in range(10)): ... | ^^^ Syntax Error: Expected `)`, found `for` 13 | 14 | # Make sure the parser doesn't report the same error twice | | 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... 12 | with (item, x for x in range(10)): ... | ^ Syntax Error: Expected `:`, found `)` 13 | 14 | # Make sure the parser doesn't report the same error twice | | 10 | with (item1, item2 := 10 as f): ... 11 | with (x for x in range(10), item): ... 12 | with (item, x for x in range(10)): ... | ^ Syntax Error: Expected a statement 13 | 14 | # Make sure the parser doesn't report the same error twice | | 14 | # Make sure the parser doesn't report the same error twice 15 | with ((*item)): ... | ^^^^^ Syntax Error: Starred expression cannot be used here 16 | 17 | with (*x for x in iter, item): ... | | 15 | with ((*item)): ... 16 | 17 | with (*x for x in iter, item): ... | ^ Syntax Error: Expected `)`, found `,` 18 | with (item1, *x for x in iter, item2): ... 19 | with (x as f, *y): ... | | 15 | with ((*item)): ... 16 | 17 | with (*x for x in iter, item): ... | ^ Syntax Error: Expected `,`, found `)` 18 | with (item1, *x for x in iter, item2): ... 19 | with (x as f, *y): ... | | 17 | with (*x for x in iter, item): ... 18 | with (item1, *x for x in iter, item2): ... | ^^^ Syntax Error: Expected `)`, found `for` 19 | with (x as f, *y): ... 20 | with (*x, y as f): ... | | 17 | with (*x for x in iter, item): ... 18 | with (item1, *x for x in iter, item2): ... | ^ Syntax Error: Expected `:`, found `)` 19 | with (x as f, *y): ... 20 | with (*x, y as f): ... | | 17 | with (*x for x in iter, item): ... 18 | with (item1, *x for x in iter, item2): ... | ^ Syntax Error: Expected a statement 19 | with (x as f, *y): ... 20 | with (*x, y as f): ... | | 17 | with (*x for x in iter, item): ... 18 | with (item1, *x for x in iter, item2): ... 19 | with (x as f, *y): ... | ^^ Syntax Error: Starred expression cannot be used here 20 | with (*x, y as f): ... 21 | with (x, yield y): ... | | 18 | with (item1, *x for x in iter, item2): ... 19 | with (x as f, *y): ... 20 | with (*x, y as f): ... | ^^ Syntax Error: Starred expression cannot be used here 21 | with (x, yield y): ... 22 | with (x, yield y, z): ... | | 19 | with (x as f, *y): ... 20 | with (*x, y as f): ... 21 | with (x, yield y): ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here 22 | with (x, yield y, z): ... 23 | with (x, yield from y): ... | | 20 | with (*x, y as f): ... 21 | with (x, yield y): ... 22 | with (x, yield y, z): ... | ^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 23 | with (x, yield from y): ... 24 | with (x as f, y) as f: ... | | 21 | with (x, yield y): ... 22 | with (x, yield y, z): ... 23 | with (x, yield from y): ... | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 24 | with (x as f, y) as f: ... 25 | with (x for x in iter as y): ... | | 22 | with (x, yield y, z): ... 23 | with (x, yield from y): ... 24 | with (x as f, y) as f: ... | ^^ Syntax Error: Expected `:`, found `as` 25 | with (x for x in iter as y): ... | | 23 | with (x, yield from y): ... 24 | with (x as f, y) as f: ... 25 | with (x for x in iter as y): ... | ^^ Syntax Error: Expected `)`, found `as` 26 | 27 | # The inner `(...)` is parsed as parenthesized expression | | 23 | with (x, yield from y): ... 24 | with (x as f, y) as f: ... 25 | with (x for x in iter as y): ... | ^ Syntax Error: Expected `,`, found `)` 26 | 27 | # The inner `(...)` is parsed as parenthesized expression | | 27 | # The inner `(...)` is parsed as parenthesized expression 28 | with ((item as f)): ... | ^^ Syntax Error: Expected `)`, found `as` 29 | 30 | with (item as f), x: ... | | 27 | # The inner `(...)` is parsed as parenthesized expression 28 | with ((item as f)): ... | ^ Syntax Error: Expected `:`, found `)` 29 | 30 | with (item as f), x: ... | | 27 | # The inner `(...)` is parsed as parenthesized expression 28 | with ((item as f)): ... | ^ Syntax Error: Expected a statement 29 | 30 | with (item as f), x: ... | | 28 | with ((item as f)): ... 29 | 30 | with (item as f), x: ... | ^ Syntax Error: Expected `:`, found `,` 31 | with (item as f1) as f2: ... 32 | with (item1 as f, item2 := 0): ... | | 30 | with (item as f), x: ... 31 | with (item as f1) as f2: ... | ^^ Syntax Error: Expected `:`, found `as` 32 | with (item1 as f, item2 := 0): ... | | 30 | with (item as f), x: ... 31 | with (item as f1) as f2: ... 32 | with (item1 as f, item2 := 0): ... | ^^^^^^^^^^ Syntax Error: Unparenthesized named expression cannot be used here ## Unsupported Syntax Errors | 15 | with ((*item)): ... 16 | 17 | with (*x for x in iter, item): ... | ^^ Syntax Error: Cannot use iterable unpacking in a generator expression on Python 3.14 (syntax was added in Python 3.15) 18 | with (item1, *x for x in iter, item2): ... 19 | with (x as f, *y): ... | invalid_syntax@statements__with__empty_with_items.py.snap000064400000000000000000000046361046102023000354430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/with/empty_with_items.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..105, body: [ With( StmtWith { node_index: NodeIndex(None), range: 88..98, is_async: false, items: [], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 95..98, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 95..98, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 100..105, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 100..105, left: Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 2 | # The parser should recover from this syntax error. 3 | 4 | with : ... | ^ Syntax Error: Expected the start of an expression after `with` keyword 5 | 6 | x + y | invalid_syntax@statements__with__unclosed_ambiguous_lpar.py.snap000064400000000000000000000054401046102023000367500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/with/unclosed_ambiguous_lpar.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..14, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..14, is_async: false, items: [ WithItem { range: 5..6, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 6..6, id: Name(""), ctx: Invalid, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..14, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 9..14, left: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("y"), ctx: Load, }, ), }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | with (: | ^ Syntax Error: Expected an expression 2 | 3 | x + y | | 1 | with (: 2 | 3 | x + y | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@statements__with__unclosed_ambiguous_lpar_eof.py.snap000064400000000000000000000023261046102023000376010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/with/unclosed_ambiguous_lpar_eof.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..6, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..6, is_async: false, items: [ WithItem { range: 5..6, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 6..6, id: Name(""), ctx: Invalid, }, ), optional_vars: None, }, ], body: [], }, ), ], }, ) ``` ## Errors | 1 | with ( | ^ Syntax Error: unexpected EOF while parsing invalid_syntax@statements__with__unparenthesized_with_items.py.snap000064400000000000000000000354031046102023000375110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/invalid/statements/with/unparenthesized_with_items.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..249, body: [ With( StmtWith { node_index: NodeIndex(None), range: 86..102, is_async: false, items: [ WithItem { range: 91..95, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 91..95, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 98..102, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 103..124, is_async: false, items: [ WithItem { range: 108..117, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 108..112, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 116..117, id: Name("x"), ctx: Store, }, ), ), }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 120..124, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 125..141, is_async: false, items: [ WithItem { range: 130..135, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 130..135, value: Name( ExprName { node_index: NodeIndex(None), range: 131..135, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 137..141, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 142..163, is_async: false, items: [ WithItem { range: 147..157, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 147..152, value: Name( ExprName { node_index: NodeIndex(None), range: 148..152, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("x"), ctx: Store, }, ), ), }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 159..163, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 164..193, is_async: false, items: [ WithItem { range: 169..175, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 169..175, value: Name( ExprName { node_index: NodeIndex(None), range: 170..175, id: Name("item1"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 177..187, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 177..182, id: Name("item2"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 186..187, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 189..193, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 194..223, is_async: false, items: [ WithItem { range: 199..209, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 199..204, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 208..209, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 211..217, node_index: NodeIndex(None), context_expr: Starred( ExprStarred { node_index: NodeIndex(None), range: 211..217, value: Name( ExprName { node_index: NodeIndex(None), range: 212..217, id: Name("item2"), ctx: Load, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 219..223, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 224..249, is_async: false, items: [ WithItem { range: 229..233, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 229..233, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 237..243, node_index: NodeIndex(None), context_expr: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 237..238, value: Int( 0, ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 242..243, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 245..249, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # For parenthesized with items test cases, refer to `./ambiguous_lpar_with_items.py` 2 | 3 | with item,: pass | ^ Syntax Error: Trailing comma not allowed 4 | with item as x,: pass 5 | with *item: pass | | 3 | with item,: pass 4 | with item as x,: pass | ^ Syntax Error: Trailing comma not allowed 5 | with *item: pass 6 | with *item as x: pass | | 3 | with item,: pass 4 | with item as x,: pass 5 | with *item: pass | ^^^^^ Syntax Error: Starred expression cannot be used here 6 | with *item as x: pass 7 | with *item1, item2 as f: pass | | 4 | with item as x,: pass 5 | with *item: pass 6 | with *item as x: pass | ^^^^^ Syntax Error: Starred expression cannot be used here 7 | with *item1, item2 as f: pass 8 | with item1 as f, *item2: pass | | 5 | with *item: pass 6 | with *item as x: pass 7 | with *item1, item2 as f: pass | ^^^^^^ Syntax Error: Starred expression cannot be used here 8 | with item1 as f, *item2: pass 9 | with item := 0 as f: pass | | 6 | with *item as x: pass 7 | with *item1, item2 as f: pass 8 | with item1 as f, *item2: pass | ^^^^^^ Syntax Error: Starred expression cannot be used here 9 | with item := 0 as f: pass | | 7 | with *item1, item2 as f: pass 8 | with item1 as f, *item2: pass 9 | with item := 0 as f: pass | ^^ Syntax Error: Expected `,`, found `:=` invalid_syntax@t_string_empty_expression.py.snap000064400000000000000000000122201046102023000335630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_empty_expression.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..58, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..49, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..49, value: TStringValue { inner: Single( TString { range: 44..49, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..48, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..47, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 50..57, value: TString( ExprTString { node_index: NodeIndex(None), range: 50..57, value: TStringValue { inner: Single( TString { range: 50..57, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 52..56, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 53..53, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{}" | ^ Syntax Error: Expected an expression 3 | t"{ }" | | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{}" 3 | t"{ }" | ^ Syntax Error: Expected an expression invalid_syntax@t_string_invalid_conversion_flag_name_tok.py.snap000064400000000000000000000053561046102023000367230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_invalid_conversion_flag_name_tok.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..52, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..52, value: TStringValue { inner: Single( TString { range: 44..52, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..51, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{x!z}" | ^ Syntax Error: t-string: invalid conversion character invalid_syntax@t_string_invalid_conversion_flag_other_tok.py.snap000064400000000000000000000123231046102023000371140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_invalid_conversion_flag_other_tok.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..66, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..54, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..54, value: TStringValue { inner: Single( TString { range: 44..54, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..53, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 55..65, value: TString( ExprTString { node_index: NodeIndex(None), range: 55..65, value: TStringValue { inner: Single( TString { range: 55..65, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 57..64, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{x!123}" | ^^^ Syntax Error: t-string: invalid conversion character 3 | t"{x!'a'}" | | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{x!123}" 3 | t"{x!'a'}" | ^^^ Syntax Error: t-string: invalid conversion character invalid_syntax@t_string_invalid_starred_expr.py.snap000064400000000000000000000270521046102023000343670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_invalid_starred_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..156, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 121..127, value: TString( ExprTString { node_index: NodeIndex(None), range: 121..127, value: TStringValue { inner: Single( TString { range: 121..127, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 123..126, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 124..125, value: Name( ExprName { node_index: NodeIndex(None), range: 125..125, id: Name(""), ctx: Invalid, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 128..141, value: TString( ExprTString { node_index: NodeIndex(None), range: 128..141, value: TStringValue { inner: Single( TString { range: 128..141, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 130..140, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 131..139, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 132..139, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 138..139, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 142..155, value: TString( ExprTString { node_index: NodeIndex(None), range: 142..155, value: TStringValue { inner: Single( TString { range: 142..155, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 144..154, node_index: NodeIndex(None), expression: Starred( ExprStarred { node_index: NodeIndex(None), range: 145..153, value: Yield( ExprYield { node_index: NodeIndex(None), range: 146..153, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 152..153, id: Name("x"), ctx: Load, }, ), ), }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | # Starred expression inside t-string has a minimum precedence of bitwise or. 3 | t"{*}" | ^ Syntax Error: Expected an expression 4 | t"{*x and y}" 5 | t"{*yield x}" | | 2 | # Starred expression inside t-string has a minimum precedence of bitwise or. 3 | t"{*}" 4 | t"{*x and y}" | ^^^^^^^ Syntax Error: Boolean expression cannot be used here 5 | t"{*yield x}" | | 3 | t"{*}" 4 | t"{*x and y}" 5 | t"{*yield x}" | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@t_string_lambda_without_parentheses.py.snap000064400000000000000000000146321046102023000355630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_lambda_without_parentheses.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..61, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..60, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..60, value: TStringValue { inner: Single( TString { range: 44..60, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..56, node_index: NodeIndex(None), expression: Lambda( ExprLambda { node_index: NodeIndex(None), range: 47..56, parameters: Some( Parameters { range: 54..55, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 54..55, node_index: NodeIndex(None), parameter: Parameter { range: 54..55, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 54..55, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 56..56, id: Name(""), ctx: Invalid, }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 56..58, node_index: NodeIndex(None), value: " x", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{lambda x: x}" | ^^ Syntax Error: Expected an expression | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{lambda x: x}" | ^^^^^^^^^ Syntax Error: t-string: lambda expressions are not allowed without parentheses | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{lambda x: x}" | ^^ Syntax Error: t-string: expecting `}` | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{lambda x: x}" | ^ Syntax Error: Expected an element of or the end of the t-string invalid_syntax@t_string_unclosed_lbrace.py.snap000064400000000000000000000313431046102023000333010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..82, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..48, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..48, value: TStringValue { inner: Single( TString { range: 44..48, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..47, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..47, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..58, value: TString( ExprTString { node_index: NodeIndex(None), range: 49..58, value: TStringValue { inner: Single( TString { range: 49..58, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 51..57, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 52..55, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Repr, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 59..67, value: TString( ExprTString { node_index: NodeIndex(None), range: 59..67, value: TStringValue { inner: Single( TString { range: 59..67, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 61..66, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 62..65, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "foo", trailing: "=", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..72, value: TString( ExprTString { node_index: NodeIndex(None), range: 68..72, value: TStringValue { inner: Single( TString { range: 68..72, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 70..71, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 71..71, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 73..81, value: TString( ExprTString { node_index: NodeIndex(None), range: 73..81, value: TStringValue { inner: Single( TString { range: 73..81, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 77..78, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 78..78, id: Name(""), ctx: Invalid, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{" | ^ Syntax Error: Expected an expression 3 | t"{foo!r" 4 | t"{foo=" | | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{" 3 | t"{foo!r" | ^ Syntax Error: t-string: expecting `}` 4 | t"{foo=" 5 | t"{" | | 2 | t"{" 3 | t"{foo!r" 4 | t"{foo=" | ^ Syntax Error: t-string: expecting `}` 5 | t"{" 6 | t"""{""" | | 3 | t"{foo!r" 4 | t"{foo=" 5 | t"{" | ^ Syntax Error: Expected an expression 6 | t"""{""" | | 4 | t"{foo=" 5 | t"{" 6 | t"""{""" | ^^^ Syntax Error: Expected an expression invalid_syntax@t_string_unclosed_lbrace_in_format_spec.py.snap000064400000000000000000000171101046102023000363450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/t_string_unclosed_lbrace_in_format_spec.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..56, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..56, value: TStringValue { inner: Single( TString { range: 44..56, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 46..52, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 52..55, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 55..55, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..72, value: TString( ExprTString { node_index: NodeIndex(None), range: 57..72, value: TStringValue { inner: Single( TString { range: 57..72, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 59..65, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 65..71, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 68..71, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 68..71, node_index: NodeIndex(None), value: ".3f", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Errors | 1 | # parse_options: {"target-version": "3.14"} 2 | t"hello {x:" | ^ Syntax Error: t-string: expecting `}` 3 | t"hello {x:.3f" | | 1 | # parse_options: {"target-version": "3.14"} 2 | t"hello {x:" 3 | t"hello {x:.3f" | ^ Syntax Error: t-string: expecting `}` invalid_syntax@template_strings_py313.py.snap000064400000000000000000000162051046102023000325670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/template_strings_py313.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..89, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..52, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..52, value: TStringValue { inner: Single( TString { range: 44..52, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..51, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..50, id: Name("hey"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..63, value: TString( ExprTString { node_index: NodeIndex(None), range: 53..63, value: TStringValue { inner: Single( TString { range: 53..63, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 55..62, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 56..61, id: Name("there"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 64..88, value: TString( ExprTString { node_index: NodeIndex(None), range: 64..88, value: TStringValue { inner: Single( TString { range: 64..88, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 68..85, node_index: NodeIndex(None), value: "what's\nhappening?", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.13"} 2 | t"{hey}" | ^^^^^^^^ Syntax Error: Cannot use t-strings on Python 3.13 (syntax was added in Python 3.14) 3 | t'{there}' 4 | t"""what's | | 1 | # parse_options: {"target-version": "3.13"} 2 | t"{hey}" 3 | t'{there}' | ^^^^^^^^^^ Syntax Error: Cannot use t-strings on Python 3.13 (syntax was added in Python 3.14) 4 | t"""what's 5 | happening?""" | | 2 | t"{hey}" 3 | t'{there}' 4 | / t"""what's 5 | | happening?""" | |_____________^ Syntax Error: Cannot use t-strings on Python 3.13 (syntax was added in Python 3.14) invalid_syntax@try_stmt_invalid_order.py.snap000064400000000000000000000032631046102023000330320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/try_stmt_invalid_order.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..47, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..31, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [], orelse: [], finalbody: [ Pass( StmtPass { node_index: NodeIndex(None), range: 27..31, }, ), ], is_star: false, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 42..46, }, ), ], }, ) ``` ## Errors | 3 | finally: 4 | pass 5 | else: | ^^^^ Syntax Error: `else` block must come before `finally` block 6 | pass | | 3 | finally: 4 | pass 5 | else: | ^ Syntax Error: Expected a statement 6 | pass | | 3 | finally: 4 | pass 5 | else: | ^ Syntax Error: Expected a statement 6 | pass | | 4 | pass 5 | else: 6 | pass | ^^^^ Syntax Error: Unexpected indentation invalid_syntax@try_stmt_missing_except_finally.py.snap000064400000000000000000000036511046102023000347510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/try_stmt_missing_except_finally.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..43, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..13, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 14..42, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 23..27, }, ), ], handlers: [], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 38..42, }, ), ], finalbody: [], is_star: false, }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | try: | ^^^ Syntax Error: Expected `except` or `finally` after `try` block 4 | pass 5 | else: | | 5 | else: 6 | pass | ^ Syntax Error: Expected `except` or `finally` after `try` block invalid_syntax@try_stmt_misspelled_except.py.snap000064400000000000000000000166601046102023000337270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/try_stmt_misspelled_except.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..165, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..13, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [], orelse: [], finalbody: [], is_star: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 14..20, target: Name( ExprName { node_index: NodeIndex(None), range: 14..19, id: Name("exept"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 20..20, id: Name(""), ctx: Invalid, }, ), value: None, simple: true, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 54..58, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 72..76, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 77..82, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("a"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 1, ), }, ), }, ), Try( StmtTry { node_index: NodeIndex(None), range: 83..113, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 92..96, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 97..113, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 109..113, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 114..120, target: Name( ExprName { node_index: NodeIndex(None), range: 114..119, id: Name("exept"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 120..120, id: Name(""), ctx: Invalid, }, ), value: None, simple: true, }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 154..158, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 159..164, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 159..160, id: Name("b"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 163..164, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | try: 2 | pass 3 | exept: # spellchecker:disable-line | ^^^^^ Syntax Error: Expected `except` or `finally` after `try` block 4 | pass 5 | finally: | | 1 | try: 2 | pass 3 | exept: # spellchecker:disable-line | ^ Syntax Error: Expected an expression 4 | pass 5 | finally: 6 | pass | | 2 | pass 3 | exept: # spellchecker:disable-line 4 | pass | ^^^^ Syntax Error: Unexpected indentation 5 | finally: 6 | pass | | 3 | exept: # spellchecker:disable-line 4 | pass 5 | finally: | ^^^^^^^ Syntax Error: Expected a statement 6 | pass 7 | a = 1 | | 3 | exept: # spellchecker:disable-line 4 | pass 5 | finally: | ^ Syntax Error: Expected a statement 6 | pass 7 | a = 1 | | 3 | exept: # spellchecker:disable-line 4 | pass 5 | finally: | ^ Syntax Error: Expected a statement 6 | pass 7 | a = 1 8 | try: | | 4 | pass 5 | finally: 6 | pass | ^^^^ Syntax Error: Unexpected indentation 7 | a = 1 8 | try: | | 10 | except: 11 | pass 12 | exept: # spellchecker:disable-line | ^ Syntax Error: Expected an expression 13 | pass 14 | b = 1 | | 11 | pass 12 | exept: # spellchecker:disable-line 13 | pass | ^^^^ Syntax Error: Unexpected indentation 14 | b = 1 | invalid_syntax@try_stmt_mixed_except_kind.py.snap000064400000000000000000000247101046102023000336740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/try_stmt_mixed_except_kind.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..242, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..63, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 14..30, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 26..30, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 31..63, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 39..53, id: Name("ExceptionGroup"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 59..63, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 64..127, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 73..77, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 78..110, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 86..100, id: Name("ExceptionGroup"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 106..110, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 111..127, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 123..127, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 128..241, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 137..141, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 142..158, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 154..158, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 159..175, node_index: NodeIndex(None), type_: None, name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 171..175, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 176..208, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 184..198, id: Name("ExceptionGroup"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 204..208, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 209..241, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 217..231, id: Name("ExceptionGroup"), ctx: Load, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 237..241, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), ], }, ) ``` ## Errors | 3 | except: 4 | pass 5 | / except* ExceptionGroup: 6 | | pass | |________^ Syntax Error: Cannot have both 'except' and 'except*' on the same 'try' 7 | try: 8 | pass | | 9 | except* ExceptionGroup: 10 | pass 11 | / except: 12 | | pass | |________^ Syntax Error: Cannot have both 'except' and 'except*' on the same 'try' 13 | try: 14 | pass | | 17 | except: 18 | pass 19 | / except* ExceptionGroup: 20 | | pass | |________^ Syntax Error: Cannot have both 'except' and 'except*' on the same 'try' 21 | except* ExceptionGroup: 22 | pass | | 19 | except* ExceptionGroup: 20 | pass 21 | / except* ExceptionGroup: 22 | | pass | |________^ Syntax Error: Cannot have both 'except' and 'except*' on the same 'try' invalid_syntax@tuple_context_manager_py38.py.snap000064400000000000000000000156271046102023000335250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/tuple_context_manager_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..289, body: [ With( StmtWith { node_index: NodeIndex(None), range: 216..236, is_async: false, items: [ WithItem { range: 222..225, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 222..225, id: Name("foo"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 227..230, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 227..230, id: Name("bar"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 233..236, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 233..236, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 237..271, is_async: false, items: [ WithItem { range: 246..249, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 246..249, id: Name("foo"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 253..256, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 253..256, id: Name("bar"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 260..263, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 260..263, id: Name("baz"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 268..271, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 268..271, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 272..288, is_async: false, items: [ WithItem { range: 278..281, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 278..281, id: Name("foo"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 285..288, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 285..288, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 3 | # is parsed as a tuple, but this will always cause a runtime error, so we flag it 4 | # anyway 5 | with (foo, bar): ... | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) 6 | with ( 7 | foo, | | 4 | # anyway 5 | with (foo, bar): ... 6 | with ( | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) 7 | foo, 8 | bar, | | 9 | baz, 10 | ): ... 11 | with (foo,): ... | ^ Syntax Error: Cannot use parentheses within a `with` statement on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@type_alias_incomplete_stmt.py.snap000064400000000000000000000052321046102023000336620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_alias_incomplete_stmt.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..21, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..4, value: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("type"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5..9, value: Name( ExprName { node_index: NodeIndex(None), range: 5..9, id: Name("type"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..11, value: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 12..20, name: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 20..20, id: Name(""), ctx: Invalid, }, ), }, ), ], }, ) ``` ## Errors | 1 | type 2 | type x | ^ Syntax Error: Simple statements must be separated by newlines or semicolons 3 | type x = | | 1 | type 2 | type x 3 | type x = | ^ Syntax Error: Expected an expression invalid_syntax@type_alias_invalid_value_expr.py.snap000064400000000000000000000136301046102023000343350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_alias_invalid_value_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..11, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Store, }, ), type_params: None, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 9..11, value: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 12..28, name: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Store, }, ), type_params: None, value: Yield( ExprYield { node_index: NodeIndex(None), range: 21..28, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("y"), ctx: Load, }, ), ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 29..50, name: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Store, }, ), type_params: None, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 38..50, value: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("y"), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 51..61, name: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("x"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 65..66, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 1, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | type x = *y | ^^ Syntax Error: Starred expression cannot be used here 2 | type x = yield y 3 | type x = yield from y | | 1 | type x = *y 2 | type x = yield y | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | type x = yield from y 4 | type x = x := 1 | | 1 | type x = *y 2 | type x = yield y 3 | type x = yield from y | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | type x = x := 1 | | 2 | type x = yield y 3 | type x = yield from y 4 | type x = x := 1 | ^^ Syntax Error: Expected a statement ## Semantic Syntax Errors | 1 | type x = *y 2 | type x = yield y | ^^^^^^^ Syntax Error: yield expression cannot be used within a type alias 3 | type x = yield from y 4 | type x = x := 1 | | 1 | type x = *y 2 | type x = yield y 3 | type x = yield from y | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type alias 4 | type x = x := 1 | invalid_syntax@type_param_default_py312.py.snap000064400000000000000000000342311046102023000330460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_default_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..149, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 44..65, name: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 50..59, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 51..58, name: Identifier { id: Name("T"), range: 51..52, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 55..58, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 62..65, id: Name("int"), ctx: Load, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 66..87, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 70..71, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 71..80, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 72..79, name: Identifier { id: Name("T"), range: 72..73, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), parameters: Parameters { range: 80..82, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 84..87, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 84..87, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 88..111, decorator_list: [], name: Identifier { id: Name("C"), range: 94..95, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 95..104, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 96..103, name: Identifier { id: Name("T"), range: 96..97, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 100..103, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 104..106, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 108..111, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 108..111, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 112..148, decorator_list: [], name: Identifier { id: Name("D"), range: 118..119, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 119..141, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 120..121, name: Identifier { id: Name("S"), range: 120..121, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 123..130, name: Identifier { id: Name("T"), range: 123..124, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 127..130, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 132..140, name: Identifier { id: Name("U"), range: 132..133, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 136..140, id: Name("uint"), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 141..143, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 145..148, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 145..148, }, ), }, ), ], }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.12"} 2 | type X[T = int] = int | ^^^^^ Syntax Error: Cannot set default type for a type parameter on Python 3.12 (syntax was added in Python 3.13) 3 | def f[T = int](): ... 4 | class C[T = int](): ... | | 1 | # parse_options: {"target-version": "3.12"} 2 | type X[T = int] = int 3 | def f[T = int](): ... | ^^^^^ Syntax Error: Cannot set default type for a type parameter on Python 3.12 (syntax was added in Python 3.13) 4 | class C[T = int](): ... 5 | class D[S, T = int, U = uint](): ... | | 2 | type X[T = int] = int 3 | def f[T = int](): ... 4 | class C[T = int](): ... | ^^^^^ Syntax Error: Cannot set default type for a type parameter on Python 3.12 (syntax was added in Python 3.13) 5 | class D[S, T = int, U = uint](): ... | | 3 | def f[T = int](): ... 4 | class C[T = int](): ... 5 | class D[S, T = int, U = uint](): ... | ^^^^^ Syntax Error: Cannot set default type for a type parameter on Python 3.12 (syntax was added in Python 3.13) | 3 | def f[T = int](): ... 4 | class C[T = int](): ... 5 | class D[S, T = int, U = uint](): ... | ^^^^^^ Syntax Error: Cannot set default type for a type parameter on Python 3.12 (syntax was added in Python 3.13) invalid_syntax@type_param_invalid_bound_expr.py.snap000064400000000000000000000311401046102023000343330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_invalid_bound_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..103, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..21, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..15, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..14, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 10..14, value: Name( ExprName { node_index: NodeIndex(None), range: 11..14, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 18..21, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 22..46, name: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 28..40, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 29..39, name: Identifier { id: Name("T"), range: 29..30, node_index: NodeIndex(None), }, bound: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 32..39, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("x"), ctx: Load, }, ), ), }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 47..76, name: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 53..70, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 54..69, name: Identifier { id: Name("T"), range: 54..55, node_index: NodeIndex(None), }, bound: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 57..69, value: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 73..76, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 77..102, name: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 83..96, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 84..88, name: Identifier { id: Name("T"), range: 84..85, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("x"), ctx: Load, }, ), ), default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 92..95, name: Identifier { id: Name("int"), range: 92..95, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 99..102, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[T: *int] = int | ^^^^ Syntax Error: Starred expression cannot be used here 2 | type X[T: yield x] = int 3 | type X[T: yield from x] = int | | 1 | type X[T: *int] = int 2 | type X[T: yield x] = int | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | type X[T: yield from x] = int 4 | type X[T: x := int] = int | | 1 | type X[T: *int] = int 2 | type X[T: yield x] = int 3 | type X[T: yield from x] = int | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | type X[T: x := int] = int | | 2 | type X[T: yield x] = int 3 | type X[T: yield from x] = int 4 | type X[T: x := int] = int | ^^ Syntax Error: Expected `,`, found `:=` ## Semantic Syntax Errors | 1 | type X[T: *int] = int 2 | type X[T: yield x] = int | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound 3 | type X[T: yield from x] = int 4 | type X[T: x := int] = int | | 1 | type X[T: *int] = int 2 | type X[T: yield x] = int 3 | type X[T: yield from x] = int | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound 4 | type X[T: x := int] = int | invalid_syntax@type_param_missing_bound.py.snap000064400000000000000000000112051046102023000333200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_missing_bound.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..41, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..17, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..11, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..9, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 18..40, name: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 24..34, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 25..28, name: Identifier { id: Name("T1"), range: 25..27, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 31..33, name: Identifier { id: Name("T2"), range: 31..33, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 37..40, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[T: ] = int | ^ Syntax Error: Expected an expression 2 | type X[T1: , T2] = int | | 1 | type X[T: ] = int 2 | type X[T1: , T2] = int | ^ Syntax Error: Expected an expression invalid_syntax@type_param_param_spec_bound.py.snap000064400000000000000000000062061046102023000337660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_param_spec_bound.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..23, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..10, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..10, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 7..10, name: Identifier { id: Name("T"), range: 9..10, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 10..10, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..15, value: Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("int"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: Name( ExprName { node_index: NodeIndex(None), range: 19..22, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[**T: int] = int | ^ Syntax Error: Expected `]`, found `:` | 1 | type X[**T: int] = int | ^ Syntax Error: Expected a statement | 1 | type X[**T: int] = int | ^ Syntax Error: Expected a statement invalid_syntax@type_param_param_spec_invalid_default_expr.py.snap000064400000000000000000000373341046102023000370550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_param_spec_invalid_default_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..140, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..24, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..18, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 7..17, name: Identifier { id: Name("P"), range: 9..10, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..17, value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 21..24, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 25..52, name: Name( ExprName { node_index: NodeIndex(None), range: 30..31, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 31..46, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 32..45, name: Identifier { id: Name("P"), range: 34..35, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 38..45, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 49..52, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 53..85, name: Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 59..79, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 60..78, name: Identifier { id: Name("P"), range: 62..63, node_index: NodeIndex(None), }, default: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 66..78, value: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 82..85, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 86..114, name: Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 92..108, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 93..100, name: Identifier { id: Name("P"), range: 95..96, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("x"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 104..107, name: Identifier { id: Name("int"), range: 104..107, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 111..114, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 115..139, name: Name( ExprName { node_index: NodeIndex(None), range: 120..121, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 121..133, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 122..132, name: Identifier { id: Name("P"), range: 124..125, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 128..132, value: Name( ExprName { node_index: NodeIndex(None), range: 129..132, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 136..139, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[**P = *int] = int | ^^^^ Syntax Error: Starred expression cannot be used here 2 | type X[**P = yield x] = int 3 | type X[**P = yield from x] = int | | 1 | type X[**P = *int] = int 2 | type X[**P = yield x] = int | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | type X[**P = yield from x] = int 4 | type X[**P = x := int] = int | | 1 | type X[**P = *int] = int 2 | type X[**P = yield x] = int 3 | type X[**P = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | type X[**P = x := int] = int 5 | type X[**P = *int] = int | | 2 | type X[**P = yield x] = int 3 | type X[**P = yield from x] = int 4 | type X[**P = x := int] = int | ^^ Syntax Error: Expected `,`, found `:=` 5 | type X[**P = *int] = int | | 3 | type X[**P = yield from x] = int 4 | type X[**P = x := int] = int 5 | type X[**P = *int] = int | ^^^^ Syntax Error: Starred expression cannot be used here ## Semantic Syntax Errors | 1 | type X[**P = *int] = int 2 | type X[**P = yield x] = int | ^^^^^^^ Syntax Error: yield expression cannot be used within a ParamSpec default 3 | type X[**P = yield from x] = int 4 | type X[**P = x := int] = int | | 1 | type X[**P = *int] = int 2 | type X[**P = yield x] = int 3 | type X[**P = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a ParamSpec default 4 | type X[**P = x := int] = int 5 | type X[**P = *int] = int | | 2 | type X[**P = yield x] = int 3 | type X[**P = yield from x] = int 4 | type X[**P = x := int] = int | ^^^ Syntax Error: non default type parameter `int` follows default type parameter 5 | type X[**P = *int] = int | invalid_syntax@type_param_param_spec_missing_default.py.snap000064400000000000000000000110721046102023000360310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_param_spec_missing_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..44, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..19, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..13, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 7..12, name: Identifier { id: Name("P"), range: 9..10, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 16..19, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 20..43, name: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 26..37, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 27..32, name: Identifier { id: Name("P"), range: 29..30, node_index: NodeIndex(None), }, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 34..36, name: Identifier { id: Name("T2"), range: 34..36, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 40..43, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[**P =] = int | ^ Syntax Error: Expected an expression 2 | type X[**P =, T2] = int | | 1 | type X[**P =] = int 2 | type X[**P =, T2] = int | ^ Syntax Error: Expected an expression invalid_syntax@type_param_type_var_invalid_default_expr.py.snap000064400000000000000000000470031046102023000365660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_type_var_invalid_default_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..163, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..22, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..16, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..15, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: None, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 11..15, value: Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 19..22, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 23..48, name: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 29..42, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 30..41, name: Identifier { id: Name("T"), range: 30..31, node_index: NodeIndex(None), }, bound: None, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 34..41, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 45..48, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 49..76, name: Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 55..70, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 56..69, name: Identifier { id: Name("T"), range: 56..57, node_index: NodeIndex(None), }, bound: None, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 61..68, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 73..76, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 77..107, name: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 83..101, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 84..100, name: Identifier { id: Name("T"), range: 84..85, node_index: NodeIndex(None), }, bound: None, default: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 88..100, value: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 104..107, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 108..134, name: Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 114..128, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 115..120, name: Identifier { id: Name("T"), range: 115..116, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 119..120, id: Name("x"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 124..127, name: Identifier { id: Name("int"), range: 124..127, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 131..134, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 135..162, name: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 141..156, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 142..155, name: Identifier { id: Name("T"), range: 142..143, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 145..148, id: Name("int"), ctx: Load, }, ), ), default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 151..155, value: Name( ExprName { node_index: NodeIndex(None), range: 152..155, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 159..162, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[T = *int] = int | ^^^^ Syntax Error: Starred expression cannot be used here 2 | type X[T = yield x] = int 3 | type X[T = (yield x)] = int | | 1 | type X[T = *int] = int 2 | type X[T = yield x] = int | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int | | 2 | type X[T = yield x] = int 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | type X[T = x := int] = int 6 | type X[T: int = *int] = int | | 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int 5 | type X[T = x := int] = int | ^^ Syntax Error: Expected `,`, found `:=` 6 | type X[T: int = *int] = int | | 4 | type X[T = yield from x] = int 5 | type X[T = x := int] = int 6 | type X[T: int = *int] = int | ^^^^ Syntax Error: Starred expression cannot be used here ## Semantic Syntax Errors | 1 | type X[T = *int] = int 2 | type X[T = yield x] = int | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int | | 1 | type X[T = *int] = int 2 | type X[T = yield x] = int 3 | type X[T = (yield x)] = int | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default 4 | type X[T = yield from x] = int 5 | type X[T = x := int] = int | | 2 | type X[T = yield x] = int 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default 5 | type X[T = x := int] = int 6 | type X[T: int = *int] = int | | 3 | type X[T = (yield x)] = int 4 | type X[T = yield from x] = int 5 | type X[T = x := int] = int | ^^^ Syntax Error: non default type parameter `int` follows default type parameter 6 | type X[T: int = *int] = int | invalid_syntax@type_param_type_var_missing_default.py.snap000064400000000000000000000161231046102023000355520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_type_var_missing_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..64, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..17, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..11, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..10, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 18..40, name: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 24..34, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 25..33, name: Identifier { id: Name("T"), range: 25..26, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 28..31, id: Name("int"), ctx: Load, }, ), ), default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 37..40, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 41..63, name: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 47..57, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 48..52, name: Identifier { id: Name("T1"), range: 48..50, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 54..56, name: Identifier { id: Name("T2"), range: 54..56, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[T =] = int | ^ Syntax Error: Expected an expression 2 | type X[T: int =] = int 3 | type X[T1 =, T2] = int | | 1 | type X[T =] = int 2 | type X[T: int =] = int | ^ Syntax Error: Expected an expression 3 | type X[T1 =, T2] = int | | 1 | type X[T =] = int 2 | type X[T: int =] = int 3 | type X[T1 =, T2] = int | ^ Syntax Error: Expected an expression invalid_syntax@type_param_type_var_tuple_bound.py.snap000064400000000000000000000062041046102023000347140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_type_var_tuple_bound.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..22, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..9, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..9, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 7..9, name: Identifier { id: Name("T"), range: 8..9, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 9..9, id: Name(""), ctx: Invalid, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..14, value: Name( ExprName { node_index: NodeIndex(None), range: 11..14, id: Name("int"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..21, value: Name( ExprName { node_index: NodeIndex(None), range: 18..21, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[*T: int] = int | ^ Syntax Error: Expected `]`, found `:` | 1 | type X[*T: int] = int | ^ Syntax Error: Expected a statement | 1 | type X[*T: int] = int | ^ Syntax Error: Expected a statement invalid_syntax@type_param_type_var_tuple_invalid_default_expr.py.snap000064400000000000000000000416411046102023000400010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_type_var_tuple_invalid_default_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..147, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..24, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..18, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 7..17, name: Identifier { id: Name("Ts"), range: 8..10, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 13..17, value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 21..24, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 25..56, name: Name( ExprName { node_index: NodeIndex(None), range: 30..31, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 31..50, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 32..49, name: Identifier { id: Name("Ts"), range: 33..35, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 38..49, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 39..49, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 39..42, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 46..49, id: Name("str"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 53..56, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 57..84, name: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 63..78, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 64..77, name: Identifier { id: Name("Ts"), range: 65..67, node_index: NodeIndex(None), }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 70..77, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 76..77, id: Name("x"), ctx: Load, }, ), ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 81..84, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 85..117, name: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 91..111, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 92..110, name: Identifier { id: Name("Ts"), range: 93..95, node_index: NodeIndex(None), }, default: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 98..110, value: Name( ExprName { node_index: NodeIndex(None), range: 109..110, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 114..117, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 118..146, name: Name( ExprName { node_index: NodeIndex(None), range: 123..124, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 124..140, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 125..132, name: Identifier { id: Name("Ts"), range: 126..128, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("x"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 136..139, name: Identifier { id: Name("int"), range: 136..139, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 143..146, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[*Ts = *int] = int 2 | type X[*Ts = *int or str] = int | ^^^^^^^^^^ Syntax Error: Boolean expression cannot be used here 3 | type X[*Ts = yield x] = int 4 | type X[*Ts = yield from x] = int | | 1 | type X[*Ts = *int] = int 2 | type X[*Ts = *int or str] = int 3 | type X[*Ts = yield x] = int | ^^^^^^^ Syntax Error: Yield expression cannot be used here 4 | type X[*Ts = yield from x] = int 5 | type X[*Ts = x := int] = int | | 2 | type X[*Ts = *int or str] = int 3 | type X[*Ts = yield x] = int 4 | type X[*Ts = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | type X[*Ts = x := int] = int | | 3 | type X[*Ts = yield x] = int 4 | type X[*Ts = yield from x] = int 5 | type X[*Ts = x := int] = int | ^^ Syntax Error: Expected `,`, found `:=` ## Semantic Syntax Errors | 1 | type X[*Ts = *int] = int 2 | type X[*Ts = *int or str] = int 3 | type X[*Ts = yield x] = int | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVarTuple default 4 | type X[*Ts = yield from x] = int 5 | type X[*Ts = x := int] = int | | 2 | type X[*Ts = *int or str] = int 3 | type X[*Ts = yield x] = int 4 | type X[*Ts = yield from x] = int | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVarTuple default 5 | type X[*Ts = x := int] = int | | 3 | type X[*Ts = yield x] = int 4 | type X[*Ts = yield from x] = int 5 | type X[*Ts = x := int] = int | ^^^ Syntax Error: non default type parameter `int` follows default type parameter invalid_syntax@type_param_type_var_tuple_missing_default.py.snap000064400000000000000000000111141046102023000367560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_param_type_var_tuple_missing_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..44, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..19, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..13, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 7..12, name: Identifier { id: Name("Ts"), range: 8..10, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 16..19, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 20..43, name: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 26..37, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 27..32, name: Identifier { id: Name("Ts"), range: 28..30, node_index: NodeIndex(None), }, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 34..36, name: Identifier { id: Name("T2"), range: 34..36, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 40..43, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Errors | 1 | type X[*Ts =] = int | ^ Syntax Error: Expected an expression 2 | type X[*Ts =, T2] = int | | 1 | type X[*Ts =] = int 2 | type X[*Ts =, T2] = int | ^ Syntax Error: Expected an expression invalid_syntax@type_parameter_default_order.py.snap000064400000000000000000000371331046102023000341670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_parameter_default_order.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..114, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..24, decorator_list: [], name: Identifier { id: Name("C"), range: 6..7, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 7..19, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 8..15, name: Identifier { id: Name("T"), range: 8..9, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 17..18, name: Identifier { id: Name("U"), range: 17..18, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 25..59, decorator_list: [], name: Identifier { id: Name("C"), range: 31..32, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 32..54, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 33..35, name: Identifier { id: Name("T1"), range: 33..35, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 37..45, name: Identifier { id: Name("T2"), range: 37..39, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 42..45, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 47..49, name: Identifier { id: Name("T3"), range: 47..49, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 51..53, name: Identifier { id: Name("T4"), range: 51..53, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 56..59, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 56..59, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..84, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 64..65, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 65..77, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 66..73, name: Identifier { id: Name("T"), range: 66..67, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 70..73, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 75..76, name: Identifier { id: Name("U"), range: 75..76, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 77..79, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 85..113, name: Name( ExprName { node_index: NodeIndex(None), range: 90..95, id: Name("Alias"), ctx: Store, }, ), type_params: Some( TypeParams { range: 95..107, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 96..103, name: Identifier { id: Name("T"), range: 96..97, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 100..103, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 105..106, name: Identifier { id: Name("U"), range: 105..106, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 110..113, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | class C[T = int, U]: ... | ^ Syntax Error: non default type parameter `U` follows default type parameter 2 | class C[T1, T2 = int, T3, T4]: ... 3 | def f[T = int, U](): ... | | 1 | class C[T = int, U]: ... 2 | class C[T1, T2 = int, T3, T4]: ... | ^^ Syntax Error: non default type parameter `T3` follows default type parameter 3 | def f[T = int, U](): ... 4 | type Alias[T = int, U] = ... | | 1 | class C[T = int, U]: ... 2 | class C[T1, T2 = int, T3, T4]: ... | ^^ Syntax Error: non default type parameter `T4` follows default type parameter 3 | def f[T = int, U](): ... 4 | type Alias[T = int, U] = ... | | 1 | class C[T = int, U]: ... 2 | class C[T1, T2 = int, T3, T4]: ... 3 | def f[T = int, U](): ... | ^ Syntax Error: non default type parameter `U` follows default type parameter 4 | type Alias[T = int, U] = ... | | 2 | class C[T1, T2 = int, T3, T4]: ... 3 | def f[T = int, U](): ... 4 | type Alias[T = int, U] = ... | ^ Syntax Error: non default type parameter `U` follows default type parameter invalid_syntax@type_params_empty.py.snap000064400000000000000000000071531046102023000320100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_params_empty.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..52, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..21, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 7..9, node_index: NodeIndex(None), type_params: [], }, ), parameters: Parameters { range: 9..11, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 17..21, }, ), ], }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 22..51, name: Name( ExprName { node_index: NodeIndex(None), range: 27..36, id: Name("ListOrSet"), ctx: Store, }, ), type_params: Some( TypeParams { range: 36..38, node_index: NodeIndex(None), type_params: [], }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 41..51, left: Name( ExprName { node_index: NodeIndex(None), range: 41..45, id: Name("list"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 48..51, id: Name("set"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | def foo[](): | ^ Syntax Error: Type parameter list cannot be empty 2 | pass 3 | type ListOrSet[] = list | set | | 1 | def foo[](): 2 | pass 3 | type ListOrSet[] = list | set | ^ Syntax Error: Type parameter list cannot be empty invalid_syntax@type_stmt_py311.py.snap000064400000000000000000000024141046102023000312260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 44..56, name: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("x"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 53..56, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.11"} 2 | type x = int | ^^^^ Syntax Error: Cannot use `type` alias statement on Python 3.11 (syntax was added in Python 3.12) invalid_syntax@unparenthesized_named_expr_index_py38.py.snap000064400000000000000000000047211046102023000357300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/unparenthesized_named_expr_index_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..52, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 43..52, value: Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("lst"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 47..51, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 50..51, value: Int( 1, ), }, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | lst[x:=1] | ^^^^ Syntax Error: Cannot use unparenthesized assignment expression in a sequence index on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@unparenthesized_named_expr_set_comp_py38.py.snap000064400000000000000000000112071046102023000364270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/unparenthesized_named_expr_set_comp_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..72, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 43..72, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 44..53, target: Name( ExprName { node_index: NodeIndex(None), range: 44..48, id: Name("last"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 54..71, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 63..71, func: Name( ExprName { node_index: NodeIndex(None), range: 63..68, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 68..71, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 69..70, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | {last := x for x in range(3)} | ^^^^^^^^^ Syntax Error: Cannot use unparenthesized assignment expression as an element in a set comprehension on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@unparenthesized_named_expr_set_literal_py38.py.snap000064400000000000000000000212731046102023000371310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/unparenthesized_named_expr_set_literal_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..88, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..57, value: Set( ExprSet { node_index: NodeIndex(None), range: 43..57, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 44..50, target: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 1, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..72, value: Set( ExprSet { node_index: NodeIndex(None), range: 58..72, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 59..60, value: Int( 1, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 62..68, target: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 67..68, value: Int( 2, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 70..71, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 73..87, value: Set( ExprSet { node_index: NodeIndex(None), range: 73..87, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 74..75, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 77..78, value: Int( 2, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 80..86, target: Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 85..86, value: Int( 3, ), }, ), }, ), ], }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: {"target-version": "3.8"} 2 | {x := 1, 2, 3} | ^^^^^^ Syntax Error: Cannot use unparenthesized assignment expression as an element in a set literal on Python 3.8 (syntax was added in Python 3.9) 3 | {1, x := 2, 3} 4 | {1, 2, x := 3} | | 1 | # parse_options: {"target-version": "3.8"} 2 | {x := 1, 2, 3} 3 | {1, x := 2, 3} | ^^^^^^ Syntax Error: Cannot use unparenthesized assignment expression as an element in a set literal on Python 3.8 (syntax was added in Python 3.9) 4 | {1, 2, x := 3} | | 2 | {x := 1, 2, 3} 3 | {1, x := 2, 3} 4 | {1, 2, x := 3} | ^^^^^^ Syntax Error: Cannot use unparenthesized assignment expression as an element in a set literal on Python 3.8 (syntax was added in Python 3.9) invalid_syntax@unterminated_fstring_newline_recovery.py.snap000064400000000000000000000423051046102023000361360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/unterminated_fstring_newline_recovery.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..7, value: FStringValue { inner: Single( FString( FString { range: 0..7, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..7, node_index: NodeIndex(None), value: "hello", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..13, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 8..13, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 12..13, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 14..24, value: FString( ExprFString { node_index: NodeIndex(None), range: 14..24, value: FStringValue { inner: Single( FString( FString { range: 14..24, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 16..22, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 22..24, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 25..30, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 25..30, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 29..30, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 31..42, value: FString( ExprFString { node_index: NodeIndex(None), range: 31..42, value: FStringValue { inner: Single( FString( FString { range: 31..42, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 33..39, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 39..42, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 42..42, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 43..48, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 43..48, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 3, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..48, value: Int( 3, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..60, value: FString( ExprFString { node_index: NodeIndex(None), range: 49..60, value: FStringValue { inner: Single( FString( FString { range: 49..60, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 51..57, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 57..60, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: true, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 61..66, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 61..66, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 4, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 4, ), }, ), }, ), }, ), ], }, ) ``` ## Errors | 1 | f"hello | ^^^^^ Syntax Error: f-string: unterminated string 2 | 1 + 1 3 | f"hello {x | | 1 | f"hello | ^ Syntax Error: Expected FStringEnd, found newline 2 | 1 + 1 3 | f"hello {x 4 | 2 + 2 | | 1 | f"hello 2 | 1 + 1 3 | f"hello {x | ^ Syntax Error: f-string: unterminated string 4 | 2 + 2 5 | f"hello {x: | | 2 | 1 + 1 3 | f"hello {x 4 | 2 + 2 | ^ Syntax Error: f-string: expecting `}` 5 | f"hello {x: 6 | 3 + 3 | | 1 | f"hello 2 | 1 + 1 3 | f"hello {x | ^ Syntax Error: Expected FStringEnd, found newline 4 | 2 + 2 5 | f"hello {x: 6 | 3 + 3 | | 3 | f"hello {x 4 | 2 + 2 5 | f"hello {x: | ^ Syntax Error: f-string: newlines are not allowed in format specifiers when using single quotes 6 | 3 + 3 7 | f"hello {x} | | 5 | f"hello {x: 6 | 3 + 3 7 | f"hello {x} | ^ Syntax Error: f-string: unterminated string 8 | 4 + 4 | ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/invalid_syntax@walrus_py37.py.snap000064400000000000000000000031571046102023000305240ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/walrus_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..54, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 45..53, value: Named( ExprNamed { node_index: NodeIndex(None), range: 46..52, target: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` ## Unsupported Syntax Errors | 1 | # parse_options: { "target-version": "3.7" } 2 | (x := 1) | ^^^^^^ Syntax Error: Cannot use named assignment expression (`:=`) on Python 3.7 (syntax was added in Python 3.8) invalid_syntax@while_stmt_invalid_test_expr.py.snap000064400000000000000000000156631046102023000342350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/while_stmt_invalid_test_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..70, body: [ While( StmtWhile { node_index: NodeIndex(None), range: 0..13, test: Starred( ExprStarred { node_index: NodeIndex(None), range: 6..8, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 10..13, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 10..13, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 14..32, test: Yield( ExprYield { node_index: NodeIndex(None), range: 20..27, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("x"), ctx: Load, }, ), ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 33..40, test: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("a"), ctx: Load, }, ), body: [], orelse: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 42..48, target: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("b"), ctx: Store, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 45..48, }, ), value: None, simple: true, }, ), While( StmtWhile { node_index: NodeIndex(None), range: 49..61, test: Named( ExprNamed { node_index: NodeIndex(None), range: 55..61, target: Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 60..61, value: Int( 1, ), }, ), }, ), body: [], orelse: [], }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 63..69, target: Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("b"), ctx: Store, }, ), annotation: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 66..69, }, ), value: None, simple: true, }, ), ], }, ) ``` ## Errors | 1 | while *x: ... | ^^ Syntax Error: Starred expression cannot be used here 2 | while yield x: ... 3 | while a, b: ... | | 1 | while *x: ... 2 | while yield x: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here 3 | while a, b: ... 4 | while a := 1, b: ... | | 1 | while *x: ... 2 | while yield x: ... 3 | while a, b: ... | ^ Syntax Error: Expected `:`, found `,` 4 | while a := 1, b: ... | | 2 | while yield x: ... 3 | while a, b: ... 4 | while a := 1, b: ... | ^ Syntax Error: Expected `:`, found `,` invalid_syntax@while_stmt_missing_colon.py.snap000064400000000000000000000040561046102023000333470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/while_stmt_missing_colon.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..40, body: [ While( StmtWhile { node_index: NodeIndex(None), range: 0..39, test: Compare( ExprCompare { node_index: NodeIndex(None), range: 12..18, left: Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("a"), ctx: Load, }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..18, value: Int( 30, ), }, ), ], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 35..39, }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | while ( 2 | a < 30 # comment 3 | ) | ^ Syntax Error: Expected `:`, found newline 4 | pass | invalid_syntax@while_stmt_missing_test.py.snap000064400000000000000000000063711046102023000332160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/while_stmt_missing_test.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ While( StmtWhile { node_index: NodeIndex(None), range: 0..11, test: Name( ExprName { node_index: NodeIndex(None), range: 5..5, id: Name(""), ctx: Invalid, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 8..11, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 8..11, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 12..29, test: Name( ExprName { node_index: NodeIndex(None), range: 17..17, id: Name(""), ctx: Invalid, }, ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 24..29, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("a"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 1, ), }, ), }, ), ], orelse: [], }, ), ], }, ) ``` ## Errors | 1 | while : ... | ^ Syntax Error: Expected an expression 2 | while : 3 | a = 1 | | 1 | while : ... 2 | while : | ^ Syntax Error: Expected an expression 3 | a = 1 | invalid_syntax@with_items_parenthesized_missing_colon.py.snap000064400000000000000000000041611046102023000362660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/with_items_parenthesized_missing_colon.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ With( StmtWith { node_index: NodeIndex(None), range: 28..56, is_async: false, items: [ WithItem { range: 34..39, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 34..39, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 41..46, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 41..46, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 52..56, }, ), ], }, ), ], }, ) ``` ## Errors | 1 | # `)` followed by a newline 2 | with (item1, item2) | ^ Syntax Error: Expected `:`, found newline 3 | pass | invalid_syntax@with_items_parenthesized_missing_comma.py.snap000064400000000000000000000354371046102023000362620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/with_items_parenthesized_missing_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..160, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..23, is_async: false, items: [ WithItem { range: 6..11, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 6..11, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 12..17, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 12..17, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 24..53, is_async: false, items: [ WithItem { range: 30..41, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 30..35, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 39..41, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 42..47, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 42..47, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 50..53, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 54..91, is_async: false, items: [ WithItem { range: 60..65, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 60..65, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 67..72, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 67..72, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 73..78, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 73..78, id: Name("item3"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 80..85, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 80..85, id: Name("item4"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 88..91, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 88..91, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 92..135, is_async: false, items: [ WithItem { range: 98..103, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 98..103, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 105..116, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 105..110, id: Name("item2"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 114..116, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 117..122, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 117..122, id: Name("item3"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 124..129, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 124..129, id: Name("item4"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 132..135, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 132..135, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 136..159, is_async: false, items: [ WithItem { range: 141..154, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 141..154, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 142..147, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 149..154, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 156..159, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 156..159, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | with (item1 item2): ... | ^^^^^ Syntax Error: Expected `,`, found name 2 | with (item1 as f1 item2): ... 3 | with (item1, item2 item3, item4): ... | | 1 | with (item1 item2): ... 2 | with (item1 as f1 item2): ... | ^^^^^ Syntax Error: Expected `,`, found name 3 | with (item1, item2 item3, item4): ... 4 | with (item1, item2 as f1 item3, item4): ... | | 1 | with (item1 item2): ... 2 | with (item1 as f1 item2): ... 3 | with (item1, item2 item3, item4): ... | ^^^^^ Syntax Error: Expected `,`, found name 4 | with (item1, item2 as f1 item3, item4): ... 5 | with (item1, item2: ... | | 2 | with (item1 as f1 item2): ... 3 | with (item1, item2 item3, item4): ... 4 | with (item1, item2 as f1 item3, item4): ... | ^^^^^ Syntax Error: Expected `,`, found name 5 | with (item1, item2: ... | | 3 | with (item1, item2 item3, item4): ... 4 | with (item1, item2 as f1 item3, item4): ... 5 | with (item1, item2: ... | ^ Syntax Error: Expected `)`, found `:` invalid_syntax@write_to_debug_expr.py.snap000064400000000000000000000204101046102023000322750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/write_to_debug_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..83, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 4..13, id: Name("__debug__"), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 14..36, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("y"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 24..33, id: Name("__debug__"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("z"), ctx: Del, }, ), ], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 37..50, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 37..46, id: Name("__debug__"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 51..82, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 51..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("y"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 57..66, id: Name("__debug__"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("z"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 72..82, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 72..73, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 4, ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | del __debug__ | ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.14 (syntax was removed in 3.9) 2 | del x, y, __debug__, z 3 | __debug__ = 1 | | 1 | del __debug__ 2 | del x, y, __debug__, z | ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.14 (syntax was removed in 3.9) 3 | __debug__ = 1 4 | x, y, __debug__, z = 1, 2, 3, 4 | | 1 | del __debug__ 2 | del x, y, __debug__, z 3 | __debug__ = 1 | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` 4 | x, y, __debug__, z = 1, 2, 3, 4 | | 2 | del x, y, __debug__, z 3 | __debug__ = 1 4 | x, y, __debug__, z = 1, 2, 3, 4 | ^^^^^^^^^ Syntax Error: cannot assign to `__debug__` invalid_syntax@yield_after_comma.py.snap000064400000000000000000000072111046102023000317040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/yield_after_comma.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..20, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..19, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..19, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 9..19, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 12..19, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ), ], }, ) ``` ## Errors | 1 | def f(): 1, yield 1 | ^^^^^^^ Syntax Error: Yield expression cannot be used here invalid_syntax@yield_from_in_async_function.py.snap000064400000000000000000000045101046102023000341610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/yield_from_in_async_function.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..28, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..27, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 10..11, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 11..13, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 15..27, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 15..27, value: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("x"), ctx: Load, }, ), }, ), }, ), ], }, ), ], }, ) ``` ## Semantic Syntax Errors | 1 | async def f(): yield from x | ^^^^^^^^^^^^ Syntax Error: `yield from` statement in async function; use `async for` instead valid_syntax@all_async_comprehension_py310.py.snap000064400000000000000000000231521046102023000335460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/all_async_comprehension_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..126, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..125, is_async: true, decorator_list: [], name: Identifier { id: Name("test"), range: 54..58, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 58..60, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 62..125, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 69..125, elt: ListComp( ExprListComp { node_index: NodeIndex(None), range: 70..100, elt: Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 73..99, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 88..99, func: Name( ExprName { node_index: NodeIndex(None), range: 88..96, id: Name("elements"), ctx: Load, }, ), arguments: Arguments { range: 96..99, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 101..124, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 116..124, func: Name( ExprName { node_index: NodeIndex(None), range: 116..121, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 121..124, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), ), }, ), ], }, ), ], }, ) ``` valid_syntax@ambiguous_lpar_with_items_binary_expr.py.snap000064400000000000000000000502231046102023000355620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/ambiguous_lpar_with_items_binary_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..337, body: [ With( StmtWith { node_index: NodeIndex(None), range: 124..143, is_async: false, items: [ WithItem { range: 129..138, node_index: NodeIndex(None), context_expr: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 129..138, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 130..131, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("b"), ctx: Load, }, ), ], }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 140..143, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 140..143, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 144..166, is_async: false, items: [ WithItem { range: 149..161, node_index: NodeIndex(None), context_expr: Compare( ExprCompare { node_index: NodeIndex(None), range: 149..161, left: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("a"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("b"), ctx: Load, }, ), ], }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 163..166, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 163..166, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 196..220, is_async: false, items: [ WithItem { range: 201..215, node_index: NodeIndex(None), context_expr: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 201..215, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("a"), ctx: Load, }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 208..215, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 208..209, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("c"), ctx: Load, }, ), ], }, ), ], }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 217..220, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 217..220, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 221..245, is_async: false, items: [ WithItem { range: 226..240, node_index: NodeIndex(None), context_expr: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 226..240, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 226..235, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 227..228, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 234..235, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 239..240, id: Name("c"), ctx: Load, }, ), ], }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 242..245, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 242..245, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 246..272, is_async: false, items: [ WithItem { range: 251..267, node_index: NodeIndex(None), context_expr: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 251..267, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 251..263, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 252..257, left: Name( ExprName { node_index: NodeIndex(None), range: 252..253, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 256..257, id: Name("b"), ctx: Load, }, ), }, ), op: LShift, right: Name( ExprName { node_index: NodeIndex(None), range: 262..263, id: Name("c"), ctx: Load, }, ), }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 266..267, id: Name("d"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 269..272, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 269..272, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 312..336, is_async: false, items: [ WithItem { range: 317..331, node_index: NodeIndex(None), context_expr: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 317..331, left: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 317..323, value: Name( ExprName { node_index: NodeIndex(None), range: 318..319, id: Name("a"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 321..322, value: Int( 0, ), }, ), ctx: Load, }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 326..331, left: Name( ExprName { node_index: NodeIndex(None), range: 326..327, id: Name("b"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 330..331, id: Name("c"), ctx: Load, }, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 333..336, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 333..336, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@ambiguous_lpar_with_items_if_expr.py.snap000064400000000000000000000366101046102023000347000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/ambiguous_lpar_with_items_if_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..153, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..28, is_async: false, items: [ WithItem { range: 5..23, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 5..23, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 12..16, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 29..71, is_async: false, items: [ WithItem { range: 34..66, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 34..66, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 55..59, value: true, }, ), body: Generator( ExprGenerator { node_index: NodeIndex(None), range: 34..51, elt: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 37..50, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 46..50, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 68..71, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 68..71, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 72..120, is_async: false, items: [ WithItem { range: 77..115, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 77..115, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 104..108, value: true, }, ), body: Generator( ExprGenerator { node_index: NodeIndex(None), range: 77..100, elt: Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 80..99, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 95..99, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: true, }, ], parenthesized: true, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 117..120, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 117..120, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 121..152, is_async: false, items: [ WithItem { range: 126..147, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 126..147, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 136..140, value: true, }, ), body: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 126..132, value: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("x"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 130..131, value: Int( 0, ), }, ), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 149..152, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 149..152, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@ann_assign_stmt_simple_target.py.snap000064400000000000000000000115741046102023000340270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/ann_assign_stmt_simple_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..45, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..6, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("int"), ctx: Load, }, ), value: None, simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 17..25, target: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("a"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 22..25, id: Name("int"), ctx: Load, }, ), value: None, simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 26..34, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 26..29, value: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 28..29, node_index: NodeIndex(None), }, ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 31..34, id: Name("int"), ctx: Load, }, ), value: None, simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 35..44, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 35..39, value: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("a"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 37..38, value: Int( 0, ), }, ), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 41..44, id: Name("int"), ctx: Load, }, ), value: None, simple: false, }, ), ], }, ) ``` valid_syntax@args_unparenthesized_generator.py.snap000064400000000000000000000500401046102023000342020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/args_unparenthesized_generator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..107, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..51, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..51, func: Name( ExprName { node_index: NodeIndex(None), range: 0..3, id: Name("zip"), ctx: Load, }, ), arguments: Arguments { range: 3..51, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 4..26, elt: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 7..25, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 16..25, func: Name( ExprName { node_index: NodeIndex(None), range: 16..21, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 21..25, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 22..24, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), Generator( ExprGenerator { node_index: NodeIndex(None), range: 28..50, elt: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 31..49, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("y"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 40..49, func: Name( ExprName { node_index: NodeIndex(None), range: 40..45, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 45..49, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 46..48, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 52..77, value: Call( ExprCall { node_index: NodeIndex(None), range: 52..77, func: Name( ExprName { node_index: NodeIndex(None), range: 52..55, id: Name("sum"), ctx: Load, }, ), arguments: Arguments { range: 55..77, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 56..76, elt: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 58..76, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 67..76, func: Name( ExprName { node_index: NodeIndex(None), range: 67..72, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 72..76, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 73..75, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 78..106, value: Call( ExprCall { node_index: NodeIndex(None), range: 78..106, func: Name( ExprName { node_index: NodeIndex(None), range: 78..81, id: Name("sum"), ctx: Load, }, ), arguments: Arguments { range: 81..106, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 82..104, elt: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 85..103, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 94..103, func: Name( ExprName { node_index: NodeIndex(None), range: 94..99, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 99..103, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..102, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` valid_syntax@assign_stmt_starred_expr_value.py.snap000064400000000000000000000161341046102023000342270ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..5, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("_"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..5, value: Int( 4, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 6..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("_"), ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 10..13, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 4, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 14..25, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("_"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 18..25, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 19..23, value: List( ExprList { node_index: NodeIndex(None), range: 20..23, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 1, ), }, ), ], ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 26..35, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("_"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 30..35, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 30..34, value: List( ExprList { node_index: NodeIndex(None), range: 31..34, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), ], ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@assign_targets_terminator.py.snap000064400000000000000000000135471046102023000332040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/assign_targets_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..39, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("y"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 12..13, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..19, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 15..19, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 20..33, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("y"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..38, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 34..38, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@async_for_statement.py.snap000064400000000000000000000032571046102023000317670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/async_for_statement.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..29, is_async: true, target: Name( ExprName { node_index: NodeIndex(None), range: 10..16, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 20..24, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 26..29, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` valid_syntax@async_function_definition.py.snap000064400000000000000000000033271046102023000331500ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/async_function_definition.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..21, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..20, is_async: true, decorator_list: [], name: Identifier { id: Name("foo"), range: 10..13, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 13..15, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@async_with_statement.py.snap000064400000000000000000000032561046102023000321530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/async_with_statement.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..21, body: [ With( StmtWith { node_index: NodeIndex(None), range: 0..20, is_async: true, items: [ WithItem { range: 11..15, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 11..15, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 17..20, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@backslash_continuation_indentation.py.snap000064400000000000000000000063321046102023000350360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/backslash_continuation_indentation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..45, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..24, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 31..32, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 31..32, value: Int( 2, ), }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 33..45, node_index: NodeIndex(None), test: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..45, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..45, value: Int( 3, ), }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@class_def_arguments.py.snap000064400000000000000000000250521046102023000317250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/class_def_arguments.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..115, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..14, decorator_list: [], name: Identifier { id: Name("Foo"), range: 6..9, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 11..14, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 11..14, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 15..31, decorator_list: [], name: Identifier { id: Name("Foo"), range: 21..24, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 24..26, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 28..31, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 28..31, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 32..72, decorator_list: [], name: Identifier { id: Name("Foo"), range: 38..41, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 41..67, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 42..66, elt: Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("base"), ctx: Load, }, ), generators: [ Comprehension { range: 48..65, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 52..56, id: Name("base"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 60..65, id: Name("bases"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..72, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 69..72, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 73..114, decorator_list: [], name: Identifier { id: Name("Foo"), range: 79..82, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 82..109, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 83..108, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 84..108, elt: Name( ExprName { node_index: NodeIndex(None), range: 85..89, id: Name("base"), ctx: Load, }, ), generators: [ Comprehension { range: 90..107, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 94..98, id: Name("base"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 102..107, id: Name("bases"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ctx: Load, }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 111..114, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 111..114, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@class_keyword_in_case_pattern.py.snap000064400000000000000000000104741046102023000340060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..34, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..33, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 2, ), }, ), cases: [ MatchCase { range: 13..33, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 18..28, cls: Name( ExprName { node_index: NodeIndex(None), range: 18..23, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 23..28, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 24..27, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 24..25, node_index: NodeIndex(None), }, pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 26..27, pattern: None, name: Some( Identifier { id: Name("x"), range: 26..27, node_index: NodeIndex(None), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 30..33, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 30..33, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@class_type_params_py312.py.snap000064400000000000000000000150051046102023000323610ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/class_type_params_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..96, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 44..95, decorator_list: [], name: Identifier { id: Name("Foo"), range: 50..53, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 53..90, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 54..69, name: Identifier { id: Name("S"), range: 54..55, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 57..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 58..61, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 63..68, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 71..79, name: Identifier { id: Name("T"), range: 71..72, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 74..79, id: Name("float"), ctx: Load, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 81..84, name: Identifier { id: Name("Ts"), range: 82..84, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 86..89, name: Identifier { id: Name("P"), range: 88..89, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 92..95, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 92..95, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@comma_separated_regular_list_terminator.py.snap000064400000000000000000000167371046102023000360730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/comma_separated_regular_list_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..181, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 141..144, value: List( ExprList { node_index: NodeIndex(None), range: 141..144, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 142..143, value: Int( 0, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 145..151, value: List( ExprList { node_index: NodeIndex(None), range: 145..151, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 146..147, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 152..159, value: List( ExprList { node_index: NodeIndex(None), range: 152..159, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 153..154, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 156..157, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 160..169, value: List( ExprList { node_index: NodeIndex(None), range: 160..169, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 161..162, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 167..168, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 170..180, value: List( ExprList { node_index: NodeIndex(None), range: 170..180, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 171..172, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 174..175, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 177..178, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@debug_rename_import.py.snap000064400000000000000000000067171046102023000317330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/debug_rename_import.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..86, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..25, names: [ Alias { range: 7..25, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 7..16, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("debug"), range: 20..25, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 26..52, module: Some( Identifier { id: Name("__debug__"), range: 31..40, node_index: NodeIndex(None), }, ), names: [ Alias { range: 48..52, node_index: NodeIndex(None), name: Identifier { id: Name("Some"), range: 48..52, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 53..85, module: Some( Identifier { id: Name("x"), range: 58..59, node_index: NodeIndex(None), }, ), names: [ Alias { range: 67..85, node_index: NodeIndex(None), name: Identifier { id: Name("__debug__"), range: 67..76, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("debug"), range: 80..85, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@decorator_async_function.py.snap000064400000000000000000000044051046102023000330000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_async_function.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..32, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..31, is_async: true, decorator_list: [ Decorator { range: 0..10, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1..10, id: Name("decorator"), ctx: Load, }, ), }, ], name: Identifier { id: Name("foo"), range: 21..24, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 24..26, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 28..31, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 28..31, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@decorator_await_expression_py39.py.snap000064400000000000000000000102351046102023000342240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_await_expression_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..96, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..95, is_async: true, decorator_list: [], name: Identifier { id: Name("foo"), range: 55..58, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 58..60, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 66..95, is_async: false, decorator_list: [ Decorator { range: 66..76, node_index: NodeIndex(None), expression: Await( ExprAwait { node_index: NodeIndex(None), range: 67..76, value: Name( ExprName { node_index: NodeIndex(None), range: 73..76, id: Name("bar"), ctx: Load, }, ), }, ), }, ], name: Identifier { id: Name("baz"), range: 85..88, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 88..90, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 92..95, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 92..95, }, ), }, ), ], }, ), ], }, ), ], }, ) ``` valid_syntax@decorator_expression_dotted_ident_py38.py.snap000064400000000000000000000072521046102023000355710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_expression_dotted_ident_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..86, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..85, is_async: false, decorator_list: [ Decorator { range: 45..69, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..69, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..61, value: Name( ExprName { node_index: NodeIndex(None), range: 46..53, id: Name("buttons"), ctx: Load, }, ), attr: Identifier { id: Name("clicked"), range: 54..61, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("connect"), range: 62..69, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("spam"), range: 74..78, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 78..80, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 82..85, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 82..85, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@decorator_expression_eval_hack_py38.py.snap000064400000000000000000000107341046102023000350370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_expression_eval_hack_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..97, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..96, is_async: false, decorator_list: [ Decorator { range: 45..80, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 46..80, func: Name( ExprName { node_index: NodeIndex(None), range: 46..50, id: Name("eval"), ctx: Load, }, ), arguments: Arguments { range: 50..80, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 51..79, value: StringLiteralValue { inner: Single( StringLiteral { range: 51..79, node_index: NodeIndex(None), value: "buttons[0].clicked.connect", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), }, ], name: Identifier { id: Name("spam"), range: 85..89, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 89..91, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 93..96, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 93..96, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@decorator_expression_identity_hack_py38.py.snap000064400000000000000000000217231046102023000357410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_expression_identity_hack_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..111, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..63, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 49..50, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 50..53, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 51..52, node_index: NodeIndex(None), parameter: Parameter { range: 51..52, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 51..52, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 55..63, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 64..110, is_async: false, decorator_list: [ Decorator { range: 64..94, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 65..94, func: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("_"), ctx: Load, }, ), arguments: Arguments { range: 66..94, node_index: NodeIndex(None), args: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 67..93, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 67..85, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 67..77, value: Name( ExprName { node_index: NodeIndex(None), range: 67..74, id: Name("buttons"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 0, ), }, ), ctx: Load, }, ), attr: Identifier { id: Name("clicked"), range: 78..85, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("connect"), range: 86..93, node_index: NodeIndex(None), }, ctx: Load, }, ), ], keywords: [], }, }, ), }, ], name: Identifier { id: Name("spam"), range: 99..103, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 103..105, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 107..110, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 107..110, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@decorator_expression_py39.py.snap000064400000000000000000000264561046102023000330530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/decorator_expression_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..129, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 45..88, is_async: false, decorator_list: [ Decorator { range: 45..72, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..72, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 46..64, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 46..56, value: Name( ExprName { node_index: NodeIndex(None), range: 46..53, id: Name("buttons"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 0, ), }, ), ctx: Load, }, ), attr: Identifier { id: Name("clicked"), range: 57..64, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("connect"), range: 65..72, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("spam"), range: 77..81, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 81..83, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 85..88, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 85..88, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 89..128, is_async: false, decorator_list: [ Decorator { range: 89..113, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 90..113, func: Named( ExprNamed { node_index: NodeIndex(None), range: 91..107, target: Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("x"), ctx: Store, }, ), value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 96..107, parameters: Some( Parameters { range: 103..104, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 103..104, node_index: NodeIndex(None), parameter: Parameter { range: 103..104, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 103..104, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("x"), ctx: Load, }, ), }, ), }, ), arguments: Arguments { range: 108..113, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 109..112, id: Name("foo"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ], name: Identifier { id: Name("bar"), range: 118..121, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 121..123, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 125..128, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 125..128, }, ), }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@del_debug_py38.py.snap000064400000000000000000000014701046102023000305670ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/del_debug_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 43..56, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 47..56, id: Name("__debug__"), ctx: Del, }, ), ], }, ), ], }, ) ``` valid_syntax@del_targets_terminator.py.snap000064400000000000000000000110451046102023000324530ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/del_targets_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..29, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..8, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("a"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("b"), ctx: Del, }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..14, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 10..14, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("c"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("d"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 15..23, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("a"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("b"), ctx: Del, }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 24..28, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 24..28, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("c"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("d"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@different_match_pattern_bindings.py.snap000064400000000000000000000656301046102023000344570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/different_match_pattern_bindings.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..147, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..146, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..32, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 18..27, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 18..21, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 19..20, pattern: None, name: Some( Identifier { id: Name("a"), range: 19..20, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 24..27, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 25..26, pattern: None, name: Some( Identifier { id: Name("a"), range: 25..26, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, MatchCase { range: 37..62, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 42..57, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 42..48, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 43..44, pattern: None, name: Some( Identifier { id: Name("x"), range: 43..44, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 46..47, pattern: None, name: Some( Identifier { id: Name("y"), range: 46..47, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 51..57, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 52..53, pattern: None, name: Some( Identifier { id: Name("x"), range: 52..53, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 55..56, pattern: None, name: Some( Identifier { id: Name("y"), range: 55..56, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 59..62, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 59..62, }, ), }, ), ], }, MatchCase { range: 67..89, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 72..84, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 73..74, pattern: None, name: Some( Identifier { id: Name("x"), range: 73..74, node_index: NodeIndex(None), }, ), }, ), MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 77..82, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 77..78, pattern: None, name: Some( Identifier { id: Name("y"), range: 77..78, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 81..82, pattern: None, name: Some( Identifier { id: Name("y"), range: 81..82, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 86..89, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 86..89, }, ), }, ), ], }, MatchCase { range: 94..119, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 99..114, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 99..105, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 100..101, pattern: None, name: Some( Identifier { id: Name("a"), range: 100..101, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 103..104, pattern: None, name: None, }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 108..114, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 109..110, pattern: None, name: Some( Identifier { id: Name("a"), range: 109..110, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 112..113, pattern: None, name: None, }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 116..119, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 116..119, }, ), }, ), ], }, MatchCase { range: 124..146, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 129..141, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 129..132, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 130..131, pattern: None, name: Some( Identifier { id: Name("a"), range: 130..131, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 135..141, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 136..140, cls: Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("C"), ctx: Load, }, ), arguments: PatternArguments { range: 137..140, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 138..139, pattern: None, name: Some( Identifier { id: Name("a"), range: 138..139, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 143..146, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 143..146, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@dotted_name_normalized_spaces.py.snap000064400000000000000000000032051046102023000337560ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/dotted_name_normalized_spaces.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..32, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..12, names: [ Alias { range: 7..12, node_index: NodeIndex(None), name: Identifier { id: Name("a.b.c"), range: 7..12, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 13..31, names: [ Alias { range: 20..31, node_index: NodeIndex(None), name: Identifier { id: Name("a.b.c"), range: 20..31, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), ], }, ) ``` valid_syntax@duplicate_match_key_attr.py.snap000064400000000000000000000147221046102023000327470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/duplicate_match_key_attr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..40, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..39, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..39, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 18..34, keys: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 19..22, value: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("a"), range: 21..22, node_index: NodeIndex(None), }, ctx: Load, }, ), Attribute( ExprAttribute { node_index: NodeIndex(None), range: 27..30, value: Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("a"), range: 29..30, node_index: NodeIndex(None), }, ctx: Load, }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 24..25, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 32..33, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 2, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 36..39, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 36..39, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@except_star_py311.py.snap000064400000000000000000000053241046102023000311730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/except_star_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..77, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 44..76, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 53..76, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 61..71, id: Name("ValueError"), ctx: Load, }, ), ), name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 73..76, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 73..76, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` valid_syntax@except_stmt_as_name_soft_keyword.py.snap000064400000000000000000000153141046102023000345360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/except_stmt_as_name_soft_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..100, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..99, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5..8, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5..8, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 9..39, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 16..25, id: Name("Exception"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("match"), range: 29..34, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 36..39, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 36..39, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 40..69, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 47..56, id: Name("Exception"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("case"), range: 60..64, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 66..69, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 66..69, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 70..99, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 77..86, id: Name("Exception"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("type"), range: 90..94, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), ], }, ) ``` valid_syntax@except_stmt_unparenthesized_tuple_no_as_py314.py.snap000064400000000000000000000140501046102023000370700ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/except_stmt_unparenthesized_tuple_no_as_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..117, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 44..79, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 53..57, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 58..79, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 65..69, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 75..79, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 80..116, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 89..93, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 94..116, node_index: NodeIndex(None), type_: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 102..106, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 112..116, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), ], }, ) ``` valid_syntax@expressions__arguments.py.snap000064400000000000000000003060511046102023000325240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/arguments.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..805, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 102..108, value: Call( ExprCall { node_index: NodeIndex(None), range: 102..108, func: Name( ExprName { node_index: NodeIndex(None), range: 102..106, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 106..108, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 109..119, value: Call( ExprCall { node_index: NodeIndex(None), range: 109..119, func: Name( ExprName { node_index: NodeIndex(None), range: 109..113, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 113..119, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 117..118, id: Name("y"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 120..131, value: Call( ExprCall { node_index: NodeIndex(None), range: 120..131, func: Name( ExprName { node_index: NodeIndex(None), range: 120..124, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 124..131, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("y"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 150..164, value: Call( ExprCall { node_index: NodeIndex(None), range: 150..164, func: Name( ExprName { node_index: NodeIndex(None), range: 150..154, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 154..164, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 155..158, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 155..156, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 157..158, value: Int( 1, ), }, ), }, Keyword { range: 160..163, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("y"), range: 160..161, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 162..163, value: Int( 2, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 165..173, value: Call( ExprCall { node_index: NodeIndex(None), range: 165..173, func: Name( ExprName { node_index: NodeIndex(None), range: 165..169, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 169..173, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 170..172, value: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 174..183, value: Call( ExprCall { node_index: NodeIndex(None), range: 174..183, func: Name( ExprName { node_index: NodeIndex(None), range: 174..178, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 178..183, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 179..182, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 181..182, id: Name("x"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..205, value: Call( ExprCall { node_index: NodeIndex(None), range: 193..205, func: Name( ExprName { node_index: NodeIndex(None), range: 193..197, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 197..205, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 198..199, id: Name("x"), ctx: Load, }, ), ], keywords: [ Keyword { range: 201..204, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("y"), range: 201..202, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 203..204, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 206..217, value: Call( ExprCall { node_index: NodeIndex(None), range: 206..217, func: Name( ExprName { node_index: NodeIndex(None), range: 206..210, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 210..217, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 211..212, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 214..216, value: Name( ExprName { node_index: NodeIndex(None), range: 215..216, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 218..230, value: Call( ExprCall { node_index: NodeIndex(None), range: 218..230, func: Name( ExprName { node_index: NodeIndex(None), range: 218..222, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 222..230, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 223..224, id: Name("x"), ctx: Load, }, ), ], keywords: [ Keyword { range: 226..229, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 228..229, id: Name("y"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 231..244, value: Call( ExprCall { node_index: NodeIndex(None), range: 231..244, func: Name( ExprName { node_index: NodeIndex(None), range: 231..235, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 235..244, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 241..243, value: Name( ExprName { node_index: NodeIndex(None), range: 242..243, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 236..239, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 236..237, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 238..239, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 245..259, value: Call( ExprCall { node_index: NodeIndex(None), range: 245..259, func: Name( ExprName { node_index: NodeIndex(None), range: 245..249, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 249..259, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 250..253, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 250..251, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 252..253, value: Int( 1, ), }, ), }, Keyword { range: 255..258, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 257..258, id: Name("y"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 260..273, value: Call( ExprCall { node_index: NodeIndex(None), range: 260..273, func: Name( ExprName { node_index: NodeIndex(None), range: 260..264, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 264..273, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 265..267, value: Name( ExprName { node_index: NodeIndex(None), range: 266..267, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 269..272, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 271..272, id: Name("y"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 274..288, value: Call( ExprCall { node_index: NodeIndex(None), range: 274..288, func: Name( ExprName { node_index: NodeIndex(None), range: 274..278, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 278..288, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 279..281, value: Name( ExprName { node_index: NodeIndex(None), range: 280..281, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 283..284, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 286..287, id: Name("z"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 289..308, value: Call( ExprCall { node_index: NodeIndex(None), range: 289..308, func: Name( ExprName { node_index: NodeIndex(None), range: 289..293, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 293..308, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 294..297, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 296..297, id: Name("x"), ctx: Load, }, ), }, Keyword { range: 299..302, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("y"), range: 299..300, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 301..302, value: Int( 1, ), }, ), }, Keyword { range: 304..307, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("z"), range: 304..305, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 306..307, value: Int( 2, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 309..335, value: Call( ExprCall { node_index: NodeIndex(None), range: 309..335, func: Name( ExprName { node_index: NodeIndex(None), range: 309..313, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 313..335, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 314..317, value: Name( ExprName { node_index: NodeIndex(None), range: 315..317, id: Name("x1"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 319..322, value: Name( ExprName { node_index: NodeIndex(None), range: 320..322, id: Name("x2"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 324..328, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 326..328, id: Name("y1"), ctx: Load, }, ), }, Keyword { range: 330..334, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 332..334, id: Name("y2"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 336..355, value: Call( ExprCall { node_index: NodeIndex(None), range: 336..355, func: Name( ExprName { node_index: NodeIndex(None), range: 336..340, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 340..355, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 341..344, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 341..342, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 343..344, value: Int( 1, ), }, ), }, Keyword { range: 346..349, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 348..349, id: Name("y"), ctx: Load, }, ), }, Keyword { range: 351..354, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("z"), range: 351..352, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 353..354, value: Int( 1, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 378..402, value: Call( ExprCall { node_index: NodeIndex(None), range: 378..402, func: Name( ExprName { node_index: NodeIndex(None), range: 378..382, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 382..402, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 383..401, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 383..384, node_index: NodeIndex(None), }, ), value: If( ExprIf { node_index: NodeIndex(None), range: 385..401, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 390..394, value: true, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 385..386, value: Int( 1, ), }, ), orelse: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 400..401, value: Int( 2, ), }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 403..418, value: Call( ExprCall { node_index: NodeIndex(None), range: 403..418, func: Name( ExprName { node_index: NodeIndex(None), range: 403..407, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 407..418, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 408..417, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 408..409, node_index: NodeIndex(None), }, ), value: Await( ExprAwait { node_index: NodeIndex(None), range: 410..417, value: Name( ExprName { node_index: NodeIndex(None), range: 416..417, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 419..438, value: Call( ExprCall { node_index: NodeIndex(None), range: 419..438, func: Name( ExprName { node_index: NodeIndex(None), range: 419..423, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 423..438, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 424..437, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 424..425, node_index: NodeIndex(None), }, ), value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 426..437, parameters: Some( Parameters { range: 433..434, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 433..434, node_index: NodeIndex(None), parameter: Parameter { range: 433..434, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 433..434, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 436..437, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 439..455, value: Call( ExprCall { node_index: NodeIndex(None), range: 439..455, func: Name( ExprName { node_index: NodeIndex(None), range: 439..443, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 443..455, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 444..454, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("x"), range: 444..445, node_index: NodeIndex(None), }, ), value: Named( ExprNamed { node_index: NodeIndex(None), range: 447..453, target: Name( ExprName { node_index: NodeIndex(None), range: 447..448, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 452..453, value: Int( 1, ), }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 476..491, value: Call( ExprCall { node_index: NodeIndex(None), range: 476..491, func: Name( ExprName { node_index: NodeIndex(None), range: 476..480, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 480..491, node_index: NodeIndex(None), args: [ Yield( ExprYield { node_index: NodeIndex(None), range: 482..489, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 488..489, id: Name("x"), ctx: Load, }, ), ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 492..512, value: Call( ExprCall { node_index: NodeIndex(None), range: 492..512, func: Name( ExprName { node_index: NodeIndex(None), range: 492..496, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 496..512, node_index: NodeIndex(None), args: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 498..510, value: Name( ExprName { node_index: NodeIndex(None), range: 509..510, id: Name("x"), ctx: Load, }, ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 533..545, value: Call( ExprCall { node_index: NodeIndex(None), range: 533..545, func: Name( ExprName { node_index: NodeIndex(None), range: 533..537, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 537..545, node_index: NodeIndex(None), args: [ Named( ExprNamed { node_index: NodeIndex(None), range: 538..544, target: Name( ExprName { node_index: NodeIndex(None), range: 538..539, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 543..544, value: Int( 1, ), }, ), }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 546..572, value: Call( ExprCall { node_index: NodeIndex(None), range: 546..572, func: Name( ExprName { node_index: NodeIndex(None), range: 546..550, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 550..572, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 551..571, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 551..557, target: Name( ExprName { node_index: NodeIndex(None), range: 551..552, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 556..557, value: Int( 1, ), }, ), }, ), generators: [ Comprehension { range: 558..571, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 562..563, id: Name("i"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 567..571, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 596..610, value: Call( ExprCall { node_index: NodeIndex(None), range: 596..610, func: Name( ExprName { node_index: NodeIndex(None), range: 596..600, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 600..610, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 601..609, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 602..609, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 602..603, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 608..609, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 611..623, value: Call( ExprCall { node_index: NodeIndex(None), range: 611..623, func: Name( ExprName { node_index: NodeIndex(None), range: 611..615, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 615..623, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 616..622, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 617..622, left: Name( ExprName { node_index: NodeIndex(None), range: 617..618, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 621..622, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 624..638, value: Call( ExprCall { node_index: NodeIndex(None), range: 624..638, func: Name( ExprName { node_index: NodeIndex(None), range: 624..628, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 628..638, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 629..637, value: Await( ExprAwait { node_index: NodeIndex(None), range: 630..637, value: Name( ExprName { node_index: NodeIndex(None), range: 636..637, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 639..657, value: Call( ExprCall { node_index: NodeIndex(None), range: 639..657, func: Name( ExprName { node_index: NodeIndex(None), range: 639..643, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 643..657, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 644..656, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 645..656, parameters: Some( Parameters { range: 652..653, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 652..653, node_index: NodeIndex(None), parameter: Parameter { range: 652..653, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 652..653, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 655..656, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 658..681, value: Call( ExprCall { node_index: NodeIndex(None), range: 658..681, func: Name( ExprName { node_index: NodeIndex(None), range: 658..662, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 662..681, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 663..680, value: If( ExprIf { node_index: NodeIndex(None), range: 664..680, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 669..673, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 664..665, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 679..680, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 700..709, value: Call( ExprCall { node_index: NodeIndex(None), range: 700..709, func: Name( ExprName { node_index: NodeIndex(None), range: 700..704, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 704..709, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 705..708, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 707..708, id: Name("x"), ctx: Load, }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 710..725, value: Call( ExprCall { node_index: NodeIndex(None), range: 710..725, func: Name( ExprName { node_index: NodeIndex(None), range: 710..714, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 714..725, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 715..724, node_index: NodeIndex(None), arg: None, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 717..724, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 717..718, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 723..724, id: Name("y"), ctx: Load, }, ), ], }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 726..741, value: Call( ExprCall { node_index: NodeIndex(None), range: 726..741, func: Name( ExprName { node_index: NodeIndex(None), range: 726..730, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 730..741, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 731..740, node_index: NodeIndex(None), arg: None, value: Await( ExprAwait { node_index: NodeIndex(None), range: 733..740, value: Name( ExprName { node_index: NodeIndex(None), range: 739..740, id: Name("x"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 742..766, value: Call( ExprCall { node_index: NodeIndex(None), range: 742..766, func: Name( ExprName { node_index: NodeIndex(None), range: 742..746, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 746..766, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 747..765, node_index: NodeIndex(None), arg: None, value: If( ExprIf { node_index: NodeIndex(None), range: 749..765, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 754..758, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 749..750, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 764..765, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 767..784, value: Call( ExprCall { node_index: NodeIndex(None), range: 767..784, func: Name( ExprName { node_index: NodeIndex(None), range: 767..771, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 771..784, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 772..783, node_index: NodeIndex(None), arg: None, value: Yield( ExprYield { node_index: NodeIndex(None), range: 775..782, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 781..782, id: Name("x"), ctx: Load, }, ), ), }, ), }, ], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 785..804, value: Call( ExprCall { node_index: NodeIndex(None), range: 785..804, func: Name( ExprName { node_index: NodeIndex(None), range: 785..789, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 789..804, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 790..803, node_index: NodeIndex(None), arg: None, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 792..803, parameters: Some( Parameters { range: 799..800, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 799..800, node_index: NodeIndex(None), parameter: Parameter { range: 799..800, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 799..800, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 802..803, id: Name("x"), ctx: Load, }, ), }, ), }, ], }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__attribute.py.snap000064400000000000000000000275261046102023000325310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/attribute.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..90, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 0..10, value: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("value"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 6..10, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..23, value: Call( ExprCall { node_index: NodeIndex(None), range: 11..23, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 11..21, value: Name( ExprName { node_index: NodeIndex(None), range: 11..16, id: Name("value"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 17..21, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 21..23, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 24..36, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 24..36, value: Call( ExprCall { node_index: NodeIndex(None), range: 24..31, func: Name( ExprName { node_index: NodeIndex(None), range: 24..29, id: Name("value"), ctx: Load, }, ), arguments: Arguments { range: 29..31, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("attr"), range: 32..36, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 37..55, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 37..55, value: Call( ExprCall { node_index: NodeIndex(None), range: 37..51, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 37..49, value: Call( ExprCall { node_index: NodeIndex(None), range: 37..44, func: Name( ExprName { node_index: NodeIndex(None), range: 37..42, id: Name("value"), ctx: Load, }, ), arguments: Arguments { range: 42..44, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("attr"), range: 45..49, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 49..51, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("foo"), range: 52..55, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 56..70, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 56..70, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 56..66, value: Name( ExprName { node_index: NodeIndex(None), range: 56..61, id: Name("value"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 62..66, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("foo"), range: 67..70, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 71..89, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 71..89, value: Call( ExprCall { node_index: NodeIndex(None), range: 71..85, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 71..83, value: Name( ExprName { node_index: NodeIndex(None), range: 72..77, id: Name("value"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 79..83, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 83..85, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("foo"), range: 86..89, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__await.py.snap000064400000000000000000000637001046102023000316250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/await.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..211, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: Await( ExprAwait { node_index: NodeIndex(None), range: 0..7, value: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..19, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 8..19, left: Await( ExprAwait { node_index: NodeIndex(None), range: 8..15, value: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Load, }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..33, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 20..33, op: And, values: [ Await( ExprAwait { node_index: NodeIndex(None), range: 20..27, value: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("a"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..43, value: Await( ExprAwait { node_index: NodeIndex(None), range: 34..43, value: Call( ExprCall { node_index: NodeIndex(None), range: 40..43, func: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 41..43, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 44..56, value: Await( ExprAwait { node_index: NodeIndex(None), range: 44..56, value: List( ExprList { node_index: NodeIndex(None), range: 50..56, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..69, value: Await( ExprAwait { node_index: NodeIndex(None), range: 57..69, value: Set( ExprSet { node_index: NodeIndex(None), range: 63..69, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..65, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 67..68, value: Int( 4, ), }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 70..82, value: Await( ExprAwait { node_index: NodeIndex(None), range: 70..82, value: Dict( ExprDict { node_index: NodeIndex(None), range: 76..82, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("i"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 80..81, value: Int( 5, ), }, ), }, ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 83..93, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 83..93, elts: [ Await( ExprAwait { node_index: NodeIndex(None), range: 83..90, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 7, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 92..93, value: Int( 8, ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 94..107, value: Await( ExprAwait { node_index: NodeIndex(None), range: 94..107, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 100..107, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 101..102, value: Int( 9, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..106, value: Int( 10, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 108..120, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 108..120, left: Await( ExprAwait { node_index: NodeIndex(None), range: 108..115, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 114..115, value: Int( 1, ), }, ), }, ), ops: [ Eq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..146, value: If( ExprIf { node_index: NodeIndex(None), range: 121..146, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 132..136, value: true, }, ), body: Await( ExprAwait { node_index: NodeIndex(None), range: 121..128, value: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("x"), ctx: Load, }, ), }, ), orelse: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 142..146, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 147..158, value: Await( ExprAwait { node_index: NodeIndex(None), range: 147..158, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 153..158, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 154..156, value: Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 159..178, value: Await( ExprAwait { node_index: NodeIndex(None), range: 159..178, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 166..177, parameters: Some( Parameters { range: 173..174, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 173..174, node_index: NodeIndex(None), parameter: Parameter { range: 173..174, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 173..174, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 176..177, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 179..192, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 179..192, left: Await( ExprAwait { node_index: NodeIndex(None), range: 179..186, value: Name( ExprName { node_index: NodeIndex(None), range: 185..186, id: Name("x"), ctx: Load, }, ), }, ), op: Pow, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 190..192, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 191..192, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..211, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 193..211, left: Await( ExprAwait { node_index: NodeIndex(None), range: 193..200, value: Name( ExprName { node_index: NodeIndex(None), range: 199..200, id: Name("x"), ctx: Load, }, ), }, ), op: Pow, right: Await( ExprAwait { node_index: NodeIndex(None), range: 204..211, value: Name( ExprName { node_index: NodeIndex(None), range: 210..211, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__bin_op.py.snap000064400000000000000000001633271046102023000317740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/bin_op.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..397, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..14, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 9..14, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..20, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 15..20, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 15..16, value: Int( 1, ), }, ), op: Sub, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..26, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 21..26, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 1, ), }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..32, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 27..32, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 1, ), }, ), op: Div, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 31..32, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 33..39, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 33..39, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..34, value: Int( 1, ), }, ), op: FloorDiv, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 40..45, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 40..45, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 40..41, value: Int( 1, ), }, ), op: Mod, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..45, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 46..52, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 46..52, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 46..47, value: Int( 1, ), }, ), op: Pow, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..58, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 53..58, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 1, ), }, ), op: BitOr, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 59..64, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 59..64, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 59..60, value: Int( 1, ), }, ), op: BitXor, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 65..70, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 65..70, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 1, ), }, ), op: BitAnd, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 69..70, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 71..77, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 71..77, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 1, ), }, ), op: RShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 78..84, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 78..84, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 1, ), }, ), op: LShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 85..90, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 85..90, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 85..86, value: Int( 1, ), }, ), op: MatMult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 110..123, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 110..123, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 110..119, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 110..115, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 110..111, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 114..115, value: Int( 2, ), }, ), }, ), op: Sub, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 3, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 4, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 124..146, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 124..146, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 124..142, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 124..138, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 124..133, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 124..129, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 124..125, value: Int( 1, ), }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 2, ), }, ), }, ), op: Div, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 132..133, value: Int( 3, ), }, ), }, ), op: FloorDiv, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 137..138, value: Int( 4, ), }, ), }, ), op: MatMult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 141..142, value: Int( 5, ), }, ), }, ), op: Mod, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 145..146, value: Int( 6, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 147..168, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 147..168, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 147..163, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 147..158, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 147..153, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 147..148, value: Int( 1, ), }, ), op: LShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 152..153, value: Int( 2, ), }, ), }, ), op: RShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 157..158, value: Int( 3, ), }, ), }, ), op: RShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 162..163, value: Int( 4, ), }, ), }, ), op: LShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 167..168, value: Int( 5, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..202, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 193..202, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 193..194, value: Int( 1, ), }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 197..202, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..198, value: Int( 2, ), }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 3, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 203..212, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 203..212, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 203..208, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 203..204, value: Int( 1, ), }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 207..208, value: Int( 2, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 211..212, value: Int( 3, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 213..244, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 213..244, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 213..235, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 213..231, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 213..223, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 213..219, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..214, value: Int( 1, ), }, ), op: Pow, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 218..219, value: Int( 2, ), }, ), }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 222..223, value: Int( 3, ), }, ), }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 226..231, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 226..227, value: Int( 4, ), }, ), op: MatMult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 230..231, value: Int( 5, ), }, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 234..235, value: Int( 6, ), }, ), }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 238..244, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 238..239, value: Int( 7, ), }, ), op: FloorDiv, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 243..244, value: Int( 8, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 270..306, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 270..306, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 270..271, value: Int( 1, ), }, ), op: BitOr, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 274..306, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 274..279, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 274..275, value: Int( 2, ), }, ), op: BitAnd, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 278..279, value: Int( 3, ), }, ), }, ), op: BitXor, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 282..306, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 282..301, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 282..291, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 282..283, value: Int( 4, ), }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 286..291, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 286..287, value: Int( 5, ), }, ), op: MatMult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 290..291, value: Int( 6, ), }, ), }, ), }, ), op: LShift, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 295..301, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 295..296, value: Int( 7, ), }, ), op: FloorDiv, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 300..301, value: Int( 8, ), }, ), }, ), }, ), op: RShift, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 305..306, value: Int( 9, ), }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 324..339, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 324..339, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 324..335, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 324..325, value: Int( 1, ), }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 329..334, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 329..330, value: Int( 2, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 333..334, value: Int( 3, ), }, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 338..339, value: Int( 4, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 340..359, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 340..359, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 340..345, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 340..341, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 344..345, value: Int( 2, ), }, ), }, ), op: Add, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 349..358, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 349..354, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 349..350, value: Int( 3, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 353..354, value: Int( 4, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 357..358, value: Int( 5, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 390..396, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 390..396, left: Name( ExprName { node_index: NodeIndex(None), range: 390..391, id: Name("x"), ctx: Load, }, ), op: Add, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 393..396, op: UAdd, operand: Name( ExprName { node_index: NodeIndex(None), range: 395..396, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__bool_op.py.snap000064400000000000000000000521261046102023000321510ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/bool_op.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..142, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..7, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 0..7, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 8..21, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 8..21, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..28, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 22..28, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 29..40, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 29..40, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 41..53, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 41..53, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 41..48, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 54..88, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 54..88, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 54..67, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("c"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("d"), ctx: Load, }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 76..83, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 76..77, id: Name("e"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("f"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("g"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 89..105, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 89..105, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 89..100, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("a"), ctx: Load, }, ), UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 95..100, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("b"), ctx: Load, }, ), }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 106..124, value: Yield( ExprYield { node_index: NodeIndex(None), range: 106..124, value: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 112..124, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 112..119, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 123..124, id: Name("c"), ctx: Load, }, ), ], }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 125..141, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 125..141, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 125..136, op: And, values: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 125..130, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("a"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__call.py.snap000064400000000000000000000755201046102023000314360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/call.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..349, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 114..120, value: Call( ExprCall { node_index: NodeIndex(None), range: 114..120, func: Name( ExprName { node_index: NodeIndex(None), range: 114..118, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 118..120, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..132, value: Call( ExprCall { node_index: NodeIndex(None), range: 121..132, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 121..130, value: Name( ExprName { node_index: NodeIndex(None), range: 121..125, id: Name("attr"), ctx: Load, }, ), attr: Identifier { id: Name("expr"), range: 126..130, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 130..132, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..150, value: Call( ExprCall { node_index: NodeIndex(None), range: 133..150, func: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 133..148, value: Name( ExprName { node_index: NodeIndex(None), range: 133..142, id: Name("subscript"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 143..147, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..144, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 146..147, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), arguments: Arguments { range: 148..150, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 151..162, value: Call( ExprCall { node_index: NodeIndex(None), range: 151..162, func: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 151..160, value: Name( ExprName { node_index: NodeIndex(None), range: 151..156, id: Name("slice"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 157..159, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 1, ), }, ), ), step: None, }, ), ctx: Load, }, ), arguments: Arguments { range: 160..162, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 163..174, value: Call( ExprCall { node_index: NodeIndex(None), range: 163..174, func: List( ExprList { node_index: NodeIndex(None), range: 163..172, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 167..168, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 170..171, value: Int( 3, ), }, ), ], ctx: Load, }, ), arguments: Arguments { range: 172..174, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 175..186, value: Call( ExprCall { node_index: NodeIndex(None), range: 175..186, func: Tuple( ExprTuple { node_index: NodeIndex(None), range: 175..184, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 176..177, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 179..180, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 182..183, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), arguments: Arguments { range: 184..186, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 187..206, value: Call( ExprCall { node_index: NodeIndex(None), range: 187..206, func: Generator( ExprGenerator { node_index: NodeIndex(None), range: 187..204, elt: Name( ExprName { node_index: NodeIndex(None), range: 188..189, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 190..203, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 194..195, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 199..203, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), arguments: Arguments { range: 204..206, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 207..218, value: Call( ExprCall { node_index: NodeIndex(None), range: 207..218, func: Set( ExprSet { node_index: NodeIndex(None), range: 207..216, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 208..209, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 211..212, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 214..215, value: Int( 3, ), }, ), ], }, ), arguments: Arguments { range: 216..218, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 219..233, value: Call( ExprCall { node_index: NodeIndex(None), range: 219..233, func: Dict( ExprDict { node_index: NodeIndex(None), range: 219..231, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 220..221, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 223..224, value: Int( 2, ), }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 226..227, value: Int( 3, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 229..230, value: Int( 4, ), }, ), }, ], }, ), arguments: Arguments { range: 231..233, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 234..245, value: Call( ExprCall { node_index: NodeIndex(None), range: 234..245, func: Yield( ExprYield { node_index: NodeIndex(None), range: 235..242, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 241..242, id: Name("x"), ctx: Load, }, ), ), }, ), arguments: Arguments { range: 243..245, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 306..312, value: Call( ExprCall { node_index: NodeIndex(None), range: 306..312, func: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 306..310, value: true, }, ), arguments: Arguments { range: 310..312, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 313..320, value: Call( ExprCall { node_index: NodeIndex(None), range: 313..320, func: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 313..318, value: false, }, ), arguments: Arguments { range: 318..320, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 321..327, value: Call( ExprCall { node_index: NodeIndex(None), range: 321..327, func: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 321..325, }, ), arguments: Arguments { range: 325..327, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 328..338, value: Call( ExprCall { node_index: NodeIndex(None), range: 328..338, func: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 328..336, value: StringLiteralValue { inner: Single( StringLiteral { range: 328..336, node_index: NodeIndex(None), value: "string", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), arguments: Arguments { range: 336..338, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 339..342, value: Call( ExprCall { node_index: NodeIndex(None), range: 339..342, func: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 339..340, value: Int( 1, ), }, ), arguments: Arguments { range: 340..342, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 343..348, value: Call( ExprCall { node_index: NodeIndex(None), range: 343..348, func: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 343..346, value: Float( 1.0, ), }, ), arguments: Arguments { range: 346..348, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__compare.py.snap000064400000000000000000001030041046102023000321360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/compare.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..542, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..15, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 9..15, left: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("a"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..21, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 16..21, left: Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("b"), ctx: Load, }, ), ops: [ Lt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("a"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..27, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 22..27, left: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("b"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("a"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..34, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 28..34, left: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("a"), ctx: Load, }, ), ops: [ GtE, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 35..41, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 35..41, left: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("a"), ctx: Load, }, ), ops: [ LtE, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 42..48, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 42..48, left: Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("a"), ctx: Load, }, ), ops: [ NotEq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..55, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 49..55, left: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("a"), ctx: Load, }, ), ops: [ Is, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 56..62, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 56..62, left: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("a"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 61..62, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 63..73, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 63..73, left: Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("a"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 74..84, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 74..84, left: Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("a"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("b"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 110..156, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 110..156, left: Name( ExprName { node_index: NodeIndex(None), range: 110..111, id: Name("a"), ctx: Load, }, ), ops: [ NotIn, IsNot, NotIn, NotIn, IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 119..120, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("c"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("e"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("f"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 177..203, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 177..203, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 177..182, left: Name( ExprName { node_index: NodeIndex(None), range: 177..178, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 181..182, id: Name("b"), ctx: Load, }, ), }, ), ops: [ Lt, NotIn, ], comparators: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 185..190, left: Name( ExprName { node_index: NodeIndex(None), range: 185..186, id: Name("c"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("d"), ctx: Load, }, ), }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 198..203, left: Name( ExprName { node_index: NodeIndex(None), range: 198..199, id: Name("e"), ctx: Load, }, ), op: BitAnd, right: Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("f"), ctx: Load, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 379..393, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 379..393, op: Not, operand: Compare( ExprCompare { node_index: NodeIndex(None), range: 383..393, left: Name( ExprName { node_index: NodeIndex(None), range: 383..384, id: Name("x"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 392..393, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 395..416, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 395..416, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 395..396, id: Name("x"), ctx: Load, }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 400..416, op: And, values: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 400..410, left: Name( ExprName { node_index: NodeIndex(None), range: 400..401, id: Name("y"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 409..410, id: Name("z"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 415..416, id: Name("a"), ctx: Load, }, ), ], }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 417..429, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 417..429, left: Name( ExprName { node_index: NodeIndex(None), range: 417..418, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Await( ExprAwait { node_index: NodeIndex(None), range: 422..429, value: Name( ExprName { node_index: NodeIndex(None), range: 428..429, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 430..446, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 430..446, left: Name( ExprName { node_index: NodeIndex(None), range: 430..431, id: Name("x"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Await( ExprAwait { node_index: NodeIndex(None), range: 439..446, value: Name( ExprName { node_index: NodeIndex(None), range: 445..446, id: Name("y"), ctx: Load, }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 489..541, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 489..541, left: Name( ExprName { node_index: NodeIndex(None), range: 489..490, id: Name("a"), ctx: Load, }, ), ops: [ Lt, Eq, Gt, Is, NotIn, IsNot, LtE, GtE, NotEq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 493..494, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 498..499, id: Name("c"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 502..503, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 507..508, id: Name("e"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 516..517, id: Name("f"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 525..526, id: Name("g"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 530..531, id: Name("h"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 535..536, id: Name("i"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 540..541, id: Name("j"), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__dictionary.py.snap000064400000000000000000002236271046102023000326730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/dictionary.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..622, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..11, value: Dict( ExprDict { node_index: NodeIndex(None), range: 9..11, items: [], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..18, value: Dict( ExprDict { node_index: NodeIndex(None), range: 12..18, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 2, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..43, value: Dict( ExprDict { node_index: NodeIndex(None), range: 19..43, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 2, ), }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("a"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 29..30, value: Int( 1, ), }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("b"), ctx: Load, }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 35..42, value: StringLiteralValue { inner: Single( StringLiteral { range: 35..42, node_index: NodeIndex(None), value: "hello", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 66..69, value: Dict( ExprDict { node_index: NodeIndex(None), range: 66..69, items: [], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 70..100, value: Dict( ExprDict { node_index: NodeIndex(None), range: 70..100, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 2, ), }, ), }, DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 90..91, value: Int( 3, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 97..98, value: Int( 4, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 111..132, value: Dict( ExprDict { node_index: NodeIndex(None), range: 111..132, items: [ DictItem { key: Some( Dict( ExprDict { node_index: NodeIndex(None), range: 112..118, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 113..114, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 116..117, value: Int( 2, ), }, ), }, ], }, ), ), value: Dict( ExprDict { node_index: NodeIndex(None), range: 120..131, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 121..122, value: Int( 3, ), }, ), ), value: Dict( ExprDict { node_index: NodeIndex(None), range: 124..130, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 125..126, value: Int( 4, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 5, ), }, ), }, ], }, ), }, ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 155..171, value: Dict( ExprDict { node_index: NodeIndex(None), range: 155..171, items: [ DictItem { key: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 156..167, parameters: Some( Parameters { range: 163..164, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 163..164, node_index: NodeIndex(None), parameter: Parameter { range: 163..164, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 163..164, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("x"), ctx: Load, }, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 169..170, value: Int( 1, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 172..202, value: Dict( ExprDict { node_index: NodeIndex(None), range: 172..202, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 173..176, value: StringLiteralValue { inner: Single( StringLiteral { range: 173..176, node_index: NodeIndex(None), value: "A", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 178..192, parameters: Some( Parameters { range: 185..186, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 185..186, node_index: NodeIndex(None), parameter: Parameter { range: 185..186, node_index: NodeIndex(None), name: Identifier { id: Name("p"), range: 185..186, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 188..192, }, ), }, ), }, DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 194..197, value: StringLiteralValue { inner: Single( StringLiteral { range: 194..197, node_index: NodeIndex(None), value: "B", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 199..200, id: Name("C"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 224..237, value: Dict( ExprDict { node_index: NodeIndex(None), range: 224..237, items: [ DictItem { key: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 226..232, target: Name( ExprName { node_index: NodeIndex(None), range: 226..227, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 231..232, value: Int( 1, ), }, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 235..236, id: Name("y"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 238..258, value: Dict( ExprDict { node_index: NodeIndex(None), range: 238..258, items: [ DictItem { key: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 240..246, target: Name( ExprName { node_index: NodeIndex(None), range: 240..241, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 245..246, value: Int( 1, ), }, ), }, ), ), value: Named( ExprNamed { node_index: NodeIndex(None), range: 250..256, target: Name( ExprName { node_index: NodeIndex(None), range: 250..251, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 255..256, value: Int( 2, ), }, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 284..289, value: Dict( ExprDict { node_index: NodeIndex(None), range: 284..289, items: [ DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("d"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 290..301, value: Dict( ExprDict { node_index: NodeIndex(None), range: 290..301, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 291..292, id: Name("a"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 294..295, id: Name("b"), ctx: Load, }, ), }, DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 299..300, id: Name("d"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 302..312, value: Dict( ExprDict { node_index: NodeIndex(None), range: 302..312, items: [ DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 305..306, id: Name("a"), ctx: Load, }, ), }, DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 310..311, id: Name("b"), ctx: Load, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 313..338, value: Dict( ExprDict { node_index: NodeIndex(None), range: 313..338, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 314..317, value: StringLiteralValue { inner: Single( StringLiteral { range: 314..317, node_index: NodeIndex(None), value: "a", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 319..322, value: StringLiteralValue { inner: Single( StringLiteral { range: 319..322, node_index: NodeIndex(None), value: "b", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 326..327, id: Name("c"), ctx: Load, }, ), }, DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 329..332, value: StringLiteralValue { inner: Single( StringLiteral { range: 329..332, node_index: NodeIndex(None), value: "d", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 334..337, value: StringLiteralValue { inner: Single( StringLiteral { range: 334..337, node_index: NodeIndex(None), value: "e", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 339..367, value: Dict( ExprDict { node_index: NodeIndex(None), range: 339..367, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 340..341, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 343..344, value: Int( 2, ), }, ), }, DictItem { key: None, value: Dict( ExprDict { node_index: NodeIndex(None), range: 348..366, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 349..357, value: StringLiteralValue { inner: Single( StringLiteral { range: 349..357, node_index: NodeIndex(None), value: "nested", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 359..365, value: StringLiteralValue { inner: Single( StringLiteral { range: 359..365, node_index: NodeIndex(None), value: "dict", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 368..393, value: Dict( ExprDict { node_index: NodeIndex(None), range: 368..393, items: [ DictItem { key: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 369..374, left: Name( ExprName { node_index: NodeIndex(None), range: 369..370, id: Name("x"), ctx: Load, }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 373..374, value: Int( 1, ), }, ), }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 376..382, left: Name( ExprName { node_index: NodeIndex(None), range: 376..377, id: Name("y"), ctx: Load, }, ), op: Pow, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 381..382, value: Int( 2, ), }, ), }, ), }, DictItem { key: None, value: Call( ExprCall { node_index: NodeIndex(None), range: 386..392, func: Name( ExprName { node_index: NodeIndex(None), range: 386..390, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 390..392, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 460..471, value: Dict( ExprDict { node_index: NodeIndex(None), range: 460..471, items: [ DictItem { key: None, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 464..469, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 468..469, id: Name("x"), ctx: Load, }, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 494..515, value: Dict( ExprDict { node_index: NodeIndex(None), range: 494..515, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 495..496, value: Int( 1, ), }, ), ), value: If( ExprIf { node_index: NodeIndex(None), range: 498..514, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 503..507, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 498..499, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 513..514, id: Name("y"), ctx: Load, }, ), }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 516..575, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 516..575, key: Some( If( ExprIf { node_index: NodeIndex(None), range: 517..533, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 522..526, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 517..518, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 532..533, id: Name("y"), ctx: Load, }, ), }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 535..536, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 537..555, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 541..542, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 546..555, func: Name( ExprName { node_index: NodeIndex(None), range: 546..551, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 551..555, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 552..554, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, Comprehension { range: 556..574, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 560..561, id: Name("y"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 565..574, func: Name( ExprName { node_index: NodeIndex(None), range: 565..570, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 570..574, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 571..573, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 576..600, value: Dict( ExprDict { node_index: NodeIndex(None), range: 576..600, items: [ DictItem { key: Some( Set( ExprSet { node_index: NodeIndex(None), range: 577..583, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 578..579, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 581..582, value: Int( 2, ), }, ), ], }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 585..586, value: Int( 3, ), }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 588..589, id: Name("x"), ctx: Load, }, ), ), value: Dict( ExprDict { node_index: NodeIndex(None), range: 591..598, items: [ DictItem { key: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 592..593, value: Int( 1, ), }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 595..596, value: Int( 2, ), }, ), }, ], }, ), }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 601..621, value: Dict( ExprDict { node_index: NodeIndex(None), range: 601..621, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 603..604, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 608..609, id: Name("y"), ctx: Load, }, ), }, DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 613..614, id: Name("z"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 618..619, id: Name("a"), ctx: Load, }, ), }, ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__dictionary_comprehension.py.snap000064400000000000000000001662441046102023000356250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/dictionary_comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..589, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 0..22, elt: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 3..21, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("y"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 12..21, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..42, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 23..42, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 24..26, id: Name("x1"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 28..30, id: Name("x2"), ctx: Load, }, ), generators: [ Comprehension { range: 31..41, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("y"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("z"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 43..73, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 43..73, key: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 44..49, left: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 48..49, value: Int( 1, ), }, ), }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 51..54, value: StringLiteralValue { inner: Single( StringLiteral { range: 51..54, node_index: NodeIndex(None), value: "x", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), generators: [ Comprehension { range: 55..72, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("i"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 64..72, func: Name( ExprName { node_index: NodeIndex(None), range: 64..69, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 69..72, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 70..71, value: Int( 5, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 74..122, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 74..122, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("b"), ctx: Load, }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 78..83, left: Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("c"), ctx: Load, }, ), op: Mult, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 2, ), }, ), }, ), generators: [ Comprehension { range: 84..121, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("c"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("d"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 98..104, left: Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 103..104, id: Name("w"), ctx: Load, }, ), ], }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 108..116, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 114..116, id: Name("yy"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 120..121, id: Name("z"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 123..176, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 123..176, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 124..125, id: Name("a"), ctx: Load, }, ), ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 127..133, left: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("a"), ctx: Load, }, ), op: Pow, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 132..133, value: Int( 2, ), }, ), }, ), generators: [ Comprehension { range: 134..155, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 138..139, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 148..155, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 148..149, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 154..155, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 156..175, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 170..175, left: Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 174..175, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 177..231, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 177..231, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("a"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 181..182, id: Name("b"), ctx: Load, }, ), generators: [ Comprehension { range: 183..204, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 187..188, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 192..193, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 197..204, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 203..204, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 205..230, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 215..216, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 220..221, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 225..230, left: Name( ExprName { node_index: NodeIndex(None), range: 225..226, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 229..230, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 232..252, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 232..252, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 233..234, id: Name("a"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 238..251, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 242..246, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 242..243, id: Name("b"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("c"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 250..251, id: Name("d"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 391..416, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 391..416, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 392..393, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 395..396, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 397..415, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 401..402, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 407..414, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 413..414, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 417..447, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 417..447, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 418..419, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 421..422, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 423..446, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 427..428, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 433..445, value: Name( ExprName { node_index: NodeIndex(None), range: 444..445, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 448..477, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 448..477, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 449..450, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 452..453, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 454..476, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 458..459, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 464..475, parameters: Some( Parameters { range: 471..472, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 471..472, node_index: NodeIndex(None), parameter: Parameter { range: 471..472, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 471..472, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 474..475, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 478..511, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 478..511, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 479..480, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 482..483, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 484..510, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 488..489, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 493..497, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 502..509, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 508..509, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 512..550, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 512..550, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 513..514, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 516..517, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 518..549, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 522..523, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 527..531, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 536..548, value: Name( ExprName { node_index: NodeIndex(None), range: 547..548, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 551..588, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 551..588, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 552..553, id: Name("x"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 555..556, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 557..587, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 561..562, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 566..570, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 575..586, parameters: Some( Parameters { range: 582..583, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 582..583, node_index: NodeIndex(None), parameter: Parameter { range: 582..583, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 582..583, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 585..586, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__f_string.py.snap000064400000000000000000005743601046102023000323440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..979, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 18..21, value: FString( ExprFString { node_index: NodeIndex(None), range: 18..21, value: FStringValue { inner: Single( FString( FString { range: 18..21, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..25, value: FString( ExprFString { node_index: NodeIndex(None), range: 22..25, value: FStringValue { inner: Single( FString( FString { range: 22..25, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: FString( ExprFString { node_index: NodeIndex(None), range: 26..29, value: FStringValue { inner: Single( FString( FString { range: 26..29, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..37, value: FString( ExprFString { node_index: NodeIndex(None), range: 30..37, value: FStringValue { inner: Single( FString( FString { range: 30..37, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 38..45, value: FString( ExprFString { node_index: NodeIndex(None), range: 38..45, value: FStringValue { inner: Single( FString( FString { range: 38..45, node_index: NodeIndex(None), elements: [], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 47..56, value: FString( ExprFString { node_index: NodeIndex(None), range: 47..56, value: FStringValue { inner: Single( FString( FString { range: 47..56, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 49..55, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 50..54, value: StringLiteralValue { inner: Single( StringLiteral { range: 50..54, node_index: NodeIndex(None), value: " f", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..67, value: FString( ExprFString { node_index: NodeIndex(None), range: 57..67, value: FStringValue { inner: Single( FString( FString { range: 57..67, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 59..66, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..75, value: FString( ExprFString { node_index: NodeIndex(None), range: 68..75, value: FStringValue { inner: Single( FString( FString { range: 68..75, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 70..74, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 71..73, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..86, value: FString( ExprFString { node_index: NodeIndex(None), range: 76..86, value: FStringValue { inner: Single( FString( FString { range: 76..86, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 78..85, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 79..83, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 3, ), }, ), ops: [ NotEq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 4, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 84..84, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 87..102, value: FString( ExprFString { node_index: NodeIndex(None), range: 87..102, value: FStringValue { inner: Single( FString( FString { range: 87..102, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 89..101, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 90..91, value: Int( 3, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 92..100, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 92..97, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 93..96, value: StringLiteralValue { inner: Single( StringLiteral { range: 93..96, node_index: NodeIndex(None), value: "}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 97..100, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 103..118, value: FString( ExprFString { node_index: NodeIndex(None), range: 103..118, value: FStringValue { inner: Single( FString( FString { range: 103..118, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 105..117, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 106..107, value: Int( 3, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 108..116, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 108..113, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 109..112, value: StringLiteralValue { inner: Single( StringLiteral { range: 109..112, node_index: NodeIndex(None), value: "{", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 113..116, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 119..133, value: FString( ExprFString { node_index: NodeIndex(None), range: 119..133, value: FStringValue { inner: Single( FString( FString { range: 119..133, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 121..132, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 124..127, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 134..154, value: FString( ExprFString { node_index: NodeIndex(None), range: 134..154, value: FStringValue { inner: Single( FString( FString { range: 134..154, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 136..153, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 139..142, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 147..152, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 147..152, node_index: NodeIndex(None), value: ".3f ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 155..173, value: FString( ExprFString { node_index: NodeIndex(None), range: 155..173, value: FStringValue { inner: Single( FString( FString { range: 155..173, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 157..172, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 160..163, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: Str, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 174..190, value: FString( ExprFString { node_index: NodeIndex(None), range: 174..190, value: FStringValue { inner: Single( FString( FString { range: 174..190, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 176..189, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 179..183, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 179..180, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 182..183, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: Some( DebugText { leading: " ", expression: "1, 2", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 191..217, value: FString( ExprFString { node_index: NodeIndex(None), range: 191..217, value: FStringValue { inner: Single( FString( FString { range: 191..217, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 193..216, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 194..210, value: FStringValue { inner: Single( FString( FString { range: 194..210, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 196..209, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..203, value: Float( 3.1415, ), }, ), debug_text: Some( DebugText { leading: "", expression: "3.1415", trailing: "=", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 205..208, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 205..208, node_index: NodeIndex(None), value: ".1f", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 211..215, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 211..215, node_index: NodeIndex(None), value: "*^20", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 219..253, value: Dict( ExprDict { node_index: NodeIndex(None), range: 219..253, items: [ DictItem { key: Some( FString( ExprFString { node_index: NodeIndex(None), range: 220..248, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 220..226, node_index: NodeIndex(None), value: "foo ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 227..242, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 229..233, node_index: NodeIndex(None), value: "bar ", }, ), Interpolation( InterpolatedElement { range: 233..240, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 234..239, left: Name( ExprName { node_index: NodeIndex(None), range: 234..235, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 238..239, id: Name("y"), ctx: Load, }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 240..241, node_index: NodeIndex(None), value: " ", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 243..248, node_index: NodeIndex(None), value: "baz", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 250..252, value: Int( 10, ), }, ), }, ], }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 254..345, subject: Name( ExprName { node_index: NodeIndex(None), range: 260..263, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 269..293, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 274..279, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 274..279, value: StringLiteralValue { inner: Single( StringLiteral { range: 274..279, node_index: NodeIndex(None), value: "one", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 289..293, }, ), ], }, MatchCase { range: 298..345, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 303..331, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 303..331, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 303..316, node_index: NodeIndex(None), value: "implicitly ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 317..331, node_index: NodeIndex(None), value: "concatenated", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "implicitly concatenated", }, ), }, }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 341..345, }, ), ], }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 347..364, value: FString( ExprFString { node_index: NodeIndex(None), range: 347..364, value: FStringValue { inner: Single( FString( FString { range: 347..364, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 349..350, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 350..355, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 351..354, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 355..356, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 356..363, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 357..360, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 361..362, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 361..362, node_index: NodeIndex(None), value: "\\", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 365..379, value: FString( ExprFString { node_index: NodeIndex(None), range: 365..379, value: FStringValue { inner: Single( FString( FString { range: 365..379, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 367..378, node_index: NodeIndex(None), value: "\\{foo\\}", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 380..420, value: FString( ExprFString { node_index: NodeIndex(None), range: 380..420, value: FStringValue { inner: Single( FString( FString { range: 380..420, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 384..417, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 390..393, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 394..416, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 394..416, node_index: NodeIndex(None), value: "x\n y\n z\n", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 421..439, value: FString( ExprFString { node_index: NodeIndex(None), range: 421..439, value: FStringValue { inner: Single( FString( FString { range: 421..439, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 423..438, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 428..431, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ( ", expression: "foo", trailing: " ) = ", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 441..486, value: FString( ExprFString { node_index: NodeIndex(None), range: 441..486, value: FStringValue { inner: Single( FString( FString { range: 441..486, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 443..450, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 450..455, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 451..454, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 455..468, node_index: NodeIndex(None), value: " {another} ", }, ), Interpolation( InterpolatedElement { range: 468..473, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 469..472, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 473..476, node_index: NodeIndex(None), value: " {", }, ), Interpolation( InterpolatedElement { range: 476..483, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 477..482, id: Name("three"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 483..485, node_index: NodeIndex(None), value: "}", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 487..529, value: FString( ExprFString { node_index: NodeIndex(None), range: 487..529, value: FStringValue { inner: Single( FString( FString { range: 487..529, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 489..496, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 496..503, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 497..500, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Ascii, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 503..504, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 504..511, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 505..508, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 511..512, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 512..519, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 513..516, id: Name("baz"), ctx: Load, }, ), debug_text: None, conversion: Repr, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 519..520, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 520..528, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 521..527, id: Name("foobar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 530..549, value: FString( ExprFString { node_index: NodeIndex(None), range: 530..549, value: FStringValue { inner: Single( FString( FString { range: 530..549, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 532..539, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 539..548, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 540..541, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 542..547, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 542..547, node_index: NodeIndex(None), value: "y + 2", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 550..568, value: FString( ExprFString { node_index: NodeIndex(None), range: 550..568, value: FStringValue { inner: Single( FString( FString { range: 550..568, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 552..567, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 553..554, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 555..566, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 555..566, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 556..565, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 556..563, value: Set( ExprSet { node_index: NodeIndex(None), range: 556..559, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 557..558, value: Int( 1, ), }, ), ], }, ), attr: Identifier { id: Name("pop"), range: 560..563, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 563..565, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 569..588, value: FString( ExprFString { node_index: NodeIndex(None), range: 569..588, value: FStringValue { inner: Single( FString( FString { range: 569..588, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 571..587, node_index: NodeIndex(None), expression: Lambda( ExprLambda { node_index: NodeIndex(None), range: 573..585, parameters: Some( Parameters { range: 580..581, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 580..581, node_index: NodeIndex(None), parameter: Parameter { range: 580..581, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 580..581, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Set( ExprSet { node_index: NodeIndex(None), range: 582..585, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 583..584, id: Name("x"), ctx: Load, }, ), ], }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 589..597, value: FString( ExprFString { node_index: NodeIndex(None), range: 589..597, value: FStringValue { inner: Single( FString( FString { range: 589..597, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 591..596, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 592..593, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " =", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 598..611, value: FString( ExprFString { node_index: NodeIndex(None), range: 598..611, value: FStringValue { inner: Single( FString( FString { range: 598..611, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 600..610, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 605..606, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "x", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 612..621, value: FString( ExprFString { node_index: NodeIndex(None), range: 612..621, value: FStringValue { inner: Single( FString( FString { range: 612..621, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 614..620, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 615..616, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: "=", }, ), conversion: Ascii, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 622..636, value: FString( ExprFString { node_index: NodeIndex(None), range: 622..636, value: FStringValue { inner: Single( FString( FString { range: 622..636, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 624..635, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 625..626, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 627..634, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 627..634, node_index: NodeIndex(None), value: ".3f!r =", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 637..653, value: FString( ExprFString { node_index: NodeIndex(None), range: 637..653, value: FStringValue { inner: Single( FString( FString { range: 637..653, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 639..652, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 640..641, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " = ", }, ), conversion: Repr, format_spec: Some( InterpolatedStringFormatSpec { range: 648..651, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 648..651, node_index: NodeIndex(None), value: ".3f", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 654..667, value: FString( ExprFString { node_index: NodeIndex(None), range: 654..667, value: FStringValue { inner: Single( FString( FString { range: 654..667, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 656..666, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 657..658, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 659..665, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 659..665, node_index: NodeIndex(None), value: ".3f=!r", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 668..682, value: FString( ExprFString { node_index: NodeIndex(None), range: 668..682, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 668..675, node_index: NodeIndex(None), value: "hello", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 676..682, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 678..681, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 679..680, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 683..696, value: FString( ExprFString { node_index: NodeIndex(None), range: 683..696, value: FStringValue { inner: Concatenated( [ FString( FString { range: 683..689, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 685..688, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 686..687, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 690..696, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 692..695, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 693..694, id: Name("y"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 697..711, value: FString( ExprFString { node_index: NodeIndex(None), range: 697..711, value: FStringValue { inner: Concatenated( [ FString( FString { range: 697..703, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 699..702, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 700..701, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 704..711, node_index: NodeIndex(None), value: "world", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 712..756, value: FString( ExprFString { node_index: NodeIndex(None), range: 712..756, value: FStringValue { inner: Single( FString( FString { range: 712..756, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 714..739, node_index: NodeIndex(None), value: "Invalid args in command: ", }, ), Interpolation( InterpolatedElement { range: 739..755, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 740..754, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 740..747, id: Name("command"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 749..754, value: Name( ExprName { node_index: NodeIndex(None), range: 750..754, id: Name("args"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 757..775, value: FString( ExprFString { node_index: NodeIndex(None), range: 757..775, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 757..762, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 763..769, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 765..768, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 766..767, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 770..775, node_index: NodeIndex(None), value: "bar", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 776..825, value: FString( ExprFString { node_index: NodeIndex(None), range: 782..823, value: FStringValue { inner: Concatenated( [ FString( FString { range: 782..786, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 784..785, node_index: NodeIndex(None), value: "a", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 791..795, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 793..794, node_index: NodeIndex(None), value: "b", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 800..803, node_index: NodeIndex(None), value: "c", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 808..813, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 811..812, node_index: NodeIndex(None), value: "d", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 818..823, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 821..822, node_index: NodeIndex(None), value: "e", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 850..879, value: FString( ExprFString { node_index: NodeIndex(None), range: 850..879, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 850..856, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 857..865, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 859..864, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 860..863, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 866..871, node_index: NodeIndex(None), value: "baz", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 872..879, node_index: NodeIndex(None), value: " some", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 880..909, value: FString( ExprFString { node_index: NodeIndex(None), range: 880..909, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 880..885, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 886..894, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 888..893, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 889..892, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 895..901, node_index: NodeIndex(None), value: "baz", flags: StringLiteralFlags { quote_style: Double, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 902..909, node_index: NodeIndex(None), value: " some", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 910..939, value: FString( ExprFString { node_index: NodeIndex(None), range: 910..939, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 910..915, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 916..924, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 918..923, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 919..922, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 925..930, node_index: NodeIndex(None), value: "baz", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 931..939, node_index: NodeIndex(None), value: " some", flags: StringLiteralFlags { quote_style: Double, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 940..978, value: FString( ExprFString { node_index: NodeIndex(None), range: 940..978, value: FStringValue { inner: Concatenated( [ Literal( StringLiteral { range: 940..946, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), FString( FString { range: 947..966, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 949..953, node_index: NodeIndex(None), value: "bar ", }, ), Interpolation( InterpolatedElement { range: 953..958, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 954..957, id: Name("baz"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 958..965, node_index: NodeIndex(None), value: " really", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 967..973, node_index: NodeIndex(None), value: "bar", flags: StringLiteralFlags { quote_style: Double, prefix: Unicode, triple_quoted: false, unclosed: false, }, }, ), Literal( StringLiteral { range: 974..978, node_index: NodeIndex(None), value: "no", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), ], ), }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__generator.py.snap000064400000000000000000001327711046102023000325130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/generator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..482, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..22, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 0..22, elt: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 3..21, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 7..13, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 17..21, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..51, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 23..51, elt: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 26..50, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 36..42, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 46..50, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: true, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 52..100, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 52..100, elt: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 55..99, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 59..65, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 69..73, id: Name("iter"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 77..83, left: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("y"), ctx: Load, }, ), ], }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 87..94, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("c"), ctx: Load, }, ), ], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 101..166, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 101..166, elt: Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 104..135, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 108..115, id: Name("target1"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 119..124, id: Name("iter1"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 128..135, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 134..135, id: Name("y"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 136..165, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 140..147, id: Name("target2"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 151..156, id: Name("iter2"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 160..165, left: Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("a"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 164..165, id: Name("b"), ctx: Load, }, ), ], }, ), ], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 167..238, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 167..238, elt: Name( ExprName { node_index: NodeIndex(None), range: 168..169, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 170..201, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 174..181, id: Name("target1"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 185..190, id: Name("iter1"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 194..201, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 194..195, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 200..201, id: Name("y"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 202..237, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 212..219, id: Name("target2"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 223..228, id: Name("iter2"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 232..237, left: Name( ExprName { node_index: NodeIndex(None), range: 232..233, id: Name("a"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("b"), ctx: Load, }, ), ], }, ), ], is_async: true, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 259..282, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 259..282, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 260..270, target: Name( ExprName { node_index: NodeIndex(None), range: 260..261, id: Name("x"), ctx: Store, }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 265..270, left: Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("y"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 269..270, value: Int( 1, ), }, ), }, ), }, ), generators: [ Comprehension { range: 271..281, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 275..276, id: Name("y"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 280..281, id: Name("z"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 300..326, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 300..326, elt: If( ExprIf { node_index: NodeIndex(None), range: 301..314, test: Name( ExprName { node_index: NodeIndex(None), range: 306..307, id: Name("y"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 301..302, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 313..314, id: Name("y"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 315..325, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 319..320, id: Name("y"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("z"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 340..481, value: Call( ExprCall { node_index: NodeIndex(None), range: 340..481, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 340..348, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 340..343, value: StringLiteralValue { inner: Single( StringLiteral { range: 340..343, node_index: NodeIndex(None), value: " ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("join"), range: 344..348, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 348..481, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 354..479, elt: Name( ExprName { node_index: NodeIndex(None), range: 354..357, id: Name("sql"), ctx: Load, }, ), generators: [ Comprehension { range: 362..479, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 366..369, id: Name("sql"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 373..479, elts: [ If( ExprIf { node_index: NodeIndex(None), range: 383..420, test: Name( ExprName { node_index: NodeIndex(None), range: 405..410, id: Name("limit"), ctx: Load, }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 383..401, left: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 383..393, value: StringLiteralValue { inner: Single( StringLiteral { range: 383..393, node_index: NodeIndex(None), value: "LIMIT %d", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), op: Mod, right: Name( ExprName { node_index: NodeIndex(None), range: 396..401, id: Name("limit"), ctx: Load, }, ), }, ), orelse: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 416..420, }, ), }, ), If( ExprIf { node_index: NodeIndex(None), range: 430..472, test: Name( ExprName { node_index: NodeIndex(None), range: 456..462, id: Name("offset"), ctx: Load, }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 431..451, left: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 431..442, value: StringLiteralValue { inner: Single( StringLiteral { range: 431..442, node_index: NodeIndex(None), value: "OFFSET %d", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), op: Mod, right: Name( ExprName { node_index: NodeIndex(None), range: 445..451, id: Name("offset"), ctx: Load, }, ), }, ), orelse: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 468..472, }, ), }, ), ], ctx: Load, parenthesized: true, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__if.py.snap000064400000000000000000000774211046102023000312020ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/if.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..423, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..16, value: If( ExprIf { node_index: NodeIndex(None), range: 0..16, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 5..9, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("a"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 15..16, id: Name("b"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 17..35, value: If( ExprIf { node_index: NodeIndex(None), range: 17..35, test: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), body: Call( ExprCall { node_index: NodeIndex(None), range: 17..20, func: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 18..20, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), orelse: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 31..35, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 36..61, value: If( ExprIf { node_index: NodeIndex(None), range: 36..61, test: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("b"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("a"), ctx: Load, }, ), orelse: If( ExprIf { node_index: NodeIndex(None), range: 48..61, test: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("d"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("c"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("e"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 62..84, value: If( ExprIf { node_index: NodeIndex(None), range: 62..84, test: Compare( ExprCompare { node_index: NodeIndex(None), range: 71..76, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 0, ), }, ), ], }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 62..67, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 1, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("x"), ctx: Load, }, ), }, ), orelse: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 82..84, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 85..108, value: If( ExprIf { node_index: NodeIndex(None), range: 85..108, test: Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("x"), ctx: Load, }, ), body: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 85..92, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 85..86, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("b"), ctx: Load, }, ), ], }, ), orelse: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 103..108, value: false, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 109..127, value: If( ExprIf { node_index: NodeIndex(None), range: 109..127, test: Name( ExprName { node_index: NodeIndex(None), range: 119..120, id: Name("y"), ctx: Load, }, ), body: Compare( ExprCompare { node_index: NodeIndex(None), range: 109..115, left: Name( ExprName { node_index: NodeIndex(None), range: 109..110, id: Name("x"), ctx: Load, }, ), ops: [ LtE, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("y"), ctx: Load, }, ), ], }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 128..154, value: If( ExprIf { node_index: NodeIndex(None), range: 128..154, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 136..143, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 142..143, id: Name("b"), ctx: Load, }, ), ], }, ), body: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 128..132, value: true, }, ), orelse: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 149..154, value: false, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 155..171, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 155..171, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 155..156, value: Int( 1, ), }, ), If( ExprIf { node_index: NodeIndex(None), range: 158..171, test: Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("a"), ctx: Load, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 158..159, value: Int( 1, ), }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("c"), ctx: Load, }, ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 214..240, value: If( ExprIf { node_index: NodeIndex(None), range: 214..240, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 219..223, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("x"), ctx: Load, }, ), orelse: Lambda( ExprLambda { node_index: NodeIndex(None), range: 229..240, parameters: Some( Parameters { range: 236..237, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 236..237, node_index: NodeIndex(None), parameter: Parameter { range: 236..237, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 236..237, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 239..240, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 302..323, value: If( ExprIf { node_index: NodeIndex(None), range: 302..323, test: Yield( ExprYield { node_index: NodeIndex(None), range: 308..315, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 314..315, id: Name("x"), ctx: Load, }, ), ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 302..303, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 322..323, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 324..350, value: If( ExprIf { node_index: NodeIndex(None), range: 324..350, test: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 330..342, value: Name( ExprName { node_index: NodeIndex(None), range: 341..342, id: Name("x"), ctx: Load, }, ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 349..350, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 351..376, value: If( ExprIf { node_index: NodeIndex(None), range: 351..376, test: Lambda( ExprLambda { node_index: NodeIndex(None), range: 357..368, parameters: Some( Parameters { range: 364..365, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 364..365, node_index: NodeIndex(None), parameter: Parameter { range: 364..365, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 364..365, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 367..368, id: Name("x"), ctx: Load, }, ), }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 351..352, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 375..376, id: Name("y"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 408..423, value: If( ExprIf { node_index: NodeIndex(None), range: 409..422, test: Name( ExprName { node_index: NodeIndex(None), range: 414..415, id: Name("y"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 409..410, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 421..422, id: Name("z"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__lambda.py.snap000064400000000000000000002735311046102023000317450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/lambda.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..530, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..9, parameters: None, body: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("a"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 10..19, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 10..19, parameters: None, body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..31, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 20..31, parameters: Some( Parameters { range: 27..28, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 27..28, node_index: NodeIndex(None), parameter: Parameter { range: 27..28, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 27..28, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..48, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 32..48, parameters: Some( Parameters { range: 39..43, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 39..40, node_index: NodeIndex(None), parameter: Parameter { range: 39..40, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 39..40, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 42..43, node_index: NodeIndex(None), parameter: Parameter { range: 42..43, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 42..43, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 45..48, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..66, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 49..66, parameters: Some( Parameters { range: 56..63, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 56..57, node_index: NodeIndex(None), parameter: Parameter { range: 56..57, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 56..57, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 59..60, node_index: NodeIndex(None), parameter: Parameter { range: 59..60, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 59..60, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 62..63, node_index: NodeIndex(None), parameter: Parameter { range: 62..63, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 62..63, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 67..90, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 67..90, parameters: Some( Parameters { range: 74..87, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 74..75, node_index: NodeIndex(None), parameter: Parameter { range: 74..75, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 74..75, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 77..81, node_index: NodeIndex(None), parameter: Parameter { range: 77..78, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 77..78, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..81, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 83..87, node_index: NodeIndex(None), parameter: Parameter { range: 83..84, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 83..84, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 85..87, value: Int( 30, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 91..109, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 91..109, parameters: Some( Parameters { range: 98..102, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 98..99, node_index: NodeIndex(None), parameter: Parameter { range: 98..99, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 98..99, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 101..102, node_index: NodeIndex(None), parameter: Parameter { range: 101..102, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 101..102, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 104..109, left: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("x"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 110..130, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 110..130, parameters: Some( Parameters { range: 117..123, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 117..118, node_index: NodeIndex(None), parameter: Parameter { range: 117..118, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 117..118, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 120..123, node_index: NodeIndex(None), parameter: Parameter { range: 120..121, node_index: NodeIndex(None), name: Identifier { id: Name("z"), range: 120..121, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 122..123, value: Int( 1, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 125..130, left: Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("z"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 131..143, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 131..143, parameters: Some( Parameters { range: 138..140, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 138..140, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 139..140, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 142..143, id: Name("a"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 144..166, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 144..166, parameters: Some( Parameters { range: 151..161, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 151..153, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 152..153, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 155..156, node_index: NodeIndex(None), parameter: Parameter { range: 155..156, node_index: NodeIndex(None), name: Identifier { id: Name("z"), range: 155..156, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 158..161, node_index: NodeIndex(None), parameter: Parameter { range: 158..159, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 158..159, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..161, value: Int( 0, ), }, ), ), }, ], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 163..166, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 167..187, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 167..187, parameters: Some( Parameters { range: 174..184, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 177..178, node_index: NodeIndex(None), parameter: Parameter { range: 177..178, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 177..178, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 180..181, node_index: NodeIndex(None), parameter: Parameter { range: 180..181, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 180..181, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 183..184, node_index: NodeIndex(None), parameter: Parameter { range: 183..184, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 183..184, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 186..187, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 188..214, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 188..214, parameters: Some( Parameters { range: 195..211, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 198..199, node_index: NodeIndex(None), parameter: Parameter { range: 198..199, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 198..199, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 201..205, node_index: NodeIndex(None), parameter: Parameter { range: 201..202, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 201..202, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 203..205, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 207..211, node_index: NodeIndex(None), parameter: Parameter { range: 207..208, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 207..208, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 209..211, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..214, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 215..241, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 215..241, parameters: Some( Parameters { range: 222..238, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 222..223, node_index: NodeIndex(None), parameter: Parameter { range: 222..223, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 222..223, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 225..226, node_index: NodeIndex(None), parameter: Parameter { range: 225..226, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 225..226, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 228..229, node_index: NodeIndex(None), parameter: Parameter { range: 228..229, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 228..229, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 234..235, node_index: NodeIndex(None), parameter: Parameter { range: 234..235, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 234..235, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 237..238, node_index: NodeIndex(None), parameter: Parameter { range: 237..238, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 237..238, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 240..241, value: Int( 0, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 242..262, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 242..262, parameters: Some( Parameters { range: 249..257, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 249..257, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 251..257, node_index: NodeIndex(None), }, annotation: None, }, ), }, ), body: Call( ExprCall { node_index: NodeIndex(None), range: 259..262, func: Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 260..262, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 263..294, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 263..294, parameters: Some( Parameters { range: 270..285, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 270..275, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 271..275, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 277..285, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 279..285, node_index: NodeIndex(None), }, annotation: None, }, ), }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 287..294, left: Call( ExprCall { node_index: NodeIndex(None), range: 287..290, func: Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 288..290, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 293..294, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 295..334, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 295..334, parameters: Some( Parameters { range: 302..325, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 302..307, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 303..307, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 309..310, node_index: NodeIndex(None), parameter: Parameter { range: 309..310, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 309..310, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 312..315, node_index: NodeIndex(None), parameter: Parameter { range: 312..313, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 312..313, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 314..315, value: Int( 1, ), }, ), ), }, ], kwarg: Some( Parameter { range: 317..325, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 319..325, node_index: NodeIndex(None), }, annotation: None, }, ), }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 327..334, left: Call( ExprCall { node_index: NodeIndex(None), range: 327..330, func: Name( ExprName { node_index: NodeIndex(None), range: 327..328, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 328..330, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 333..334, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 335..351, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 335..351, parameters: Some( Parameters { range: 342..346, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 342..343, node_index: NodeIndex(None), parameter: Parameter { range: 342..343, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 342..343, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 348..351, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 352..371, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 352..371, parameters: Some( Parameters { range: 359..366, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 359..360, node_index: NodeIndex(None), parameter: Parameter { range: 359..360, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 359..360, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 365..366, node_index: NodeIndex(None), parameter: Parameter { range: 365..366, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 365..366, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 368..371, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 372..391, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 372..391, parameters: Some( Parameters { range: 379..386, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 379..382, node_index: NodeIndex(None), parameter: Parameter { range: 379..380, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 379..380, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 381..382, value: Int( 1, ), }, ), ), }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 388..391, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 392..417, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 392..417, parameters: Some( Parameters { range: 399..412, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 399..400, node_index: NodeIndex(None), parameter: Parameter { range: 399..400, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 399..400, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 402..403, node_index: NodeIndex(None), parameter: Parameter { range: 402..403, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 402..403, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 411..412, node_index: NodeIndex(None), parameter: Parameter { range: 411..412, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 411..412, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 414..417, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 418..440, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 418..440, parameters: Some( Parameters { range: 425..435, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 425..429, node_index: NodeIndex(None), parameter: Parameter { range: 425..427, node_index: NodeIndex(None), name: Identifier { id: Name("kw"), range: 425..427, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 428..429, value: Int( 1, ), }, ), ), }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 434..435, node_index: NodeIndex(None), parameter: Parameter { range: 434..435, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 434..435, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 437..440, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 441..467, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 441..467, parameters: Some( Parameters { range: 448..464, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 448..449, node_index: NodeIndex(None), parameter: Parameter { range: 448..449, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 448..449, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 451..455, node_index: NodeIndex(None), parameter: Parameter { range: 451..452, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 451..452, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 453..455, value: Int( 20, ), }, ), ), }, ], args: [ ParameterWithDefault { range: 460..464, node_index: NodeIndex(None), parameter: Parameter { range: 460..461, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 460..461, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 462..464, value: Int( 30, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 466..467, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 468..497, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 468..497, parameters: Some( Parameters { range: 475..494, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 475..476, node_index: NodeIndex(None), parameter: Parameter { range: 475..476, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 475..476, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 478..479, node_index: NodeIndex(None), parameter: Parameter { range: 478..479, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 478..479, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 484..485, node_index: NodeIndex(None), parameter: Parameter { range: 484..485, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 484..485, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 490..491, node_index: NodeIndex(None), parameter: Parameter { range: 490..491, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 490..491, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 493..494, node_index: NodeIndex(None), parameter: Parameter { range: 493..494, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 493..494, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 496..497, value: Int( 0, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 498..530, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 498..530, parameters: Some( Parameters { range: 505..527, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 505..506, node_index: NodeIndex(None), parameter: Parameter { range: 505..506, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 505..506, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 508..509, node_index: NodeIndex(None), parameter: Parameter { range: 508..509, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 508..509, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 514..515, node_index: NodeIndex(None), parameter: Parameter { range: 514..515, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 514..515, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 517..519, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 518..519, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 521..522, node_index: NodeIndex(None), parameter: Parameter { range: 521..522, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 521..522, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: Some( Parameter { range: 524..527, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 526..527, node_index: NodeIndex(None), }, annotation: None, }, ), }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 529..530, value: Int( 0, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__list.py.snap000064400000000000000000001403731046102023000314750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/list.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..397, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 15..17, value: List( ExprList { node_index: NodeIndex(None), range: 15..17, elts: [], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..21, value: List( ExprList { node_index: NodeIndex(None), range: 18..21, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..26, value: List( ExprList { node_index: NodeIndex(None), range: 22..26, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..36, value: List( ExprList { node_index: NodeIndex(None), range: 27..36, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 31..32, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 34..35, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 37..47, value: List( ExprList { node_index: NodeIndex(None), range: 37..47, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..42, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..45, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 75..78, value: List( ExprList { node_index: NodeIndex(None), range: 75..78, elts: [], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 79..92, value: List( ExprList { node_index: NodeIndex(None), range: 79..92, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 1, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..114, value: List( ExprList { node_index: NodeIndex(None), range: 93..114, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 99..100, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 110..111, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 125..132, value: List( ExprList { node_index: NodeIndex(None), range: 125..132, elts: [ List( ExprList { node_index: NodeIndex(None), range: 126..131, elts: [ List( ExprList { node_index: NodeIndex(None), range: 127..130, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 1, ), }, ), ], ctx: Load, }, ), ], ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..149, value: List( ExprList { node_index: NodeIndex(None), range: 133..149, elts: [ List( ExprList { node_index: NodeIndex(None), range: 134..140, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 138..139, value: Int( 2, ), }, ), ], ctx: Load, }, ), List( ExprList { node_index: NodeIndex(None), range: 142..148, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..144, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 146..147, value: Int( 4, ), }, ), ], ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 170..178, value: List( ExprList { node_index: NodeIndex(None), range: 170..178, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 171..177, target: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 176..177, value: Int( 2, ), }, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 179..188, value: List( ExprList { node_index: NodeIndex(None), range: 179..188, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 180..186, target: Name( ExprName { node_index: NodeIndex(None), range: 180..181, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 185..186, value: Int( 2, ), }, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 189..203, value: List( ExprList { node_index: NodeIndex(None), range: 189..203, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 190..191, value: Int( 1, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 193..199, target: Name( ExprName { node_index: NodeIndex(None), range: 193..194, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 198..199, value: Int( 2, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 223..233, value: List( ExprList { node_index: NodeIndex(None), range: 223..233, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 224..225, value: Int( 1, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 227..229, value: Name( ExprName { node_index: NodeIndex(None), range: 228..229, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 231..232, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 234..248, value: List( ExprList { node_index: NodeIndex(None), range: 234..248, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 235..236, value: Int( 1, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 238..244, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 239..244, left: Name( ExprName { node_index: NodeIndex(None), range: 239..240, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 243..244, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 246..247, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 271..334, value: List( ExprList { node_index: NodeIndex(None), range: 271..334, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 272..277, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 272..273, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 276..277, value: Int( 2, ), }, ), }, ), List( ExprList { node_index: NodeIndex(None), range: 279..291, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 280..281, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 283..284, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 286..287, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 289..290, value: Int( 4, ), }, ), ], ctx: Load, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 293..306, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 294..295, id: Name("a"), ctx: Load, }, ), BinOp( ExprBinOp { node_index: NodeIndex(None), range: 297..302, left: Name( ExprName { node_index: NodeIndex(None), range: 297..298, id: Name("b"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 301..302, id: Name("c"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 304..305, id: Name("d"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), Set( ExprSet { node_index: NodeIndex(None), range: 308..317, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 309..310, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 312..313, id: Name("b"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 315..316, id: Name("c"), ctx: Load, }, ), ], }, ), Dict( ExprDict { node_index: NodeIndex(None), range: 319..325, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 320..321, id: Name("a"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 323..324, value: Int( 1, ), }, ), }, ], }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 327..333, target: Name( ExprName { node_index: NodeIndex(None), range: 327..328, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 332..333, value: Int( 2, ), }, ), }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 335..383, value: List( ExprList { node_index: NodeIndex(None), range: 335..383, elts: [ Call( ExprCall { node_index: NodeIndex(None), range: 336..382, func: Name( ExprName { node_index: NodeIndex(None), range: 336..341, id: Name("call1"), ctx: Load, }, ), arguments: Arguments { range: 341..382, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 342..381, elt: Call( ExprCall { node_index: NodeIndex(None), range: 342..361, func: Name( ExprName { node_index: NodeIndex(None), range: 342..347, id: Name("call2"), ctx: Load, }, ), arguments: Arguments { range: 347..361, node_index: NodeIndex(None), args: [ Call( ExprCall { node_index: NodeIndex(None), range: 348..360, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 348..358, value: Name( ExprName { node_index: NodeIndex(None), range: 348..353, id: Name("value"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 354..358, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 358..360, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ], keywords: [], }, }, ), generators: [ Comprehension { range: 362..381, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 366..373, id: Name("element"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 377..381, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 384..396, value: List( ExprList { node_index: NodeIndex(None), range: 384..396, elts: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 385..395, left: Name( ExprName { node_index: NodeIndex(None), range: 385..389, id: Name("item"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 393..395, id: Name("xs"), ctx: Load, }, ), ], }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__list_comprehension.py.snap000064400000000000000000002301631046102023000344230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/list_comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..776, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..26, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 4..26, elt: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("y"), ctx: Load, }, ), generators: [ Comprehension { range: 7..25, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("y"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 16..25, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..18, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..49, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 28..49, elt: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 31..48, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("i"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 40..48, func: Name( ExprName { node_index: NodeIndex(None), range: 40..45, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 45..48, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 46..47, value: Int( 5, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 50..91, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 50..91, elt: Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("b"), ctx: Load, }, ), generators: [ Comprehension { range: 53..90, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("c"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("d"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 67..73, left: Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("w"), ctx: Load, }, ), ], }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 77..85, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 83..85, id: Name("yy"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("z"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..137, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 92..137, elt: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 95..116, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 109..116, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 109..110, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 115..116, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 117..136, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 121..122, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 131..136, left: Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 138..189, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 138..189, elt: Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 141..162, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 145..146, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 155..162, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 163..188, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 173..174, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 183..188, left: Name( ExprName { node_index: NodeIndex(None), range: 183..184, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 187..188, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 190..209, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 190..209, elt: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 191..192, value: Int( 1, ), }, ), generators: [ Comprehension { range: 193..208, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("i"), ctx: Store, }, ), iter: Compare( ExprCompare { node_index: NodeIndex(None), range: 202..208, left: Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 207..208, id: Name("a"), ctx: Load, }, ), ], }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 210..227, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 210..227, elt: Name( ExprName { node_index: NodeIndex(None), range: 211..212, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 213..226, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 217..221, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 217..218, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 220..221, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 225..226, id: Name("G"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 228..257, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 228..257, elt: Await( ExprAwait { node_index: NodeIndex(None), range: 234..241, value: Name( ExprName { node_index: NodeIndex(None), range: 240..241, id: Name("x"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 242..255, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 246..250, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 246..247, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 249..250, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 254..255, id: Name("C"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 258..300, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 258..300, elt: Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("i"), ctx: Load, }, ), generators: [ Comprehension { range: 261..299, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("i"), ctx: Store, }, ), iter: Await( ExprAwait { node_index: NodeIndex(None), range: 270..277, value: Name( ExprName { node_index: NodeIndex(None), range: 276..277, id: Name("x"), ctx: Load, }, ), }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 281..299, left: Name( ExprName { node_index: NodeIndex(None), range: 281..287, id: Name("entity"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 295..299, }, ), ], }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 301..337, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 301..337, elt: Name( ExprName { node_index: NodeIndex(None), range: 302..303, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 304..336, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 308..309, id: Name("x"), ctx: Store, }, ), iter: If( ExprIf { node_index: NodeIndex(None), range: 314..330, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 319..323, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 314..315, id: Name("l"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 329..330, id: Name("L"), ctx: Load, }, ), }, ), ifs: [ Name( ExprName { node_index: NodeIndex(None), range: 335..336, id: Name("T"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 338..380, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 338..380, elt: Name( ExprName { node_index: NodeIndex(None), range: 339..340, id: Name("i"), ctx: Load, }, ), generators: [ Comprehension { range: 341..379, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 345..346, id: Name("i"), ctx: Store, }, ), iter: If( ExprIf { node_index: NodeIndex(None), range: 351..373, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 362..366, value: true, }, ), body: Await( ExprAwait { node_index: NodeIndex(None), range: 351..358, value: Name( ExprName { node_index: NodeIndex(None), range: 357..358, id: Name("x"), ctx: Load, }, ), }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 372..373, id: Name("X"), ctx: Load, }, ), }, ), ifs: [ Name( ExprName { node_index: NodeIndex(None), range: 378..379, id: Name("F"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 381..423, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 381..423, elt: Name( ExprName { node_index: NodeIndex(None), range: 382..383, id: Name("i"), ctx: Load, }, ), generators: [ Comprehension { range: 384..422, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 388..389, id: Name("i"), ctx: Store, }, ), iter: Await( ExprAwait { node_index: NodeIndex(None), range: 393..417, value: If( ExprIf { node_index: NodeIndex(None), range: 400..416, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 405..409, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 400..401, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 415..416, id: Name("X"), ctx: Load, }, ), }, ), }, ), ifs: [ Name( ExprName { node_index: NodeIndex(None), range: 421..422, id: Name("F"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 424..457, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 424..457, elt: Name( ExprName { node_index: NodeIndex(None), range: 425..426, id: Name("f"), ctx: Load, }, ), generators: [ Comprehension { range: 427..456, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 431..432, id: Name("f"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 436..456, func: Name( ExprName { node_index: NodeIndex(None), range: 436..437, id: Name("c"), ctx: Load, }, ), arguments: Arguments { range: 437..456, node_index: NodeIndex(None), args: [ If( ExprIf { node_index: NodeIndex(None), range: 438..455, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 443..447, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 438..439, id: Name("x"), ctx: Load, }, ), orelse: List( ExprList { node_index: NodeIndex(None), range: 453..455, elts: [], ctx: Load, }, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 596..618, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 596..618, elt: Name( ExprName { node_index: NodeIndex(None), range: 597..598, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 599..617, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 603..604, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 609..616, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 615..616, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 619..646, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 619..646, elt: Name( ExprName { node_index: NodeIndex(None), range: 620..621, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 622..645, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 626..627, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 632..644, value: Name( ExprName { node_index: NodeIndex(None), range: 643..644, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 647..673, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 647..673, elt: Name( ExprName { node_index: NodeIndex(None), range: 648..649, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 650..672, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 654..655, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 660..671, parameters: Some( Parameters { range: 667..668, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 667..668, node_index: NodeIndex(None), parameter: Parameter { range: 667..668, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 667..668, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 670..671, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 674..704, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 674..704, elt: Name( ExprName { node_index: NodeIndex(None), range: 675..676, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 677..703, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 681..682, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 686..690, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 695..702, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 701..702, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 705..740, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 705..740, elt: Name( ExprName { node_index: NodeIndex(None), range: 706..707, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 708..739, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 712..713, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 717..721, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 726..738, value: Name( ExprName { node_index: NodeIndex(None), range: 737..738, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 741..775, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 741..775, elt: Name( ExprName { node_index: NodeIndex(None), range: 742..743, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 744..774, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 748..749, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 753..757, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 762..773, parameters: Some( Parameters { range: 769..770, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 769..770, node_index: NodeIndex(None), parameter: Parameter { range: 769..770, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 769..770, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 772..773, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__name.py.snap000064400000000000000000000105361046102023000314370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/name.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..76, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..1, value: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("_"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 2..5, value: Name( ExprName { node_index: NodeIndex(None), range: 3..4, id: Name("_"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 6..8, value: Name( ExprName { node_index: NodeIndex(None), range: 6..8, id: Name("__"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..17, value: Name( ExprName { node_index: NodeIndex(None), range: 9..17, id: Name("__init__"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..22, value: Name( ExprName { node_index: NodeIndex(None), range: 18..22, id: Name("name"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 23..29, value: Name( ExprName { node_index: NodeIndex(None), range: 24..28, id: Name("name"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..65, value: Name( ExprName { node_index: NodeIndex(None), range: 60..65, id: Name("match"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 66..70, value: Name( ExprName { node_index: NodeIndex(None), range: 66..70, id: Name("case"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 71..75, value: Name( ExprName { node_index: NodeIndex(None), range: 71..75, id: Name("type"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__named.py.snap000064400000000000000000000401071046102023000316000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/named.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..157, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: Named( ExprNamed { node_index: NodeIndex(None), range: 1..10, target: Name( ExprName { node_index: NodeIndex(None), range: 1..5, id: Name("name"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 0, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..29, value: Named( ExprNamed { node_index: NodeIndex(None), range: 13..28, target: Name( ExprName { node_index: NodeIndex(None), range: 13..17, id: Name("name"), ctx: Store, }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 22..27, left: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..45, value: Named( ExprNamed { node_index: NodeIndex(None), range: 31..44, target: Name( ExprName { node_index: NodeIndex(None), range: 31..35, id: Name("name"), ctx: Store, }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 39..44, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 39..40, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 46..63, value: Named( ExprNamed { node_index: NodeIndex(None), range: 47..62, target: Name( ExprName { node_index: NodeIndex(None), range: 47..51, id: Name("name"), ctx: Store, }, ), value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 55..62, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 56..58, value: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 64..90, value: Named( ExprNamed { node_index: NodeIndex(None), range: 65..89, target: Name( ExprName { node_index: NodeIndex(None), range: 65..69, id: Name("name"), ctx: Store, }, ), value: If( ExprIf { node_index: NodeIndex(None), range: 73..89, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 78..82, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 88..89, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 91..112, value: Named( ExprNamed { node_index: NodeIndex(None), range: 92..111, target: Name( ExprName { node_index: NodeIndex(None), range: 92..96, id: Name("name"), ctx: Store, }, ), value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 100..111, parameters: Some( Parameters { range: 107..108, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 107..108, node_index: NodeIndex(None), parameter: Parameter { range: 107..108, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 107..108, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 110..111, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 113..132, value: Named( ExprNamed { node_index: NodeIndex(None), range: 114..131, target: Name( ExprName { node_index: NodeIndex(None), range: 114..118, id: Name("name"), ctx: Store, }, ), value: Yield( ExprYield { node_index: NodeIndex(None), range: 123..130, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..157, value: Named( ExprNamed { node_index: NodeIndex(None), range: 134..156, target: Name( ExprName { node_index: NodeIndex(None), range: 134..138, id: Name("name"), ctx: Store, }, ), value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 143..155, value: Name( ExprName { node_index: NodeIndex(None), range: 154..155, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__number_literal.py.snap000064400000000000000000001341231046102023000335220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/number_literal.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..700, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4..13, value: Int( 123456789, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 14..24, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..24, value: Int( 123456, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 25..31, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 29..31, value: Float( 0.1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 32..38, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..38, value: Float( 1.0, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 39..47, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..47, value: Float( 10.0, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 48..56, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..56, value: Float( 0.1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 57..73, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..73, value: Float( 1.00000001, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 74..97, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..97, value: Float( 123456789.12345679, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 98..131, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 102..131, value: Float( inf, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 132..155, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 136..155, value: Float( inf, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 156..170, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..170, value: Complex { real: 0.0, imag: 123456789.0, }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 171..195, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 175..195, value: Complex { real: 0.0, imag: 123456789.12345679, }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 196..207, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 200..207, value: Int( 727756, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 208..218, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 208..209, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 212..218, value: Int( 11, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 219..228, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 219..220, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 223..228, value: Int( 511, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 229..244, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 229..230, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 233..244, value: Float( 6e-9, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 245..254, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 249..254, value: Int( 10000, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 255..265, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 255..256, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 259..265, value: Int( 133333, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 286..298, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 286..287, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 290..298, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 290..292, value: Float( 1.0, ), }, ), attr: Identifier { id: Name("imag"), range: 294..298, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 299..312, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 299..300, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 303..312, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 303..307, value: Float( 10.0, ), }, ), attr: Identifier { id: Name("imag"), range: 308..312, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 313..326, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 313..314, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 317..326, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 317..321, value: Float( 0.1, ), }, ), attr: Identifier { id: Name("real"), range: 322..326, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 327..356, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 327..328, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 331..356, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 331..354, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 331..350, value: Float( 123456789.12345679, ), }, ), attr: Identifier { id: Name("hex"), range: 351..354, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 354..356, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 357..396, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 357..358, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 361..396, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 361..390, value: Float( inf, ), }, ), attr: Identifier { id: Name("real"), range: 392..396, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 397..433, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 397..398, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 401..433, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 401..431, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 401..420, value: Float( inf, ), }, ), attr: Identifier { id: Name("conjugate"), range: 422..431, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 431..433, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 434..453, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 434..435, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 438..453, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 438..448, value: Complex { real: 0.0, imag: 123456789.0, }, }, ), attr: Identifier { id: Name("real"), range: 449..453, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 454..507, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 454..455, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 458..507, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 458..486, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 458..478, value: Complex { real: 0.0, imag: 123456789.12345679, }, }, ), attr: Identifier { id: Name("__add__"), range: 479..486, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 486..507, node_index: NodeIndex(None), args: [ Call( ExprCall { node_index: NodeIndex(None), range: 487..506, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 487..504, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 487..493, value: Int( 11, ), }, ), attr: Identifier { id: Name("bit_length"), range: 494..504, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 504..506, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 508..531, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 508..509, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 512..531, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 512..529, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 512..519, value: Int( 727756, ), }, ), attr: Identifier { id: Name("conjugate"), range: 520..529, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 529..531, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 532..555, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 532..533, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 536..555, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 536..553, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 536..542, value: Int( 11, ), }, ), attr: Identifier { id: Name("conjugate"), range: 544..553, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 553..555, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 556..571, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 556..557, id: Name("x"), ctx: Store, }, ), ], value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 560..571, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 560..565, value: Int( 511, ), }, ), attr: Identifier { id: Name("real"), range: 567..571, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 572..595, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 572..573, id: Name("x"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 576..595, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 576..593, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 576..587, value: Float( 6e-9, ), }, ), attr: Identifier { id: Name("hex"), range: 590..593, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 593..595, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 596..610, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 596..597, id: Name("x"), ctx: Store, }, ), ], value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 600..610, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 601..610, value: Complex { real: 0.0, imag: 100.0, }, }, ), }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 612..632, test: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 615..623, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 615..617, value: Int( 10, ), }, ), attr: Identifier { id: Name("real"), range: 619..623, node_index: NodeIndex(None), }, ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 629..632, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 629..632, }, ), }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 677..688, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 677..678, id: Name("y"), ctx: Store, }, ), ], value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 681..688, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 681..684, value: Int( 100, ), }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 685..687, id: Name("no"), ctx: Load, }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 689..700, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 689..690, id: Name("y"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 693..700, func: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 693..696, value: Int( 100, ), }, ), arguments: Arguments { range: 696..700, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 697..699, id: Name("no"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__parenthesized.py.snap000064400000000000000000000263431046102023000333670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/parenthesized.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..6, value: Name( ExprName { node_index: NodeIndex(None), range: 1..5, id: Name("expr"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 7..15, value: Call( ExprCall { node_index: NodeIndex(None), range: 7..15, func: Name( ExprName { node_index: NodeIndex(None), range: 8..12, id: Name("expr"), ctx: Load, }, ), arguments: Arguments { range: 13..15, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..28, value: Call( ExprCall { node_index: NodeIndex(None), range: 16..28, func: Call( ExprCall { node_index: NodeIndex(None), range: 16..26, func: Call( ExprCall { node_index: NodeIndex(None), range: 16..24, func: Name( ExprName { node_index: NodeIndex(None), range: 17..21, id: Name("expr"), ctx: Load, }, ), arguments: Arguments { range: 22..24, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), arguments: Arguments { range: 24..26, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), arguments: Arguments { range: 26..28, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..44, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 31..43, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 31..38, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 31..32, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("b"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 42..43, id: Name("c"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 45..58, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 46..57, parameters: Some( Parameters { range: 53..54, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 53..54, node_index: NodeIndex(None), parameter: Parameter { range: 53..54, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 53..54, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 59..67, value: Named( ExprNamed { node_index: NodeIndex(None), range: 60..66, target: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..77, value: Yield( ExprYield { node_index: NodeIndex(None), range: 69..76, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 78..92, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 79..91, value: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("x"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__set.py.snap000064400000000000000000001002301046102023000313600ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/set.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..313, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 14..16, value: Dict( ExprDict { node_index: NodeIndex(None), range: 14..16, items: [], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 17..20, value: Set( ExprSet { node_index: NodeIndex(None), range: 17..20, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 1, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..25, value: Set( ExprSet { node_index: NodeIndex(None), range: 21..25, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 22..23, value: Int( 1, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..35, value: Set( ExprSet { node_index: NodeIndex(None), range: 26..35, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..34, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 36..46, value: Set( ExprSet { node_index: NodeIndex(None), range: 36..46, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 37..38, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 40..41, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 74..77, value: Dict( ExprDict { node_index: NodeIndex(None), range: 74..77, items: [], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 78..91, value: Set( ExprSet { node_index: NodeIndex(None), range: 78..91, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 1, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..113, value: Set( ExprSet { node_index: NodeIndex(None), range: 92..113, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 98..99, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 109..110, value: Int( 2, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 124..129, value: Set( ExprSet { node_index: NodeIndex(None), range: 124..129, elts: [ Set( ExprSet { node_index: NodeIndex(None), range: 125..128, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 126..127, value: Int( 1, ), }, ), ], }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 130..146, value: Set( ExprSet { node_index: NodeIndex(None), range: 130..146, elts: [ Set( ExprSet { node_index: NodeIndex(None), range: 131..137, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 132..133, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 2, ), }, ), ], }, ), Set( ExprSet { node_index: NodeIndex(None), range: 139..145, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 140..141, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..144, value: Int( 4, ), }, ), ], }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 167..175, value: Set( ExprSet { node_index: NodeIndex(None), range: 167..175, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 168..174, target: Name( ExprName { node_index: NodeIndex(None), range: 168..169, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 173..174, value: Int( 2, ), }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 176..190, value: Set( ExprSet { node_index: NodeIndex(None), range: 176..190, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 177..178, value: Int( 1, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 180..186, target: Name( ExprName { node_index: NodeIndex(None), range: 180..181, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 185..186, value: Int( 2, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 188..189, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 191..205, value: Set( ExprSet { node_index: NodeIndex(None), range: 191..205, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 192..193, value: Int( 1, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 196..202, target: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 201..202, value: Int( 2, ), }, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 225..235, value: Set( ExprSet { node_index: NodeIndex(None), range: 225..235, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 226..227, value: Int( 1, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 229..231, value: Name( ExprName { node_index: NodeIndex(None), range: 230..231, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 233..234, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 236..250, value: Set( ExprSet { node_index: NodeIndex(None), range: 236..250, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 237..238, value: Int( 1, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 240..246, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 241..246, left: Name( ExprName { node_index: NodeIndex(None), range: 241..242, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 248..249, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 273..312, value: Set( ExprSet { node_index: NodeIndex(None), range: 273..312, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 274..279, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 274..275, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 278..279, value: Int( 2, ), }, ), }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 281..287, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 282..283, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 285..286, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), Set( ExprSet { node_index: NodeIndex(None), range: 289..298, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 290..291, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 293..294, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 296..297, value: Int( 3, ), }, ), ], }, ), Dict( ExprDict { node_index: NodeIndex(None), range: 300..311, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 301..302, id: Name("a"), ctx: Load, }, ), ), value: Name( ExprName { node_index: NodeIndex(None), range: 304..305, id: Name("b"), ctx: Load, }, ), }, DictItem { key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 309..310, id: Name("d"), ctx: Load, }, ), }, ], }, ), ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__set_comprehension.py.snap000064400000000000000000001262741046102023000342520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/set_comprehension.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..492, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..15, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 0..15, elt: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 3..14, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("i"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 12..14, id: Name("ll"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 16..57, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 16..57, elt: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("b"), ctx: Load, }, ), generators: [ Comprehension { range: 19..56, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("c"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("d"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 33..39, left: Name( ExprName { node_index: NodeIndex(None), range: 33..34, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("w"), ctx: Load, }, ), ], }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 43..51, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 49..51, id: Name("yy"), ctx: Load, }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("z"), ctx: Load, }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..103, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 58..103, elt: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 61..82, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 75..82, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 83..102, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 87..88, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 97..102, left: Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 104..155, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 104..155, elt: Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 107..128, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 111..112, id: Name("b"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 116..117, id: Name("c"), ctx: Load, }, ), ifs: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 121..128, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 121..122, id: Name("d"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("e"), ctx: Load, }, ), ], }, ), ], is_async: false, }, Comprehension { range: 129..154, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("f"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 144..145, id: Name("j"), ctx: Load, }, ), ifs: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 149..154, left: Name( ExprName { node_index: NodeIndex(None), range: 149..150, id: Name("k"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 153..154, id: Name("h"), ctx: Load, }, ), ], }, ), ], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 156..173, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 156..173, elt: Name( ExprName { node_index: NodeIndex(None), range: 157..158, id: Name("a"), ctx: Load, }, ), generators: [ Comprehension { range: 159..172, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 163..167, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 171..172, id: Name("G"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 312..334, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 312..334, elt: Name( ExprName { node_index: NodeIndex(None), range: 313..314, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 315..333, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 319..320, id: Name("x"), ctx: Store, }, ), iter: Yield( ExprYield { node_index: NodeIndex(None), range: 325..332, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 331..332, id: Name("y"), ctx: Load, }, ), ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 335..362, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 335..362, elt: Name( ExprName { node_index: NodeIndex(None), range: 336..337, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 338..361, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 342..343, id: Name("x"), ctx: Store, }, ), iter: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 348..360, value: Name( ExprName { node_index: NodeIndex(None), range: 359..360, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 363..389, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 363..389, elt: Name( ExprName { node_index: NodeIndex(None), range: 364..365, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 366..388, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 370..371, id: Name("x"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 376..387, parameters: Some( Parameters { range: 383..384, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 383..384, node_index: NodeIndex(None), parameter: Parameter { range: 383..384, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 383..384, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 386..387, id: Name("y"), ctx: Load, }, ), }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 390..420, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 390..420, elt: Name( ExprName { node_index: NodeIndex(None), range: 391..392, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 393..419, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 397..398, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 402..406, id: Name("data"), ctx: Load, }, ), ifs: [ Yield( ExprYield { node_index: NodeIndex(None), range: 411..418, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 417..418, id: Name("y"), ctx: Load, }, ), ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 421..456, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 421..456, elt: Name( ExprName { node_index: NodeIndex(None), range: 422..423, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 424..455, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 428..429, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 433..437, id: Name("data"), ctx: Load, }, ), ifs: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 442..454, value: Name( ExprName { node_index: NodeIndex(None), range: 453..454, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 457..491, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 457..491, elt: Name( ExprName { node_index: NodeIndex(None), range: 458..459, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 460..490, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 464..465, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 469..473, id: Name("data"), ctx: Load, }, ), ifs: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 478..489, parameters: Some( Parameters { range: 485..486, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 485..486, node_index: NodeIndex(None), parameter: Parameter { range: 485..486, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 485..486, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 488..489, id: Name("y"), ctx: Load, }, ), }, ), ], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@expressions__slice.py.snap000064400000000000000000001023561046102023000316200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/slice.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..211, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..27, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 23..27, value: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 25..26, lower: None, upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 28..33, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 28..33, value: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 30..32, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 30..31, value: Int( 1, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 34..39, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 34..39, value: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 36..38, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 37..38, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 40..46, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 40..46, value: Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 42..45, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 42..43, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..45, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 47..52, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 47..52, value: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 49..51, lower: None, upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..59, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 53..59, value: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 55..58, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 1, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..66, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 60..66, value: Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 62..65, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 67..74, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 67..74, value: Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 69..73, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 69..70, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 75..81, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 75..81, value: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 77..80, lower: None, upper: None, step: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 3, ), }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 82..89, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 82..89, value: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 84..88, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 84..85, value: Int( 1, ), }, ), ), upper: None, step: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 87..88, value: Int( 3, ), }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 90..97, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 90..97, value: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 92..96, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 93..94, value: Int( 2, ), }, ), ), step: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 95..96, value: Int( 3, ), }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 98..106, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 98..106, value: Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 100..105, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..101, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 102..103, value: Int( 2, ), }, ), ), step: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..105, value: Int( 3, ), }, ), ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 127..136, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 127..136, value: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("x"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 129..135, target: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 134..135, value: Int( 2, ), }, ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 137..149, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 137..149, value: Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 139..148, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 140..146, target: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 145..146, value: Int( 2, ), }, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 150..160, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 150..160, value: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("x"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 152..159, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 152..158, target: Name( ExprName { node_index: NodeIndex(None), range: 152..153, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 157..158, value: Int( 2, ), }, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 202..210, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 202..210, value: Name( ExprName { node_index: NodeIndex(None), range: 202..203, id: Name("x"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 204..209, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 204..205, value: Int( 1, ), }, ), Slice( ExprSlice { node_index: NodeIndex(None), range: 206..208, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 207..208, value: Int( 2, ), }, ), ), step: None, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__starred.py.snap000064400000000000000000000464521046102023000321710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/starred.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..172, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..2, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 0..2, value: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 3..11, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 3..11, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5..10, left: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("a"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..19, value: Starred( ExprStarred { node_index: NodeIndex(None), range: 12..19, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 13..19, value: Name( ExprName { node_index: NodeIndex(None), range: 13..14, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 15..19, node_index: NodeIndex(None), }, ctx: Load, }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 21..57, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 21..32, id: Name("array_slice"), ctx: Store, }, ), ], value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 35..57, value: Name( ExprName { node_index: NodeIndex(None), range: 35..40, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 41..56, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..42, value: Int( 0, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 44..52, value: Name( ExprName { node_index: NodeIndex(None), range: 45..52, id: Name("indexes"), ctx: Load, }, ), ctx: Load, }, ), UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 54..56, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 1, ), }, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 58..94, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 58..80, value: Name( ExprName { node_index: NodeIndex(None), range: 58..63, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 64..79, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..65, value: Int( 0, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 67..75, value: Name( ExprName { node_index: NodeIndex(None), range: 68..75, id: Name("indexes"), ctx: Load, }, ), ctx: Load, }, ), UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 77..79, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 1, ), }, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 83..94, id: Name("array_slice"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..140, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 95..140, value: Name( ExprName { node_index: NodeIndex(None), range: 95..100, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 101..139, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 101..119, value: Name( ExprName { node_index: NodeIndex(None), range: 102..119, id: Name("indexes_to_select"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 121..139, value: Name( ExprName { node_index: NodeIndex(None), range: 122..139, id: Name("indexes_to_select"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 141..171, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 141..171, value: Name( ExprName { node_index: NodeIndex(None), range: 141..146, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 147..170, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 147..150, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 147..148, value: Int( 3, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 5, ), }, ), ), step: None, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 152..170, value: Name( ExprName { node_index: NodeIndex(None), range: 153..170, id: Name("indexes_to_select"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__string.py.snap000064400000000000000000000417121046102023000320250ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/string.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..163, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..13, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 0..13, value: StringLiteralValue { inner: Single( StringLiteral { range: 0..13, node_index: NodeIndex(None), value: "Hello World", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 14..20, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 14..20, value: StringLiteralValue { inner: Single( StringLiteral { range: 14..20, node_index: NodeIndex(None), value: "😎", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 21..32, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 21..32, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 21..26, node_index: NodeIndex(None), value: "Foo", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 27..32, node_index: NodeIndex(None), value: "Bar", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "FooBar", }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 33..60, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 39..58, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 39..42, node_index: NodeIndex(None), value: "A", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 47..50, node_index: NodeIndex(None), value: "B", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 55..58, node_index: NodeIndex(None), value: "C", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "ABC", }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 61..79, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 61..79, value: StringLiteralValue { inner: Single( StringLiteral { range: 61..79, node_index: NodeIndex(None), value: "Olá, Mundo!", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 80..91, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 80..91, value: StringLiteralValue { inner: Single( StringLiteral { range: 80..91, node_index: NodeIndex(None), value: "ABCDE", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..121, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 98..119, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 98..106, node_index: NodeIndex(None), value: "aB", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: true, unclosed: false, }, }, StringLiteral { range: 111..119, node_index: NodeIndex(None), value: "cD", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: true, unclosed: false, }, }, ], value: "aBcD", }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 122..136, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 122..136, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 122..136, node_index: NodeIndex(None), value: [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 137..161, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 137..161, value: BytesLiteralValue { inner: Concatenated( [ BytesLiteral { range: 137..145, node_index: NodeIndex(None), value: [ 98, 121, 116, 101, 115, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, BytesLiteral { range: 146..161, node_index: NodeIndex(None), value: [ 99, 111, 110, 99, 97, 116, 101, 110, 97, 116, 101, 100, ], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__subscript.py.snap000064400000000000000000001277141046102023000325440ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/subscript.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..266, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..10, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..10, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..7, value: Name( ExprName { node_index: NodeIndex(None), range: 0..4, id: Name("data"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 0, ), }, ), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 0, ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 11..21, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 11..21, value: Name( ExprName { node_index: NodeIndex(None), range: 11..15, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 16..20, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..31, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 22..31, value: Name( ExprName { node_index: NodeIndex(None), range: 22..26, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 27..30, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 27..29, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 0, ), }, ), ), upper: None, step: None, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..43, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 32..43, value: Name( ExprName { node_index: NodeIndex(None), range: 32..36, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 37..42, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 37..39, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 37..38, value: Int( 0, ), }, ), ), upper: None, step: None, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..42, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 44..56, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 44..56, value: Name( ExprName { node_index: NodeIndex(None), range: 44..48, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 49..55, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 49..52, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 0, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), ), step: None, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..80, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 57..80, value: Name( ExprName { node_index: NodeIndex(None), range: 57..61, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 62..79, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 62..67, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 0, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..65, value: Int( 1, ), }, ), ), step: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 66..67, value: Int( 2, ), }, ), ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 69..70, value: Int( 3, ), }, ), Slice( ExprSlice { node_index: NodeIndex(None), range: 72..79, lower: Some( Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("a"), ctx: Load, }, ), ), upper: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 74..79, left: Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("b"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 1, ), }, ), }, ), ), step: None, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 81..93, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 81..93, value: Name( ExprName { node_index: NodeIndex(None), range: 81..85, id: Name("data"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 86..92, target: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("a"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 94..106, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 94..106, value: Name( ExprName { node_index: NodeIndex(None), range: 94..98, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 99..105, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 99..100, lower: None, upper: None, step: None, }, ), Slice( ExprSlice { node_index: NodeIndex(None), range: 102..105, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 103..105, value: Int( 11, ), }, ), ), step: None, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 107..120, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 107..120, value: Name( ExprName { node_index: NodeIndex(None), range: 107..111, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 112..119, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 112..113, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..132, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 121..132, value: Name( ExprName { node_index: NodeIndex(None), range: 121..125, id: Name("data"), ctx: Load, }, ), slice: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 126..131, op: Invert, operand: Name( ExprName { node_index: NodeIndex(None), range: 127..131, id: Name("flag"), ctx: Load, }, ), }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 133..148, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 133..148, value: Name( ExprName { node_index: NodeIndex(None), range: 133..137, id: Name("data"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 138..147, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 139..145, target: Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 144..145, value: Int( 0, ), }, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 149..165, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 149..165, value: Name( ExprName { node_index: NodeIndex(None), range: 149..153, id: Name("data"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 154..164, lower: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 155..161, target: Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..161, value: Int( 0, ), }, ), }, ), ), upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("y"), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 226..234, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 226..234, value: Name( ExprName { node_index: NodeIndex(None), range: 226..230, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 231..233, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 231..233, value: Name( ExprName { node_index: NodeIndex(None), range: 232..233, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 235..249, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 235..249, value: Name( ExprName { node_index: NodeIndex(None), range: 235..239, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 240..248, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 240..248, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 241..248, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 241..242, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 247..248, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 250..265, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 250..265, value: Name( ExprName { node_index: NodeIndex(None), range: 250..254, id: Name("data"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 255..264, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 255..264, value: Named( ExprNamed { node_index: NodeIndex(None), range: 257..263, target: Name( ExprName { node_index: NodeIndex(None), range: 257..258, id: Name("x"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 262..263, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@expressions__t_string.py.snap000064400000000000000000005240471046102023000323570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..864, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 18..21, value: TString( ExprTString { node_index: NodeIndex(None), range: 18..21, value: TStringValue { inner: Single( TString { range: 18..21, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..25, value: TString( ExprTString { node_index: NodeIndex(None), range: 22..25, value: TStringValue { inner: Single( TString { range: 22..25, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: TString( ExprTString { node_index: NodeIndex(None), range: 26..29, value: TStringValue { inner: Single( TString { range: 26..29, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..37, value: TString( ExprTString { node_index: NodeIndex(None), range: 30..37, value: TStringValue { inner: Single( TString { range: 30..37, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 38..45, value: TString( ExprTString { node_index: NodeIndex(None), range: 38..45, value: TStringValue { inner: Single( TString { range: 38..45, node_index: NodeIndex(None), elements: [], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 47..56, value: TString( ExprTString { node_index: NodeIndex(None), range: 47..56, value: TStringValue { inner: Single( TString { range: 47..56, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 49..55, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 50..54, value: StringLiteralValue { inner: Single( StringLiteral { range: 50..54, node_index: NodeIndex(None), value: " t", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..67, value: TString( ExprTString { node_index: NodeIndex(None), range: 57..67, value: TStringValue { inner: Single( TString { range: 57..67, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 59..66, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..75, value: TString( ExprTString { node_index: NodeIndex(None), range: 68..75, value: TStringValue { inner: Single( TString { range: 68..75, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 70..74, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 71..73, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 71..72, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..86, value: TString( ExprTString { node_index: NodeIndex(None), range: 76..86, value: TStringValue { inner: Single( TString { range: 76..86, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 78..85, node_index: NodeIndex(None), expression: Compare( ExprCompare { node_index: NodeIndex(None), range: 79..83, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 3, ), }, ), ops: [ NotEq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 4, ), }, ), ], }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 84..84, node_index: NodeIndex(None), elements: [], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 87..102, value: TString( ExprTString { node_index: NodeIndex(None), range: 87..102, value: TStringValue { inner: Single( TString { range: 87..102, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 89..101, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 90..91, value: Int( 3, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 92..100, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 92..97, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 93..96, value: StringLiteralValue { inner: Single( StringLiteral { range: 93..96, node_index: NodeIndex(None), value: "}", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 97..100, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 103..118, value: TString( ExprTString { node_index: NodeIndex(None), range: 103..118, value: TStringValue { inner: Single( TString { range: 103..118, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 105..117, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 106..107, value: Int( 3, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 108..116, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 108..113, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 109..112, value: StringLiteralValue { inner: Single( StringLiteral { range: 109..112, node_index: NodeIndex(None), value: "{", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 113..116, node_index: NodeIndex(None), value: ">10", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 119..133, value: TString( ExprTString { node_index: NodeIndex(None), range: 119..133, value: TStringValue { inner: Single( TString { range: 119..133, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 121..132, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 124..127, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 134..154, value: TString( ExprTString { node_index: NodeIndex(None), range: 134..154, value: TStringValue { inner: Single( TString { range: 134..154, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 136..153, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 139..142, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 147..152, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 147..152, node_index: NodeIndex(None), value: ".3f ", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 155..173, value: TString( ExprTString { node_index: NodeIndex(None), range: 155..173, value: TStringValue { inner: Single( TString { range: 155..173, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 157..172, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 160..163, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "foo", trailing: " = ", }, ), conversion: Str, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 174..190, value: TString( ExprTString { node_index: NodeIndex(None), range: 174..190, value: TStringValue { inner: Single( TString { range: 174..190, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 176..189, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 179..183, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 179..180, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 182..183, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: Some( DebugText { leading: " ", expression: "1, 2", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 191..217, value: TString( ExprTString { node_index: NodeIndex(None), range: 191..217, value: TStringValue { inner: Single( TString { range: 191..217, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 193..216, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 194..210, value: TStringValue { inner: Single( TString { range: 194..210, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 196..209, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 197..203, value: Float( 3.1415, ), }, ), debug_text: Some( DebugText { leading: "", expression: "3.1415", trailing: "=", }, ), conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 205..208, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 205..208, node_index: NodeIndex(None), value: ".1f", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 211..215, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 211..215, node_index: NodeIndex(None), value: "*^20", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 219..255, value: Dict( ExprDict { node_index: NodeIndex(None), range: 219..255, items: [ DictItem { key: Some( TString( ExprTString { node_index: NodeIndex(None), range: 220..250, value: TStringValue { inner: Concatenated( [ TString { range: 220..227, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 222..226, node_index: NodeIndex(None), value: "foo ", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 228..243, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 230..234, node_index: NodeIndex(None), value: "bar ", }, ), Interpolation( InterpolatedElement { range: 234..241, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 235..240, left: Name( ExprName { node_index: NodeIndex(None), range: 235..236, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 239..240, id: Name("y"), ctx: Load, }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 241..242, node_index: NodeIndex(None), value: " ", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 244..250, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 246..249, node_index: NodeIndex(None), value: "baz", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 252..254, value: Int( 10, ), }, ), }, ], }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 256..347, subject: Name( ExprName { node_index: NodeIndex(None), range: 262..265, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 271..295, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 276..281, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 276..281, value: StringLiteralValue { inner: Single( StringLiteral { range: 276..281, node_index: NodeIndex(None), value: "one", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 291..295, }, ), ], }, MatchCase { range: 300..347, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 305..333, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 305..333, value: StringLiteralValue { inner: Concatenated( ConcatenatedStringLiteral { strings: [ StringLiteral { range: 305..318, node_index: NodeIndex(None), value: "implicitly ", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, StringLiteral { range: 319..333, node_index: NodeIndex(None), value: "concatenated", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ], value: "implicitly concatenated", }, ), }, }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 343..347, }, ), ], }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 349..366, value: TString( ExprTString { node_index: NodeIndex(None), range: 349..366, value: TStringValue { inner: Single( TString { range: 349..366, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 351..352, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 352..357, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 353..356, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 357..358, node_index: NodeIndex(None), value: "\\", }, ), Interpolation( InterpolatedElement { range: 358..365, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 359..362, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 363..364, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 363..364, node_index: NodeIndex(None), value: "\\", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 367..381, value: TString( ExprTString { node_index: NodeIndex(None), range: 367..381, value: TStringValue { inner: Single( TString { range: 367..381, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 369..380, node_index: NodeIndex(None), value: "\\{foo\\}", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 382..422, value: TString( ExprTString { node_index: NodeIndex(None), range: 382..422, value: TStringValue { inner: Single( TString { range: 382..422, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 386..419, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 392..395, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 396..418, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 396..418, node_index: NodeIndex(None), value: "x\n y\n z\n", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 423..441, value: TString( ExprTString { node_index: NodeIndex(None), range: 423..441, value: TStringValue { inner: Single( TString { range: 423..441, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 425..440, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 430..433, id: Name("foo"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ( ", expression: "foo", trailing: " ) = ", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 443..488, value: TString( ExprTString { node_index: NodeIndex(None), range: 443..488, value: TStringValue { inner: Single( TString { range: 443..488, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 445..452, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 452..457, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 453..456, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 457..470, node_index: NodeIndex(None), value: " {another} ", }, ), Interpolation( InterpolatedElement { range: 470..475, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 471..474, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 475..478, node_index: NodeIndex(None), value: " {", }, ), Interpolation( InterpolatedElement { range: 478..485, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 479..484, id: Name("three"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 485..487, node_index: NodeIndex(None), value: "}", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 489..531, value: TString( ExprTString { node_index: NodeIndex(None), range: 489..531, value: TStringValue { inner: Single( TString { range: 489..531, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 491..498, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 498..505, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 499..502, id: Name("foo"), ctx: Load, }, ), debug_text: None, conversion: Ascii, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 505..506, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 506..513, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 507..510, id: Name("bar"), ctx: Load, }, ), debug_text: None, conversion: Str, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 513..514, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 514..521, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 515..518, id: Name("baz"), ctx: Load, }, ), debug_text: None, conversion: Repr, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 521..522, node_index: NodeIndex(None), value: " ", }, ), Interpolation( InterpolatedElement { range: 522..530, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 523..529, id: Name("foobar"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 532..551, value: TString( ExprTString { node_index: NodeIndex(None), range: 532..551, value: TStringValue { inner: Single( TString { range: 532..551, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 534..541, node_index: NodeIndex(None), value: "normal ", }, ), Interpolation( InterpolatedElement { range: 541..550, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 542..543, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 544..549, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 544..549, node_index: NodeIndex(None), value: "y + 2", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 552..570, value: TString( ExprTString { node_index: NodeIndex(None), range: 552..570, value: TStringValue { inner: Single( TString { range: 552..570, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 554..569, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 555..556, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 557..568, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 557..568, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 558..567, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 558..565, value: Set( ExprSet { node_index: NodeIndex(None), range: 558..561, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 559..560, value: Int( 1, ), }, ), ], }, ), attr: Identifier { id: Name("pop"), range: 562..565, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 565..567, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 571..590, value: TString( ExprTString { node_index: NodeIndex(None), range: 571..590, value: TStringValue { inner: Single( TString { range: 571..590, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 573..589, node_index: NodeIndex(None), expression: Lambda( ExprLambda { node_index: NodeIndex(None), range: 575..587, parameters: Some( Parameters { range: 582..583, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 582..583, node_index: NodeIndex(None), parameter: Parameter { range: 582..583, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 582..583, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Set( ExprSet { node_index: NodeIndex(None), range: 584..587, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 585..586, id: Name("x"), ctx: Load, }, ), ], }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 591..599, value: TString( ExprTString { node_index: NodeIndex(None), range: 591..599, value: TStringValue { inner: Single( TString { range: 591..599, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 593..598, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 594..595, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " =", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 600..613, value: TString( ExprTString { node_index: NodeIndex(None), range: 600..613, value: TStringValue { inner: Single( TString { range: 600..613, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 602..612, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 607..608, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: " ", expression: "x", trailing: " = ", }, ), conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 614..623, value: TString( ExprTString { node_index: NodeIndex(None), range: 614..623, value: TStringValue { inner: Single( TString { range: 614..623, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 616..622, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 617..618, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: "=", }, ), conversion: Ascii, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 624..638, value: TString( ExprTString { node_index: NodeIndex(None), range: 624..638, value: TStringValue { inner: Single( TString { range: 624..638, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 626..637, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 627..628, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 629..636, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 629..636, node_index: NodeIndex(None), value: ".3f!r =", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 639..655, value: TString( ExprTString { node_index: NodeIndex(None), range: 639..655, value: TStringValue { inner: Single( TString { range: 639..655, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 641..654, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 642..643, id: Name("x"), ctx: Load, }, ), debug_text: Some( DebugText { leading: "", expression: "x", trailing: " = ", }, ), conversion: Repr, format_spec: Some( InterpolatedStringFormatSpec { range: 650..653, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 650..653, node_index: NodeIndex(None), value: ".3f", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 656..669, value: TString( ExprTString { node_index: NodeIndex(None), range: 656..669, value: TStringValue { inner: Single( TString { range: 656..669, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 658..668, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 659..660, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 661..667, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 661..667, node_index: NodeIndex(None), value: ".3f=!r", }, ), ], }, ), }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 670..685, value: TString( ExprTString { node_index: NodeIndex(None), range: 670..685, value: TStringValue { inner: Concatenated( [ TString { range: 670..678, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 672..677, node_index: NodeIndex(None), value: "hello", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 679..685, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 681..684, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 682..683, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 686..699, value: TString( ExprTString { node_index: NodeIndex(None), range: 686..699, value: TStringValue { inner: Concatenated( [ TString { range: 686..692, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 688..691, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 689..690, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 693..699, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 695..698, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 696..697, id: Name("y"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 700..715, value: TString( ExprTString { node_index: NodeIndex(None), range: 700..715, value: TStringValue { inner: Concatenated( [ TString { range: 700..706, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 702..705, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 703..704, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 707..715, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 709..714, node_index: NodeIndex(None), value: "world", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 716..760, value: TString( ExprTString { node_index: NodeIndex(None), range: 716..760, value: TStringValue { inner: Single( TString { range: 716..760, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 718..743, node_index: NodeIndex(None), value: "Invalid args in command: ", }, ), Interpolation( InterpolatedElement { range: 743..759, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 744..758, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 744..751, id: Name("command"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 753..758, value: Name( ExprName { node_index: NodeIndex(None), range: 754..758, id: Name("args"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 761..781, value: TString( ExprTString { node_index: NodeIndex(None), range: 761..781, value: TStringValue { inner: Concatenated( [ TString { range: 761..767, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 763..766, node_index: NodeIndex(None), value: "foo", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 768..774, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 770..773, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 771..772, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 775..781, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 777..780, node_index: NodeIndex(None), value: "bar", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 782..832, value: TString( ExprTString { node_index: NodeIndex(None), range: 788..830, value: TStringValue { inner: Concatenated( [ TString { range: 788..792, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 790..791, node_index: NodeIndex(None), value: "a", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 797..801, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 799..800, node_index: NodeIndex(None), value: "b", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 806..810, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 808..809, node_index: NodeIndex(None), value: "c", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, TString { range: 815..820, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 818..819, node_index: NodeIndex(None), value: "d", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, TString { range: 825..830, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 828..829, node_index: NodeIndex(None), value: "e", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Raw { uppercase_r: false, }, triple_quoted: false, unclosed: false, }, }, ], ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 844..863, value: TString( ExprTString { node_index: NodeIndex(None), range: 844..863, value: TStringValue { inner: Single( TString { range: 844..863, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 846..862, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 847..861, value: FStringValue { inner: Single( FString( FString { range: 847..861, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 849..860, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 850..859, value: TStringValue { inner: Single( TString { range: 850..859, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 852..858, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 853..857, id: Name("this"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` valid_syntax@expressions__tuple.py.snap000064400000000000000000001066751046102023000316620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/tuple.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..276, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..21, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 19..21, elts: [], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 22..26, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 23..25, elts: [], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 27..37, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 27..37, elts: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 29..31, elts: [], ctx: Load, parenthesized: true, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 34..36, elts: [], ctx: Load, parenthesized: true, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 38..42, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 38..42, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 43..49, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 43..49, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 50..57, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..57, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..66, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 59..65, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 60..61, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 90..92, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 90..92, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..97, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 93..97, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 96..97, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 98..103, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 98..103, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 126..129, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 126..129, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 126..128, value: Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 130..135, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 130..135, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 130..131, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 133..135, value: Name( ExprName { node_index: NodeIndex(None), range: 134..135, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 136..161, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 136..161, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 136..142, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 137..142, left: Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 141..142, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 144..152, value: Await( ExprAwait { node_index: NodeIndex(None), range: 145..152, value: Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 154..156, elts: [], ctx: Load, parenthesized: true, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 158..161, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 159..161, elts: [], ctx: Load, parenthesized: true, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 162..167, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 162..167, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 163..165, value: Name( ExprName { node_index: NodeIndex(None), range: 164..165, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 168..175, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 168..175, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 172..174, value: Name( ExprName { node_index: NodeIndex(None), range: 173..174, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 176..203, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 176..203, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 177..183, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 178..183, left: Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 182..183, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 185..193, value: Await( ExprAwait { node_index: NodeIndex(None), range: 186..193, value: Name( ExprName { node_index: NodeIndex(None), range: 192..193, id: Name("x"), ctx: Load, }, ), }, ), ctx: Load, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 195..197, elts: [], ctx: Load, parenthesized: true, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 199..202, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 200..202, elts: [], ctx: Load, parenthesized: true, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 224..233, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 224..233, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 225..231, target: Name( ExprName { node_index: NodeIndex(None), range: 225..226, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 230..231, value: Int( 1, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 234..245, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 234..245, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 235..236, id: Name("x"), ctx: Load, }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 238..244, target: Name( ExprName { node_index: NodeIndex(None), range: 238..239, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 243..244, value: Int( 2, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 246..260, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 246..260, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 247..248, id: Name("x"), ctx: Load, }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 250..256, target: Name( ExprName { node_index: NodeIndex(None), range: 250..251, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 255..256, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 258..259, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 261..275, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 261..275, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 261..262, id: Name("x"), ctx: Load, }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 265..271, target: Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 270..271, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 274..275, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@expressions__unary_op.py.snap000064400000000000000000000651651046102023000323630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/unary_op.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..276, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..11, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 9..11, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..14, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 12..14, op: UAdd, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 13..14, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..17, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 15..17, op: Invert, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 1, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 18..23, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 18..23, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 36..40, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 36..40, op: USub, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 37..40, op: USub, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 38..40, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 39..40, value: Int( 1, ), }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 41..45, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 41..45, op: USub, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 42..45, op: UAdd, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 43..45, op: Invert, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..45, value: Int( 1, ), }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 46..53, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 46..53, op: Not, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 49..53, op: USub, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 50..53, op: UAdd, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 51..53, op: Invert, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 1, ), }, ), }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 54..63, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 54..63, op: Not, operand: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 58..63, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 84..93, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 84..93, op: USub, operand: Await( ExprAwait { node_index: NodeIndex(None), range: 86..93, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 92..93, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 94..109, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 94..109, op: UAdd, operand: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 96..109, left: Await( ExprAwait { node_index: NodeIndex(None), range: 96..103, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 102..103, value: Int( 1, ), }, ), }, ), op: Pow, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 107..109, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 108..109, value: Int( 2, ), }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 110..117, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 110..117, op: Invert, operand: Tuple( ExprTuple { node_index: NodeIndex(None), range: 111..117, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 112..113, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 118..124, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 118..124, left: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 118..120, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 119..120, value: Int( 1, ), }, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 123..124, value: Int( 2, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 212..246, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 212..246, op: Or, values: [ BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 212..223, op: And, values: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 212..217, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 216..217, id: Name("a"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 222..223, id: Name("b"), ctx: Load, }, ), ], }, ), BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 227..246, op: And, values: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 227..236, op: Not, operand: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 231..236, left: Name( ExprName { node_index: NodeIndex(None), range: 231..232, id: Name("c"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 235..236, id: Name("d"), ctx: Load, }, ), }, ), }, ), UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 241..246, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("e"), ctx: Load, }, ), }, ), ], }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 247..259, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 247..259, op: Not, operand: Named( ExprNamed { node_index: NodeIndex(None), range: 252..258, target: Name( ExprName { node_index: NodeIndex(None), range: 252..253, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 257..258, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 260..275, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 260..275, op: Not, operand: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 264..275, left: Name( ExprName { node_index: NodeIndex(None), range: 264..265, id: Name("a"), ctx: Load, }, ), op: BitOr, right: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 269..274, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 273..274, id: Name("b"), ctx: Load, }, ), }, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__yield.py.snap000064400000000000000000000601341046102023000316240ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/yield.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..166, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: Yield( ExprYield { node_index: NodeIndex(None), range: 0..5, value: None, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 6..13, value: Yield( ExprYield { node_index: NodeIndex(None), range: 6..13, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 14..25, value: Yield( ExprYield { node_index: NodeIndex(None), range: 14..25, value: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 20..25, left: Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("x"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 24..25, value: Int( 1, ), }, ), }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 26..39, value: Yield( ExprYield { node_index: NodeIndex(None), range: 26..39, value: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 32..39, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("y"), ctx: Load, }, ), ], }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 40..52, value: Yield( ExprYield { node_index: NodeIndex(None), range: 40..52, value: Some( Call( ExprCall { node_index: NodeIndex(None), range: 46..52, func: Name( ExprName { node_index: NodeIndex(None), range: 46..50, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 50..52, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..65, value: Yield( ExprYield { node_index: NodeIndex(None), range: 53..65, value: Some( List( ExprList { node_index: NodeIndex(None), range: 59..65, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 60..61, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 63..64, value: Int( 2, ), }, ), ], ctx: Load, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 66..78, value: Yield( ExprYield { node_index: NodeIndex(None), range: 66..78, value: Some( Set( ExprSet { node_index: NodeIndex(None), range: 72..78, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 73..74, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 4, ), }, ), ], }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 79..91, value: Yield( ExprYield { node_index: NodeIndex(None), range: 79..91, value: Some( Dict( ExprDict { node_index: NodeIndex(None), range: 85..91, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("x"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 89..90, value: Int( 5, ), }, ), }, ], }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..102, value: Yield( ExprYield { node_index: NodeIndex(None), range: 92..102, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 98..102, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 103..115, value: Yield( ExprYield { node_index: NodeIndex(None), range: 103..115, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 109..115, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 110..111, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 116..128, value: Yield( ExprYield { node_index: NodeIndex(None), range: 116..128, value: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 122..128, left: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 127..128, id: Name("y"), ctx: Load, }, ), ], }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 129..143, value: Yield( ExprYield { node_index: NodeIndex(None), range: 129..143, value: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 136..142, target: Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 141..142, value: Int( 1, ), }, ), }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 144..155, value: Yield( ExprYield { node_index: NodeIndex(None), range: 144..155, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 150..155, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 153..155, value: Name( ExprName { node_index: NodeIndex(None), range: 154..155, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 156..165, value: Yield( ExprYield { node_index: NodeIndex(None), range: 156..165, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 162..165, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 162..164, value: Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ) ``` valid_syntax@expressions__yield_from.py.snap000064400000000000000000000465611046102023000326570ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/expressions/yield_from.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..199, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 0..12, value: Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 13..29, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 13..29, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 24..29, left: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 30..48, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 30..48, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 41..48, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..66, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 49..66, value: Call( ExprCall { node_index: NodeIndex(None), range: 60..66, func: Name( ExprName { node_index: NodeIndex(None), range: 60..64, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 64..66, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 67..84, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 67..84, value: List( ExprList { node_index: NodeIndex(None), range: 78..84, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 85..102, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 85..102, value: Set( ExprSet { node_index: NodeIndex(None), range: 96..102, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 97..98, value: Int( 3, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..101, value: Int( 4, ), }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 103..120, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 103..120, value: Dict( ExprDict { node_index: NodeIndex(None), range: 114..120, items: [ DictItem { key: Some( Name( ExprName { node_index: NodeIndex(None), range: 115..116, id: Name("x"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 118..119, value: Int( 5, ), }, ), }, ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 121..138, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 121..138, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 132..138, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 133..134, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 136..137, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 139..156, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 139..156, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 150..156, left: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("x"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 155..156, id: Name("y"), ctx: Load, }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 157..176, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 157..176, value: Named( ExprNamed { node_index: NodeIndex(None), range: 169..175, target: Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 174..175, value: Int( 1, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 177..199, value: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 177..199, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 188..199, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("x"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 192..198, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 193..198, left: Name( ExprName { node_index: NodeIndex(None), range: 193..194, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), }, ), ], }, ) ``` valid_syntax@for_in_target_valid_expr.py.snap000064400000000000000000000225671046102023000327640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/for_in_target_valid_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..89, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..28, is_async: false, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 4..13, value: Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("d"), ctx: Load, }, ), slice: Compare( ExprCompare { node_index: NodeIndex(None), range: 6..12, left: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("y"), ctx: Load, }, ), ], }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 17..23, id: Name("target"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 29..57, is_async: false, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 33..44, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 34..40, left: Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Load, }, ), ], }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 42..43, value: Int( 0, ), }, ), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 48..52, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 54..57, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 54..57, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 58..88, is_async: false, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 62..75, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 63..69, left: Name( ExprName { node_index: NodeIndex(None), range: 63..64, id: Name("x"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("y"), ctx: Load, }, ), ], }, ), attr: Identifier { id: Name("attr"), range: 71..75, node_index: NodeIndex(None), }, ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 79..83, id: Name("iter"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 85..88, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 85..88, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` valid_syntax@for_iter_unpack_py38.py.snap000064400000000000000000000211151046102023000317460ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ For( StmtFor { node_index: NodeIndex(None), range: 43..65, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 52..60, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 53..55, value: Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 62..65, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 62..65, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 66..88, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 75..83, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 80..82, value: Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 85..88, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 85..88, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 89..111, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 98..106, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 99..101, value: Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 103..105, value: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 108..111, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 108..111, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` valid_syntax@for_iter_unpack_py39.py.snap000064400000000000000000000211131046102023000317450ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..106, body: [ For( StmtFor { node_index: NodeIndex(None), range: 43..63, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 52..58, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 52..54, value: Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 60..63, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 60..63, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 64..84, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 74..79, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 77..79, value: Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 85..105, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("x"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 94..100, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 98..100, value: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 102..105, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 102..105, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` valid_syntax@from_import_no_space.py.snap000064400000000000000000000034061046102023000321200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/from_import_no_space.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..30, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..13, module: None, names: [ Alias { range: 12..13, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 12..13, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 14..29, module: None, names: [ Alias { range: 28..29, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 28..29, node_index: NodeIndex(None), }, asname: None, }, ], level: 3, is_lazy: false, }, ), ], }, ) ``` valid_syntax@from_import_soft_keyword_module_name.py.snap000064400000000000000000000122621046102023000354150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/from_import_soft_keyword_module_name.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..125, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..25, module: Some( Identifier { id: Name("match"), range: 5..10, node_index: NodeIndex(None), }, ), names: [ Alias { range: 18..25, node_index: NodeIndex(None), name: Identifier { id: Name("pattern"), range: 18..25, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 26..46, module: Some( Identifier { id: Name("type"), range: 31..35, node_index: NodeIndex(None), }, ), names: [ Alias { range: 43..46, node_index: NodeIndex(None), name: Identifier { id: Name("bar"), range: 43..46, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 47..71, module: Some( Identifier { id: Name("case"), range: 52..56, node_index: NodeIndex(None), }, ), names: [ Alias { range: 64..71, node_index: NodeIndex(None), name: Identifier { id: Name("pattern"), range: 64..71, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 72..92, module: Some( Identifier { id: Name("lazy"), range: 77..81, node_index: NodeIndex(None), }, ), names: [ Alias { range: 89..92, node_index: NodeIndex(None), name: Identifier { id: Name("qux"), range: 89..92, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 93..124, module: Some( Identifier { id: Name("match.type.case"), range: 98..113, node_index: NodeIndex(None), }, ), names: [ Alias { range: 121..124, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 121..124, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@from_import_stmt_terminator.py.snap000064400000000000000000000233141046102023000335640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/from_import_stmt_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..97, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..20, module: Some( Identifier { id: Name("a"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 15..16, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 15..16, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 18..19, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 18..19, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 21..41, module: Some( Identifier { id: Name("a"), range: 26..27, node_index: NodeIndex(None), }, ), names: [ Alias { range: 36..37, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 36..37, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 39..40, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 39..40, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 43..47, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 43..47, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 48..66, module: Some( Identifier { id: Name("a"), range: 53..54, node_index: NodeIndex(None), }, ), names: [ Alias { range: 62..63, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 62..63, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 65..66, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 65..66, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..72, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 68..72, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 73..91, module: Some( Identifier { id: Name("a"), range: 78..79, node_index: NodeIndex(None), }, ), names: [ Alias { range: 87..88, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 87..88, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 90..91, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 90..91, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 92..96, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 92..96, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@fstring_format_spec_terminator.py.snap000064400000000000000000000213311046102023000342130ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/fstring_format_spec_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..43, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..19, value: FString( ExprFString { node_index: NodeIndex(None), range: 0..19, value: FStringValue { inner: Single( FString( FString { range: 0..19, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 2..8, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 8..12, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 9..10, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 11..11, node_index: NodeIndex(None), elements: [], }, ), }, ), Literal( InterpolatedStringLiteralElement { range: 12..18, node_index: NodeIndex(None), value: " world", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 20..42, value: FString( ExprFString { node_index: NodeIndex(None), range: 20..42, value: FStringValue { inner: Single( FString( FString { range: 20..42, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 22..28, node_index: NodeIndex(None), value: "hello ", }, ), Interpolation( InterpolatedElement { range: 28..35, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 31..34, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 31..34, node_index: NodeIndex(None), value: ".3f", }, ), ], }, ), }, ), Literal( InterpolatedStringLiteralElement { range: 35..41, node_index: NodeIndex(None), value: " world", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` valid_syntax@function_def_parameter_range.py.snap000064400000000000000000000110701046102023000335670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/function_def_parameter_range.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..56, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..55, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..43, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 13..23, node_index: NodeIndex(None), parameter: Parameter { range: 13..23, node_index: NodeIndex(None), name: Identifier { id: Name("first"), range: 13..18, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 20..23, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 29..40, node_index: NodeIndex(None), parameter: Parameter { range: 29..40, node_index: NodeIndex(None), name: Identifier { id: Name("second"), range: 29..35, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 37..40, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 47..50, id: Name("int"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 52..55, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 52..55, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@function_def_parenthesized_return_types.py.snap000064400000000000000000000123641046102023000361320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/function_def_parenthesized_return_types.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..54, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..24, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 13..19, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 25..53, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 29..32, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 32..34, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 38..48, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 39..42, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 44..47, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 50..53, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@function_def_valid_return_expr.py.snap000064400000000000000000000224101046102023000341670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/function_def_valid_return_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..97, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..27, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..9, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 13..22, left: Name( ExprName { node_index: NodeIndex(None), range: 13..16, id: Name("int"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 19..22, id: Name("str"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 24..27, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 28..57, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 32..35, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 35..37, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 41..52, parameters: Some( Parameters { range: 48..49, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 48..49, node_index: NodeIndex(None), parameter: Parameter { range: 48..49, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 48..49, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 51..52, id: Name("x"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 54..57, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 54..57, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 58..96, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 62..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( If( ExprIf { node_index: NodeIndex(None), range: 71..91, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 78..82, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 71..74, id: Name("int"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 88..91, id: Name("str"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 93..96, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 93..96, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@function_type_params_py312.py.snap000064400000000000000000000052261046102023000331050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/function_type_params_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..62, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..61, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 51..54, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 52..53, name: Identifier { id: Name("T"), range: 52..53, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 54..56, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@global_stmt.py.snap000064400000000000000000000027711046102023000303060ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/global_stmt.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ Global( StmtGlobal { node_index: NodeIndex(None), range: 0..8, names: [ Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, ], }, ), Global( StmtGlobal { node_index: NodeIndex(None), range: 9..23, names: [ Identifier { id: Name("x"), range: 16..17, node_index: NodeIndex(None), }, Identifier { id: Name("y"), range: 19..20, node_index: NodeIndex(None), }, Identifier { id: Name("z"), range: 22..23, node_index: NodeIndex(None), }, ], }, ), ], }, ) ``` valid_syntax@import_as_name_soft_keyword.py.snap000064400000000000000000000101121046102023000335000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/import_as_name_soft_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..77, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..19, names: [ Alias { range: 7..19, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 7..10, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("match"), range: 14..19, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 20..38, names: [ Alias { range: 27..38, node_index: NodeIndex(None), name: Identifier { id: Name("bar"), range: 27..30, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("case"), range: 34..38, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 39..57, names: [ Alias { range: 46..57, node_index: NodeIndex(None), name: Identifier { id: Name("baz"), range: 46..49, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("type"), range: 53..57, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 58..76, names: [ Alias { range: 65..76, node_index: NodeIndex(None), name: Identifier { id: Name("qux"), range: 65..68, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("lazy"), range: 72..76, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@import_from_star.py.snap000064400000000000000000000023631046102023000313620ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/import_from_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..21, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..20, module: Some( Identifier { id: Name("module"), range: 5..11, node_index: NodeIndex(None), }, ), names: [ Alias { range: 19..20, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 19..20, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@import_stmt_terminator.py.snap000064400000000000000000000115401046102023000325370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/import_stmt_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..42, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..11, names: [ Alias { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 7..8, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 10..11, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 10..11, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 13..24, names: [ Alias { range: 20..21, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 20..21, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 23..24, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 23..24, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 25..36, names: [ Alias { range: 32..33, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 32..33, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 35..36, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 35..36, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 37..41, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 37..41, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("c"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("d"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@irrefutable_case_pattern_at_end.py.snap000064400000000000000000000270631046102023000342670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/irrefutable_case_pattern_at_end.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..176, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..42, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..24, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 18..19, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 21..24, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 21..24, }, ), }, ), ], }, MatchCase { range: 29..42, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 34..37, pattern: None, name: Some( Identifier { id: Name("var"), range: 34..37, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 39..42, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 39..42, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 43..83, subject: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 56..67, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 61..62, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 64..67, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 64..67, }, ), }, ), ], }, MatchCase { range: 72..83, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 77..78, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 80..83, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 80..83, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 84..175, subject: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 97..118, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 102..105, pattern: None, name: Some( Identifier { id: Name("var"), range: 102..105, node_index: NodeIndex(None), }, ), }, ), guard: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 109..113, value: true, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 115..118, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 115..118, }, ), }, ), ], }, MatchCase { range: 164..175, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 169..170, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 169..170, value: Int( 2, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 172..175, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 172..175, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@iter_unpack_return_py37.py.snap000064400000000000000000000157031046102023000325040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/iter_unpack_return_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..93, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..92, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 69..92, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 76..92, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 77..78, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 80..81, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 86..91, value: Name( ExprName { node_index: NodeIndex(None), range: 87..91, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), ], }, ), ], }, ) ``` valid_syntax@iter_unpack_return_py38.py.snap000064400000000000000000000157041046102023000325060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/iter_unpack_return_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..91, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..90, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 69..90, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 76..90, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 85..90, value: Name( ExprName { node_index: NodeIndex(None), range: 86..90, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), ], }, ), ], }, ) ``` valid_syntax@iter_unpack_yield_py37.py.snap000064400000000000000000000172221046102023000322710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/iter_unpack_yield_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..91, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..91, value: Yield( ExprYield { node_index: NodeIndex(None), range: 69..91, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 75..91, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 76..77, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 79..80, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 85..90, value: Name( ExprName { node_index: NodeIndex(None), range: 86..90, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@iter_unpack_yield_py38.py.snap000064400000000000000000000354431046102023000322770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/iter_unpack_yield_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..128, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 43..59, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 43..47, id: Name("rest"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 50..59, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 4, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 5, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 6, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 60..89, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 64..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 69..89, value: Yield( ExprYield { node_index: NodeIndex(None), range: 69..89, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 75..89, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 3, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 84..89, value: Name( ExprName { node_index: NodeIndex(None), range: 85..89, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 90..127, is_async: false, decorator_list: [], name: Identifier { id: Name("h"), range: 94..95, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 95..97, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 99..127, value: Yield( ExprYield { node_index: NodeIndex(None), range: 99..127, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 105..127, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 1, ), }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 109..123, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 115..123, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 115..116, value: Int( 2, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 118..123, value: Name( ExprName { node_index: NodeIndex(None), range: 119..123, id: Name("rest"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 126..127, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@lambda_with_no_parameters.py.snap000064400000000000000000000021401046102023000331000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lambda_with_no_parameters.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..10, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..9, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..9, parameters: None, body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@lambda_with_valid_body.py.snap000064400000000000000000000476701046102023000323760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lambda_with_valid_body.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..152, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..11, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 0..11, parameters: Some( Parameters { range: 7..8, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 7..8, node_index: NodeIndex(None), parameter: Parameter { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 7..8, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 10..11, id: Name("x"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 12..38, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 12..38, parameters: Some( Parameters { range: 19..20, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 19..20, node_index: NodeIndex(None), parameter: Parameter { range: 19..20, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 19..20, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: If( ExprIf { node_index: NodeIndex(None), range: 22..38, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 27..31, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 22..23, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 39..56, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 39..56, parameters: Some( Parameters { range: 46..47, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 46..47, node_index: NodeIndex(None), parameter: Parameter { range: 46..47, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 46..47, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Await( ExprAwait { node_index: NodeIndex(None), range: 49..56, value: Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("x"), ctx: Load, }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 57..82, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 57..82, parameters: Some( Parameters { range: 64..65, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 64..65, node_index: NodeIndex(None), parameter: Parameter { range: 64..65, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 64..65, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Lambda( ExprLambda { node_index: NodeIndex(None), range: 67..82, parameters: Some( Parameters { range: 74..75, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 74..75, node_index: NodeIndex(None), parameter: Parameter { range: 74..75, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 74..75, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 77..82, left: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("x"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("y"), ctx: Load, }, ), }, ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 83..102, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 83..102, parameters: Some( Parameters { range: 90..91, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 90..91, node_index: NodeIndex(None), parameter: Parameter { range: 90..91, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 90..91, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Yield( ExprYield { node_index: NodeIndex(None), range: 94..101, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 136..151, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 136..151, elts: [ Lambda( ExprLambda { node_index: NodeIndex(None), range: 136..147, parameters: Some( Parameters { range: 143..144, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 143..144, node_index: NodeIndex(None), parameter: Parameter { range: 143..144, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 143..144, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Load, }, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 149..151, value: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ) ``` valid_syntax@lazy_import_relative_py315.py.snap000064400000000000000000000071421046102023000331220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lazy_import_relative_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..124, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 44..69, module: None, names: [ Alias { range: 63..69, node_index: NodeIndex(None), name: Identifier { id: Name("basic2"), range: 63..69, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 70..99, module: Some( Identifier { id: Name("basic2"), range: 81..87, node_index: NodeIndex(None), }, ), names: [ Alias { range: 95..96, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 95..96, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 98..99, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 98..99, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 100..123, module: None, names: [ Alias { range: 119..120, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 119..120, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 122..123, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 122..123, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: true, }, ), ], }, ) ``` valid_syntax@lazy_import_semantic_ok_py315.py.snap000064400000000000000000000173071046102023000336070ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lazy_import_semantic_ok_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..173, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 44..61, names: [ Alias { range: 51..61, node_index: NodeIndex(None), name: Identifier { id: Name("contextlib"), range: 51..61, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), With( StmtWith { node_index: NodeIndex(None), range: 62..111, is_async: false, items: [ WithItem { range: 67..91, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 67..91, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 67..89, value: Name( ExprName { node_index: NodeIndex(None), range: 67..77, id: Name("contextlib"), ctx: Load, }, ), attr: Identifier { id: Name("nullcontext"), range: 78..89, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 89..91, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Import( StmtImport { node_index: NodeIndex(None), range: 97..111, names: [ Alias { range: 109..111, node_index: NodeIndex(None), name: Identifier { id: Name("os"), range: 109..111, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 112..172, is_async: false, items: [ WithItem { range: 117..141, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 117..141, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 117..139, value: Name( ExprName { node_index: NodeIndex(None), range: 117..127, id: Name("contextlib"), ctx: Load, }, ), attr: Identifier { id: Name("nullcontext"), range: 128..139, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 139..141, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 147..172, module: Some( Identifier { id: Name("sys"), range: 157..160, node_index: NodeIndex(None), }, ), names: [ Alias { range: 168..172, node_index: NodeIndex(None), name: Identifier { id: Name("path"), range: 168..172, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ], }, ), ], }, ) ``` valid_syntax@lazy_import_soft_keyword_split_py315.py.snap000064400000000000000000000055371046102023000352470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lazy_import_soft_keyword_split_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..97, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..48, value: Name( ExprName { node_index: NodeIndex(None), range: 44..48, id: Name("lazy"), ctx: Load, }, ), }, ), Import( StmtImport { node_index: NodeIndex(None), range: 49..58, names: [ Alias { range: 56..58, node_index: NodeIndex(None), name: Identifier { id: Name("os"), range: 56..58, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..64, value: Name( ExprName { node_index: NodeIndex(None), range: 60..64, id: Name("lazy"), ctx: Load, }, ), }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 76..96, module: Some( Identifier { id: Name("sys"), range: 81..84, node_index: NodeIndex(None), }, ), names: [ Alias { range: 92..96, node_index: NodeIndex(None), name: Identifier { id: Name("path"), range: 92..96, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@lazy_import_stmt_py315.py.snap000064400000000000000000000156751046102023000323100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/lazy_import_stmt_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..185, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 44..59, names: [ Alias { range: 56..59, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 56..59, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: true, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 60..82, names: [ Alias { range: 72..82, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 72..75, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("bar"), range: 79..82, node_index: NodeIndex(None), }, ), }, ], is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 83..107, module: Some( Identifier { id: Name("bar"), range: 93..96, node_index: NodeIndex(None), }, ), names: [ Alias { range: 104..107, node_index: NodeIndex(None), name: Identifier { id: Name("baz"), range: 104..107, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: true, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 108..135, module: Some( Identifier { id: Name("sys"), range: 118..121, node_index: NodeIndex(None), }, ), names: [ Alias { range: 129..135, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 129..130, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("y"), range: 134..135, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: true, }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 136..144, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 136..140, id: Name("lazy"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..144, value: Int( 1, ), }, ), }, ), Import( StmtImport { node_index: NodeIndex(None), range: 145..163, names: [ Alias { range: 152..163, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 152..155, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("lazy"), range: 159..163, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 164..184, module: Some( Identifier { id: Name("lazy"), range: 169..173, node_index: NodeIndex(None), }, ), names: [ Alias { range: 181..184, node_index: NodeIndex(None), name: Identifier { id: Name("qux"), range: 181..184, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@match_after_py310.py.snap000064400000000000000000000041561046102023000311300ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_after_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..80, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 46..79, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 2, ), }, ), cases: [ MatchCase { range: 59..79, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 64..65, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 64..65, value: Int( 1, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 75..79, }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_annotated_assignment.py.snap000064400000000000000000000114141046102023000332730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_annotated_assignment.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..13, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 0..8, value: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("match"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 0, ), }, ), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 10..13, id: Name("int"), ctx: Load, }, ), value: None, simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 14..35, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 14..29, value: Name( ExprName { node_index: NodeIndex(None), range: 14..19, id: Name("match"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 21..28, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("y"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 27..28, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 31..35, id: Name("dict"), ctx: Load, }, ), value: None, simple: false, }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@match_as_pattern.py.snap000064400000000000000000000102001046102023000312750ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_as_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..60, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..32, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 15..32, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 20..27, pattern: None, name: Some( Identifier { id: Name("foo_bar"), range: 20..27, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 29..32, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 29..32, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 33..59, subject: Name( ExprName { node_index: NodeIndex(None), range: 39..42, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 48..59, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 53..54, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 56..59, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 56..59, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_as_pattern_soft_keyword.py.snap000064400000000000000000000150601046102023000340260ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_as_pattern_soft_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..91, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..29, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 15..29, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 20..24, pattern: None, name: Some( Identifier { id: Name("case"), range: 20..24, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 26..29, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 30..60, subject: Name( ExprName { node_index: NodeIndex(None), range: 36..39, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 45..60, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 50..55, pattern: None, name: Some( Identifier { id: Name("match"), range: 50..55, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 61..90, subject: Name( ExprName { node_index: NodeIndex(None), range: 67..70, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 76..90, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 81..85, pattern: None, name: Some( Identifier { id: Name("type"), range: 81..85, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 87..90, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 87..90, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_attr_pattern_soft_keyword.py.snap000064400000000000000000000363751046102023000344110ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_attr_pattern_soft_keyword.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..131, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..130, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 15..34, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 20..29, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 20..29, value: Name( ExprName { node_index: NodeIndex(None), range: 20..25, id: Name("match"), ctx: Load, }, ), attr: Identifier { id: Name("bar"), range: 26..29, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 31..34, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 31..34, }, ), }, ), ], }, MatchCase { range: 39..57, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 44..52, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 44..52, value: Name( ExprName { node_index: NodeIndex(None), range: 44..48, id: Name("case"), ctx: Load, }, ), attr: Identifier { id: Name("bar"), range: 49..52, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 54..57, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 54..57, }, ), }, ), ], }, MatchCase { range: 62..80, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 67..75, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 67..75, value: Name( ExprName { node_index: NodeIndex(None), range: 67..71, id: Name("type"), ctx: Load, }, ), attr: Identifier { id: Name("bar"), range: 72..75, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 77..80, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 77..80, }, ), }, ), ], }, MatchCase { range: 85..130, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 90..125, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..125, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..119, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..114, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..109, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..105, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 90..100, value: Name( ExprName { node_index: NodeIndex(None), range: 90..95, id: Name("match"), ctx: Load, }, ), attr: Identifier { id: Name("case"), range: 96..100, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("type"), range: 101..105, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("bar"), range: 106..109, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("type"), range: 110..114, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("case"), range: 115..119, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("match"), range: 120..125, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 127..130, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 127..130, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_classify_as_identifier_1.py.snap000064400000000000000000000031101046102023000340020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_classify_as_identifier_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..18, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..17, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 0..17, left: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("match"), ctx: Load, }, ), ops: [ NotIn, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 13..17, id: Name("case"), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` valid_syntax@match_classify_as_identifier_2.py.snap000064400000000000000000000334441046102023000340200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_classify_as_identifier_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..149, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..5, value: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("match"), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 6..18, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 6..18, left: Name( ExprName { node_index: NodeIndex(None), range: 6..11, id: Name("match"), ctx: Load, }, ), ops: [ NotEq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 15..18, id: Name("foo"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 19..31, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 19..31, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 20..23, id: Name("foo"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 25..30, id: Name("match"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 32..44, value: List( ExprList { node_index: NodeIndex(None), range: 32..44, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 33..36, id: Name("foo"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 38..43, id: Name("match"), ctx: Load, }, ), ], ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 45..57, value: Set( ExprSet { node_index: NodeIndex(None), range: 45..57, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 46..49, id: Name("foo"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 51..56, id: Name("match"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..63, value: Name( ExprName { node_index: NodeIndex(None), range: 58..63, id: Name("match"), ctx: Load, }, ), }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 65..75, target: Name( ExprName { node_index: NodeIndex(None), range: 65..70, id: Name("match"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 72..75, id: Name("int"), ctx: Load, }, ), value: None, simple: true, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..82, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 76..82, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 76..81, id: Name("match"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 83..92, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 83..92, value: Name( ExprName { node_index: NodeIndex(None), range: 83..88, id: Name("match"), ctx: Load, }, ), attr: Identifier { id: Name("foo"), range: 89..92, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..104, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 93..104, left: Name( ExprName { node_index: NodeIndex(None), range: 93..98, id: Name("match"), ctx: Load, }, ), op: Div, right: Name( ExprName { node_index: NodeIndex(None), range: 101..104, id: Name("foo"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 105..117, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 105..117, left: Name( ExprName { node_index: NodeIndex(None), range: 105..110, id: Name("match"), ctx: Load, }, ), op: LShift, right: Name( ExprName { node_index: NodeIndex(None), range: 114..117, id: Name("foo"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 118..131, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 118..131, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 118..123, id: Name("match"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 128..131, id: Name("foo"), ctx: Load, }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 132..148, value: Compare( ExprCompare { node_index: NodeIndex(None), range: 132..148, left: Name( ExprName { node_index: NodeIndex(None), range: 132..137, id: Name("match"), ctx: Load, }, ), ops: [ IsNot, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 145..148, id: Name("foo"), ctx: Load, }, ), ], }, ), }, ), ], }, ) ``` valid_syntax@match_classify_as_keyword_1.py.snap000064400000000000000000000722111046102023000333540ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_classify_as_keyword_1.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..358, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..26, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..9, id: Name("foo"), ctx: Load, }, ), cases: [ MatchCase { range: 15..26, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 20..21, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 23..26, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 23..26, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 27..51, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..34, value: Int( 1, ), }, ), cases: [ MatchCase { range: 40..51, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 45..46, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 48..51, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 48..51, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 52..78, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 58..61, value: Float( 1.0, ), }, ), cases: [ MatchCase { range: 67..78, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 72..73, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 75..78, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 75..78, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 79..104, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 85..87, value: Complex { real: 0.0, imag: 1.0, }, }, ), cases: [ MatchCase { range: 93..104, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 98..99, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 101..104, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 101..104, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 105..133, subject: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 111..116, value: StringLiteralValue { inner: Single( StringLiteral { range: 111..116, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), cases: [ MatchCase { range: 122..133, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 127..128, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 130..133, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 130..133, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 134..167, subject: FString( ExprFString { node_index: NodeIndex(None), range: 140..150, value: FStringValue { inner: Single( FString( FString { range: 140..150, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 142..146, node_index: NodeIndex(None), value: "foo ", }, ), Interpolation( InterpolatedElement { range: 146..149, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 147..148, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), cases: [ MatchCase { range: 156..167, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 161..162, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 164..167, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 164..167, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 168..197, subject: Set( ExprSet { node_index: NodeIndex(None), range: 174..180, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 175..176, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 178..179, value: Int( 2, ), }, ), ], }, ), cases: [ MatchCase { range: 186..197, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 191..192, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 194..197, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 194..197, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 198..225, subject: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 204..208, op: Invert, operand: Name( ExprName { node_index: NodeIndex(None), range: 205..208, id: Name("foo"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 214..225, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 219..220, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 222..225, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 222..225, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 226..252, subject: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 232..235, }, ), cases: [ MatchCase { range: 241..252, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 246..247, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 249..252, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 249..252, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 253..283, subject: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 259..266, op: Not, operand: Name( ExprName { node_index: NodeIndex(None), range: 263..266, id: Name("foo"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 272..283, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 277..278, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 280..283, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 280..283, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 284..318, subject: Await( ExprAwait { node_index: NodeIndex(None), range: 290..301, value: Call( ExprCall { node_index: NodeIndex(None), range: 296..301, func: Name( ExprName { node_index: NodeIndex(None), range: 296..299, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 299..301, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), cases: [ MatchCase { range: 307..318, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 312..313, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 315..318, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 315..318, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 319..357, subject: Lambda( ExprLambda { node_index: NodeIndex(None), range: 325..340, parameters: Some( Parameters { range: 332..335, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 332..335, node_index: NodeIndex(None), parameter: Parameter { range: 332..335, node_index: NodeIndex(None), name: Identifier { id: Name("foo"), range: 332..335, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 337..340, id: Name("foo"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 346..357, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 351..352, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 354..357, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 354..357, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_classify_as_keyword_2.py.snap000064400000000000000000000254771046102023000333710ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_classify_as_keyword_2.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..170, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..28, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..11, id: Name("match"), ctx: Load, }, ), cases: [ MatchCase { range: 17..28, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 22..23, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 29..56, subject: Name( ExprName { node_index: NodeIndex(None), range: 35..39, id: Name("case"), ctx: Load, }, ), cases: [ MatchCase { range: 45..56, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 50..51, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..56, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 53..56, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 57..84, subject: Name( ExprName { node_index: NodeIndex(None), range: 63..67, id: Name("type"), ctx: Load, }, ), cases: [ MatchCase { range: 73..84, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 78..79, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 85..112, subject: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 91..95, }, ), cases: [ MatchCase { range: 101..112, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 106..107, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 109..112, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 113..140, subject: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 119..123, value: true, }, ), cases: [ MatchCase { range: 129..140, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 134..135, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 137..140, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 137..140, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 141..169, subject: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 147..152, value: false, }, ), cases: [ MatchCase { range: 158..169, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 163..164, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 166..169, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 166..169, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_classify_as_keyword_or_identifier.py.snap000064400000000000000000000333441046102023000360420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_classify_as_keyword_or_identifier.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..225, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..12, value: Call( ExprCall { node_index: NodeIndex(None), range: 0..12, func: Name( ExprName { node_index: NodeIndex(None), range: 0..5, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 6..12, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..11, value: Int( 2, ), }, ), ], keywords: [], }, }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 27..67, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 33..39, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 34..35, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 37..38, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), cases: [ MatchCase { range: 56..67, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 61..62, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 64..67, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 64..67, }, ), }, ), ], }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 68..78, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 68..78, value: Name( ExprName { node_index: NodeIndex(None), range: 68..73, id: Name("match"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 75..77, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 75..76, value: Int( 1, ), }, ), ), upper: None, step: None, }, ), ctx: Load, }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 93..133, subject: List( ExprList { node_index: NodeIndex(None), range: 99..105, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 100..101, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 103..104, value: Int( 2, ), }, ), ], ctx: Load, }, ), cases: [ MatchCase { range: 122..133, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 127..128, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 130..133, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 130..133, }, ), }, ), ], }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 134..145, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 134..145, left: Name( ExprName { node_index: NodeIndex(None), range: 134..139, id: Name("match"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 142..145, id: Name("foo"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 160..171, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 160..171, left: Name( ExprName { node_index: NodeIndex(None), range: 160..165, id: Name("match"), ctx: Load, }, ), op: Sub, right: Name( ExprName { node_index: NodeIndex(None), range: 168..171, id: Name("foo"), ctx: Load, }, ), }, ), }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 186..224, subject: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 192..196, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 193..196, id: Name("foo"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 213..224, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 218..219, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 221..224, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 221..224, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_sequence_pattern_parentheses_terminator.py.snap000064400000000000000000000153011046102023000372770ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_sequence_pattern_parentheses_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..56, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 19..35, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 24..30, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 25..26, pattern: None, name: Some( Identifier { id: Name("a"), range: 25..26, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 28..29, pattern: None, name: Some( Identifier { id: Name("b"), range: 28..29, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 32..35, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 32..35, }, ), }, ), ], }, MatchCase { range: 40..56, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 45..51, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 46..47, pattern: None, name: Some( Identifier { id: Name("a"), range: 46..47, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 49..50, pattern: None, name: Some( Identifier { id: Name("b"), range: 49..50, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 53..56, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 53..56, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_sequence_pattern_terminator.py.snap000064400000000000000000000252351046102023000347050ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_sequence_pattern_terminator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..95, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..94, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..13, id: Name("subject"), ctx: Load, }, ), cases: [ MatchCase { range: 19..35, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 24..25, pattern: None, name: Some( Identifier { id: Name("a"), range: 24..25, node_index: NodeIndex(None), }, ), }, ), guard: Some( Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 32..35, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 32..35, }, ), }, ), ], }, MatchCase { range: 40..54, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 45..49, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 45..46, pattern: None, name: Some( Identifier { id: Name("a"), range: 45..46, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 48..49, pattern: None, name: Some( Identifier { id: Name("b"), range: 48..49, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 51..54, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 51..54, }, ), }, ), ], }, MatchCase { range: 59..78, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 64..68, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 64..65, pattern: None, name: Some( Identifier { id: Name("a"), range: 64..65, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 67..68, pattern: None, name: Some( Identifier { id: Name("b"), range: 67..68, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: Some( Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("x"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 75..78, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 75..78, }, ), }, ), ], }, MatchCase { range: 83..94, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 88..89, pattern: None, name: Some( Identifier { id: Name("a"), range: 88..89, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 91..94, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 91..94, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_stmt_subject_expr.py.snap000064400000000000000000000263341046102023000326410ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_stmt_subject_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..185, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..29, subject: Named( ExprNamed { node_index: NodeIndex(None), range: 6..12, target: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 1, ), }, ), }, ), cases: [ MatchCase { range: 18..29, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 23..24, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..29, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 26..29, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 30..61, subject: Named( ExprNamed { node_index: NodeIndex(None), range: 37..43, target: Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 42..43, value: Int( 1, ), }, ), }, ), cases: [ MatchCase { range: 50..61, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 55..56, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 121..153, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 127..136, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 127..133, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 128..133, left: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("y"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("z"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 142..153, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 147..148, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 150..153, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 150..153, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 154..184, subject: Await( ExprAwait { node_index: NodeIndex(None), range: 160..167, value: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("x"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 173..184, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 178..179, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 181..184, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 181..184, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@match_stmt_valid_guard_expr.py.snap000064400000000000000000000357221046102023000334640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/match_stmt_valid_guard_expr.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..158, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..34, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 13..34, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 18..19, pattern: None, name: Some( Identifier { id: Name("y"), range: 18..19, node_index: NodeIndex(None), }, ), }, ), guard: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 23..29, target: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 31..34, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 31..34, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 35..79, subject: Name( ExprName { node_index: NodeIndex(None), range: 41..42, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 48..79, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 53..54, pattern: None, name: Some( Identifier { id: Name("y"), range: 53..54, node_index: NodeIndex(None), }, ), }, ), guard: Some( If( ExprIf { node_index: NodeIndex(None), range: 58..74, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 63..67, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 58..59, id: Name("a"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("b"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 76..79, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 76..79, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 80..119, subject: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 93..119, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 98..99, pattern: None, name: Some( Identifier { id: Name("y"), range: 98..99, node_index: NodeIndex(None), }, ), }, ), guard: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 103..114, parameters: Some( Parameters { range: 110..111, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 110..111, node_index: NodeIndex(None), parameter: Parameter { range: 110..111, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 110..111, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("b"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 116..119, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 116..119, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 120..157, subject: Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 133..157, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 138..139, pattern: None, name: Some( Identifier { id: Name("y"), range: 138..139, node_index: NodeIndex(None), }, ), }, ), guard: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 144..151, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("x"), ctx: Load, }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 154..157, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 154..157, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@multiple_assignment_in_case_pattern.py.snap000064400000000000000000000153641046102023000352230ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/multiple_assignment_in_case_pattern.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..42, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..41, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 2, ), }, ), cases: [ MatchCase { range: 13..41, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 18..36, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 18..26, cls: Name( ExprName { node_index: NodeIndex(None), range: 18..23, id: Name("Class"), ctx: Load, }, ), arguments: PatternArguments { range: 23..26, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 24..25, pattern: None, name: Some( Identifier { id: Name("x"), range: 24..25, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 29..32, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 30..31, pattern: None, name: Some( Identifier { id: Name("x"), range: 30..31, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 35..36, pattern: None, name: Some( Identifier { id: Name("x"), range: 35..36, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 38..41, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 38..41, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@multiple_starred_assignment_target.py.snap000064400000000000000000000212221046102023000350650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/multiple_starred_assignment_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..46, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..16, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 0..7, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 10..16, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 14..15, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 17..45, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 17..33, elts: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 17..29, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 18..20, value: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("_"), ctx: Store, }, ), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 22..28, id: Name("normed"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 31..33, value: Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("_"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 36..45, elts: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 37..41, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 2, ), }, ), ], ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@nested_alternative_patterns.py.snap000064400000000000000000001426011046102023000335150ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/nested_alternative_patterns.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..271, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 0..96, subject: Name( ExprName { node_index: NodeIndex(None), range: 6..10, id: Name("ruff"), ctx: Load, }, ), cases: [ MatchCase { range: 16..96, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 21..83, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 21..67, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 22..28, value: StringLiteralValue { inner: Single( StringLiteral { range: 22..28, node_index: NodeIndex(None), value: "lint", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 30..66, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 30..43, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 31..39, value: StringLiteralValue { inner: Single( StringLiteral { range: 31..39, node_index: NodeIndex(None), value: "select", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 41..42, pattern: None, name: Some( Identifier { id: Name("x"), range: 41..42, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 46..66, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 47..62, value: StringLiteralValue { inner: Single( StringLiteral { range: 47..62, node_index: NodeIndex(None), value: "extend-select", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 64..65, pattern: None, name: Some( Identifier { id: Name("x"), range: 64..65, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), ], }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 70..83, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 71..79, value: StringLiteralValue { inner: Single( StringLiteral { range: 71..79, node_index: NodeIndex(None), value: "select", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 81..82, pattern: None, name: Some( Identifier { id: Name("x"), range: 81..82, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 93..96, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 93..96, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 97..136, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 103..105, value: Int( 42, ), }, ), cases: [ MatchCase { range: 111..136, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 116..131, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 116..127, patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 117..126, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 117..120, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 118..119, pattern: None, name: Some( Identifier { id: Name("x"), range: 118..119, node_index: NodeIndex(None), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 123..126, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 124..125, pattern: None, name: Some( Identifier { id: Name("x"), range: 124..125, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), ], }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 130..131, pattern: None, name: Some( Identifier { id: Name("x"), range: 130..131, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 133..136, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 133..136, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 137..180, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 143..145, value: Int( 42, ), }, ), cases: [ MatchCase { range: 151..180, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 156..175, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 156..171, patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 157..170, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 157..164, patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 158..163, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 158..159, pattern: None, name: Some( Identifier { id: Name("x"), range: 158..159, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 162..163, pattern: None, name: Some( Identifier { id: Name("x"), range: 162..163, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 167..170, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 168..169, pattern: None, name: Some( Identifier { id: Name("x"), range: 168..169, node_index: NodeIndex(None), }, ), }, ), ], }, ), ], }, ), ], }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 174..175, pattern: None, name: Some( Identifier { id: Name("x"), range: 174..175, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 177..180, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 177..180, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 181..270, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 187..189, value: Int( 42, ), }, ), cases: [ MatchCase { range: 195..270, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 200..265, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 200..246, cls: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 200..213, value: Name( ExprName { node_index: NodeIndex(None), range: 200..203, id: Name("ast"), ctx: Load, }, ), attr: Identifier { id: Name("Subscript"), range: 204..213, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: PatternArguments { range: 213..246, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 214..215, pattern: None, name: Some( Identifier { id: Name("n"), range: 214..215, node_index: NodeIndex(None), }, ), }, ), MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 217..245, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 217..231, cls: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 217..229, value: Name( ExprName { node_index: NodeIndex(None), range: 217..220, id: Name("ast"), ctx: Load, }, ), attr: Identifier { id: Name("Constant"), range: 221..229, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: PatternArguments { range: 229..231, node_index: NodeIndex(None), patterns: [], keywords: [], }, }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 234..245, cls: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 234..243, value: Name( ExprName { node_index: NodeIndex(None), range: 234..237, id: Name("ast"), ctx: Load, }, ), attr: Identifier { id: Name("Slice"), range: 238..243, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: PatternArguments { range: 243..245, node_index: NodeIndex(None), patterns: [], keywords: [], }, }, ), ], }, ), ], keywords: [], }, }, ), MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 249..265, cls: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 249..262, value: Name( ExprName { node_index: NodeIndex(None), range: 249..252, id: Name("ast"), ctx: Load, }, ), attr: Identifier { id: Name("Attribute"), range: 253..262, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: PatternArguments { range: 262..265, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 263..264, pattern: None, name: Some( Identifier { id: Name("n"), range: 263..264, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 267..270, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 267..270, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@nested_async_comprehension_py310.py.snap000064400000000000000000000404661046102023000342670ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/nested_async_comprehension_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..181, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..116, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 54..55, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 55..57, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 63..84, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 63..84, elt: Name( ExprName { node_index: NodeIndex(None), range: 64..65, id: Name("_"), ctx: Load, }, ), generators: [ Comprehension { range: 66..83, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 75..83, func: Name( ExprName { node_index: NodeIndex(None), range: 75..80, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 80..83, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 81..82, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 89..116, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 89..116, elt: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("_"), ctx: Load, }, ), generators: [ Comprehension { range: 92..115, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 107..115, func: Name( ExprName { node_index: NodeIndex(None), range: 107..112, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 112..115, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 113..114, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 117..180, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 127..128, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 128..130, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 136..148, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 140..141, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 141..143, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 145..148, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 145..148, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 153..180, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 153..180, elt: Name( ExprName { node_index: NodeIndex(None), range: 154..155, id: Name("_"), ctx: Load, }, ), generators: [ Comprehension { range: 156..179, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 171..179, func: Name( ExprName { node_index: NodeIndex(None), range: 171..176, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 176..179, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 177..178, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@nested_async_comprehension_py311.py.snap000064400000000000000000000720351046102023000342650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/nested_async_comprehension_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..277, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..111, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 54..55, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 55..57, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 59..111, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 66..111, elt: ListComp( ExprListComp { node_index: NodeIndex(None), range: 67..92, elt: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 70..91, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 85..91, func: Name( ExprName { node_index: NodeIndex(None), range: 85..88, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 88..91, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 89..90, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 93..110, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 102..110, func: Name( ExprName { node_index: NodeIndex(None), range: 102..107, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 107..110, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 108..109, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 122..192, is_async: true, decorator_list: [], name: Identifier { id: Name("g"), range: 132..133, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 133..135, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 137..192, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 144..192, elt: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 145..173, key: Some( Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Load, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 1, ), }, ), generators: [ Comprehension { range: 151..172, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 166..172, func: Name( ExprName { node_index: NodeIndex(None), range: 166..169, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 169..172, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 174..191, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 178..179, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 183..191, func: Name( ExprName { node_index: NodeIndex(None), range: 183..188, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 188..191, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 189..190, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 200..267, is_async: true, decorator_list: [], name: Identifier { id: Name("h"), range: 210..211, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 211..213, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 215..267, value: Some( ListComp( ExprListComp { node_index: NodeIndex(None), range: 222..267, elt: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 223..248, elt: Name( ExprName { node_index: NodeIndex(None), range: 224..225, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 226..247, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 241..247, func: Name( ExprName { node_index: NodeIndex(None), range: 241..244, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 244..247, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 245..246, id: Name("n"), ctx: Load, }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], }, ), generators: [ Comprehension { range: 249..266, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 253..254, id: Name("n"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 258..266, func: Name( ExprName { node_index: NodeIndex(None), range: 258..263, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 263..266, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 264..265, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), ), }, ), ], }, ), ], }, ) ``` valid_syntax@non_duplicate_type_parameter_names.py.snap000064400000000000000000000467431046102023000350370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/non_duplicate_type_parameter_names.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..150, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..23, name: Name( ExprName { node_index: NodeIndex(None), range: 5..10, id: Name("Alias"), ctx: Store, }, ), type_params: Some( TypeParams { range: 10..13, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 11..12, name: Identifier { id: Name("T"), range: 11..12, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 16..23, value: Name( ExprName { node_index: NodeIndex(None), range: 16..20, id: Name("list"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 24..43, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 28..29, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 29..32, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 30..31, name: Identifier { id: Name("T"), range: 30..31, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 32..38, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 33..37, node_index: NodeIndex(None), parameter: Parameter { range: 33..37, node_index: NodeIndex(None), name: Identifier { id: Name("t"), range: 33..34, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("T"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 40..43, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 40..43, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 44..59, decorator_list: [], name: Identifier { id: Name("C"), range: 50..51, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 51..54, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 52..53, name: Identifier { id: Name("T"), range: 52..53, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 56..59, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 56..59, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 60..81, decorator_list: [], name: Identifier { id: Name("C"), range: 66..67, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 67..76, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 68..69, name: Identifier { id: Name("T"), range: 68..69, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 71..72, name: Identifier { id: Name("U"), range: 71..72, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 74..75, name: Identifier { id: Name("V"), range: 74..75, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 78..81, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 78..81, }, ), }, ), ], }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 82..149, name: Name( ExprName { node_index: NodeIndex(None), range: 87..92, id: Name("Alias"), ctx: Store, }, ), type_params: Some( TypeParams { range: 92..143, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 93..94, name: Identifier { id: Name("T"), range: 93..94, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 96..102, name: Identifier { id: Name("U"), range: 96..97, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 99..102, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 104..119, name: Identifier { id: Name("V"), range: 104..105, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 107..119, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 108..111, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 113..118, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 121..124, name: Identifier { id: Name("Ts"), range: 122..124, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 126..129, name: Identifier { id: Name("P"), range: 128..129, node_index: NodeIndex(None), }, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 131..142, name: Identifier { id: Name("D"), range: 131..132, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 135..142, id: Name("default"), ctx: Load, }, ), ), }, ), ], }, ), value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 146..149, }, ), }, ), ], }, ) ``` valid_syntax@non_nested_quote_in_format_spec_py311.py.snap000064400000000000000000000077521046102023000353020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/non_nested_quote_in_format_spec_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..90, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..53, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..53, value: FStringValue { inner: Single( FString( FString { range: 44..53, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..52, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 47..48, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 49..51, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 49..51, node_index: NodeIndex(None), value: "''", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` valid_syntax@non_rebound_comprehension_variable.py.snap000064400000000000000000000106331046102023000350220ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/non_rebound_comprehension_variable.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..27, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..26, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 0..26, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 1..7, target: Name( ExprName { node_index: NodeIndex(None), range: 1..2, id: Name("a"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..7, value: Int( 0, ), }, ), }, ), generators: [ Comprehension { range: 8..25, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 12..13, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 17..25, func: Name( ExprName { node_index: NodeIndex(None), range: 17..22, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 22..25, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 0, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@nonlocal_declaration_at_module_level.py.snap000064400000000000000000000034041046102023000353040ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/nonlocal_declaration_at_module_level.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..24, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..23, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 13..23, names: [ Identifier { id: Name("x"), range: 22..23, node_index: NodeIndex(None), }, ], }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@nonlocal_stmt.py.snap000064400000000000000000000055151046102023000306520ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/nonlocal_stmt.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..45, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..44, is_async: false, decorator_list: [], name: Identifier { id: Name("_"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 13..23, names: [ Identifier { id: Name("x"), range: 22..23, node_index: NodeIndex(None), }, ], }, ), Nonlocal( StmtNonlocal { node_index: NodeIndex(None), range: 28..44, names: [ Identifier { id: Name("x"), range: 37..38, node_index: NodeIndex(None), }, Identifier { id: Name("y"), range: 40..41, node_index: NodeIndex(None), }, Identifier { id: Name("z"), range: 43..44, node_index: NodeIndex(None), }, ], }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@other__atom.py.snap000064400000000000000000000036201046102023000302710ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/other/atom.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..73, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..3, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 0..3, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 4..8, value: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 4..8, value: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 9..14, value: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 9..14, value: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 15..19, value: NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 15..19, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@other__decorator.py.snap000064400000000000000000001051141046102023000313140ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/other/decorator.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..407, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..40, is_async: false, decorator_list: [ Decorator { range: 0..19, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1..19, id: Name("function_decorator"), ctx: Load, }, ), }, ], name: Identifier { id: Name("test"), range: 24..28, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 28..30, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 36..40, }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 43..80, decorator_list: [ Decorator { range: 43..59, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 44..59, id: Name("class_decorator"), ctx: Load, }, ), }, ], name: Identifier { id: Name("Test"), range: 66..70, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 76..80, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 83..106, is_async: false, decorator_list: [ Decorator { range: 83..93, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 84..93, id: Name("decorator"), ctx: Load, }, ), }, ], name: Identifier { id: Name("f"), range: 98..99, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 99..101, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 103..106, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 103..106, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 109..128, is_async: false, decorator_list: [ Decorator { range: 109..115, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 110..115, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 110..113, value: Name( ExprName { node_index: NodeIndex(None), range: 110..111, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 112..113, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("c"), range: 114..115, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("f"), range: 120..121, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 121..123, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 125..128, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 125..128, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 131..153, is_async: false, decorator_list: [ Decorator { range: 131..133, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("a"), ctx: Load, }, ), }, Decorator { range: 134..140, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 135..140, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 135..138, value: Name( ExprName { node_index: NodeIndex(None), range: 135..136, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 137..138, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("c"), range: 139..140, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("f"), range: 145..146, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 146..148, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 150..153, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 150..153, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 156..185, decorator_list: [ Decorator { range: 156..158, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 157..158, id: Name("a"), ctx: Load, }, ), }, Decorator { range: 159..165, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 160..165, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 160..161, value: Int( 1, ), }, ), op: BitOr, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 2, ), }, ), }, ), }, Decorator { range: 166..172, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 167..172, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 167..170, value: Name( ExprName { node_index: NodeIndex(None), range: 167..168, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 169..170, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("c"), range: 171..172, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ], name: Identifier { id: Name("T"), range: 179..180, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 182..185, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 182..185, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 188..269, is_async: false, decorator_list: [ Decorator { range: 188..195, node_index: NodeIndex(None), expression: Named( ExprNamed { node_index: NodeIndex(None), range: 189..195, target: Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 194..195, value: Int( 1, ), }, ), }, ), }, Decorator { range: 196..213, node_index: NodeIndex(None), expression: If( ExprIf { node_index: NodeIndex(None), range: 197..213, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 202..206, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 212..213, id: Name("y"), ctx: Load, }, ), }, ), }, Decorator { range: 214..226, node_index: NodeIndex(None), expression: Lambda( ExprLambda { node_index: NodeIndex(None), range: 215..226, parameters: Some( Parameters { range: 222..223, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 222..223, node_index: NodeIndex(None), parameter: Parameter { range: 222..223, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 222..223, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 225..226, id: Name("x"), ctx: Load, }, ), }, ), }, Decorator { range: 227..235, node_index: NodeIndex(None), expression: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 228..235, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 228..229, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 234..235, id: Name("y"), ctx: Load, }, ), ], }, ), }, Decorator { range: 236..246, node_index: NodeIndex(None), expression: Yield( ExprYield { node_index: NodeIndex(None), range: 238..245, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 244..245, id: Name("x"), ctx: Load, }, ), ), }, ), }, Decorator { range: 247..256, node_index: NodeIndex(None), expression: Tuple( ExprTuple { node_index: NodeIndex(None), range: 248..256, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 249..251, value: Name( ExprName { node_index: NodeIndex(None), range: 250..251, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 253..255, value: Name( ExprName { node_index: NodeIndex(None), range: 254..255, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ], name: Identifier { id: Name("f"), range: 261..262, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 262..264, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 266..269, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 266..269, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 360..380, is_async: false, decorator_list: [ Decorator { range: 360..365, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 361..365, left: Name( ExprName { node_index: NodeIndex(None), range: 361..362, id: Name("x"), ctx: Load, }, ), op: MatMult, right: Name( ExprName { node_index: NodeIndex(None), range: 364..365, id: Name("y"), ctx: Load, }, ), }, ), }, ], name: Identifier { id: Name("foo"), range: 370..373, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 373..375, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 377..380, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 377..380, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 383..407, is_async: false, decorator_list: [ Decorator { range: 383..385, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 384..385, id: Name("x"), ctx: Load, }, ), }, Decorator { range: 388..390, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 389..390, id: Name("y"), ctx: Load, }, ), }, ], name: Identifier { id: Name("foo"), range: 397..400, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 400..402, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 404..407, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 404..407, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@param_with_annotation.py.snap000064400000000000000000000200701046102023000322750ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/param_with_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..54, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..22, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..17, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..16, node_index: NodeIndex(None), parameter: Parameter { range: 8..16, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 8..11, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 13..16, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 19..22, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 19..22, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 23..53, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 27..30, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 30..48, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 31..47, node_index: NodeIndex(None), parameter: Parameter { range: 31..47, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 31..34, node_index: NodeIndex(None), }, annotation: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 36..47, parameters: Some( Parameters { range: 43..44, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 43..44, node_index: NodeIndex(None), parameter: Parameter { range: 43..44, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 43..44, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 50..53, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@param_with_default.py.snap000064400000000000000000000367151046102023000315640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/param_with_default.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..111, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..27, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..22, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..21, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 10..21, parameters: Some( Parameters { range: 17..18, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 17..18, node_index: NodeIndex(None), parameter: Parameter { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 17..18, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("y"), ctx: Load, }, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 24..27, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 24..27, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 28..60, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 32..35, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 35..55, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 36..54, node_index: NodeIndex(None), parameter: Parameter { range: 36..37, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 36..37, node_index: NodeIndex(None), }, annotation: None, }, default: Some( If( ExprIf { node_index: NodeIndex(None), range: 38..54, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 43..47, value: true, }, ), body: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 38..39, value: Int( 1, ), }, ), orelse: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 2, ), }, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 61..84, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 65..68, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 68..79, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 69..78, node_index: NodeIndex(None), parameter: Parameter { range: 69..70, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 69..70, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 71..78, value: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("y"), ctx: Load, }, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 85..110, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 89..92, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 92..105, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 93..104, node_index: NodeIndex(None), parameter: Parameter { range: 93..94, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 93..94, node_index: NodeIndex(None), }, annotation: None, }, default: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 96..103, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 102..103, id: Name("y"), ctx: Load, }, ), ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 107..110, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 107..110, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@param_with_star_annotation.py.snap000064400000000000000000000201541046102023000333310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/param_with_star_annotation.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..67, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..31, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..26, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 8..25, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 9..13, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 15..25, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 16..25, left: Name( ExprName { node_index: NodeIndex(None), range: 16..19, id: Name("int"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 22..25, id: Name("str"), ctx: Load, }, ), }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 28..31, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 28..31, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 32..66, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 36..39, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 39..61, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 40..60, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 41..45, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 47..60, value: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 49..59, op: Or, values: [ Name( ExprName { node_index: NodeIndex(None), range: 49..52, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 56..59, id: Name("str"), ctx: Load, }, ), ], }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 63..66, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 63..66, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@param_with_star_annotation_py310.py.snap000064400000000000000000000516631046102023000342760ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/param_with_star_annotation_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..432, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 169..206, module: Some( Identifier { id: Name("typing"), range: 174..180, node_index: NodeIndex(None), }, ), names: [ Alias { range: 188..197, node_index: NodeIndex(None), name: Identifier { id: Name("Annotated"), range: 188..197, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 199..206, node_index: NodeIndex(None), name: Identifier { id: Name("Literal"), range: 199..206, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 207..230, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 211..214, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 214..225, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 215..224, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 216..220, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 222..224, id: Name("Ts"), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 227..230, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 227..230, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 231..295, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 235..238, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 238..290, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 239..289, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 240..241, node_index: NodeIndex(None), }, annotation: Some( Subscript( ExprSubscript { node_index: NodeIndex(None), range: 243..289, value: Name( ExprName { node_index: NodeIndex(None), range: 243..250, id: Name("Literal"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 251..288, value: StringLiteralValue { inner: Single( StringLiteral { range: 251..288, node_index: NodeIndex(None), value: "this should allow arbitrary strings", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 292..295, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 292..295, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 296..367, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 300..303, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 303..362, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 304..361, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 305..306, node_index: NodeIndex(None), }, annotation: Some( Subscript( ExprSubscript { node_index: NodeIndex(None), range: 308..361, value: Name( ExprName { node_index: NodeIndex(None), range: 308..317, id: Name("Annotated"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 318..360, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 318..321, id: Name("str"), ctx: Load, }, ), StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 323..360, value: StringLiteralValue { inner: Single( StringLiteral { range: 323..360, node_index: NodeIndex(None), value: "this should allow arbitrary strings", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 364..367, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 364..367, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 368..405, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 372..375, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 375..400, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 376..386, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 377..381, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 383..386, id: Name("str"), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 388..399, node_index: NodeIndex(None), name: Identifier { id: Name("kwds"), range: 390..394, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 396..399, id: Name("int"), ctx: Load, }, ), ), }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 402..405, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 402..405, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 406..431, is_async: false, decorator_list: [], name: Identifier { id: Name("union"), range: 410..415, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 415..426, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 416..425, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 417..418, node_index: NodeIndex(None), }, annotation: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 420..425, left: Name( ExprName { node_index: NodeIndex(None), range: 420..421, id: Name("A"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 424..425, id: Name("B"), ctx: Load, }, ), }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 428..431, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 428..431, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@param_with_star_annotation_py311.py.snap000064400000000000000000000061401046102023000342650ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/param_with_star_annotation_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..69, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..68, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 48..51, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 51..63, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 52..62, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 53..57, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 59..62, value: Name( ExprName { node_index: NodeIndex(None), range: 60..62, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 65..68, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 65..68, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@params_non_default_after_star.py.snap000064400000000000000000000274231046102023000337740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/params_non_default_after_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..72, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..33, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..28, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 8..12, node_index: NodeIndex(None), parameter: Parameter { range: 8..9, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 8..9, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 10..12, value: Int( 10, ), }, ), ), }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 17..18, node_index: NodeIndex(None), parameter: Parameter { range: 17..18, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 17..18, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 20..24, node_index: NodeIndex(None), parameter: Parameter { range: 20..21, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 20..21, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 22..24, value: Int( 11, ), }, ), ), }, ParameterWithDefault { range: 26..27, node_index: NodeIndex(None), parameter: Parameter { range: 26..27, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 26..27, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 30..33, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 30..33, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 34..71, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 38..41, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 41..66, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 42..46, node_index: NodeIndex(None), parameter: Parameter { range: 42..43, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 42..43, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 44..46, value: Int( 10, ), }, ), ), }, ], vararg: Some( Parameter { range: 48..53, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 49..53, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 55..56, node_index: NodeIndex(None), parameter: Parameter { range: 55..56, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 55..56, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 58..62, node_index: NodeIndex(None), parameter: Parameter { range: 58..59, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 58..59, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 60..62, value: Int( 11, ), }, ), ), }, ParameterWithDefault { range: 64..65, node_index: NodeIndex(None), parameter: Parameter { range: 64..65, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 64..65, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 68..71, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 68..71, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@params_seen_keyword_only_param_after_star.py.snap000064400000000000000000000143411046102023000364100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/params_seen_keyword_only_param_after_star.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..61, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..28, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 4..7, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 7..23, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 11..12, node_index: NodeIndex(None), parameter: Parameter { range: 11..12, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 11..12, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: Some( Parameter { range: 14..22, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 16..22, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 29..60, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 33..36, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 36..55, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 40..44, node_index: NodeIndex(None), parameter: Parameter { range: 40..41, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 40..41, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 42..44, value: Int( 10, ), }, ), ), }, ], kwarg: Some( Parameter { range: 46..54, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 48..54, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@parenthesized_context_manager_py39.py.snap000064400000000000000000000175561046102023000347160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_context_manager_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..126, body: [ With( StmtWith { node_index: NodeIndex(None), range: 43..73, is_async: false, items: [ WithItem { range: 49..57, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 49..52, id: Name("foo"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Store, }, ), ), }, WithItem { range: 59..67, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 59..62, id: Name("bar"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 70..73, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 70..73, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 74..99, is_async: false, items: [ WithItem { range: 80..83, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 80..83, id: Name("foo"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 85..93, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 85..88, id: Name("bar"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 92..93, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 96..99, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 96..99, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 100..125, is_async: false, items: [ WithItem { range: 106..114, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 106..109, id: Name("foo"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 113..114, id: Name("x"), ctx: Store, }, ), ), }, WithItem { range: 116..119, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 116..119, id: Name("bar"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 122..125, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 122..125, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@parenthesized_kwarg_py37.py.snap000064400000000000000000000046441046102023000326430ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_kwarg_py37.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..52, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..51, value: Call( ExprCall { node_index: NodeIndex(None), range: 43..51, func: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 44..51, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 45..50, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 46..47, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 1, ), }, ), }, ], }, }, ), }, ), ], }, ) ``` valid_syntax@parenthesized_named_expr_index_py38.py.snap000064400000000000000000000043401046102023000350330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_named_expr_index_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..55, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..54, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 43..54, value: Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("lst"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 48..52, target: Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@parenthesized_named_expr_py38.py.snap000064400000000000000000000156171046102023000336550ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_named_expr_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..59, value: Set( ExprSet { node_index: NodeIndex(None), range: 43..59, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 45..51, target: Name( ExprName { node_index: NodeIndex(None), range: 45..46, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 50..51, value: Int( 1, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 54..55, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 57..58, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..91, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 60..91, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 62..71, target: Name( ExprName { node_index: NodeIndex(None), range: 62..66, id: Name("last"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("x"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 73..90, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 82..90, func: Name( ExprName { node_index: NodeIndex(None), range: 82..87, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 87..90, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 88..89, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@parenthesized_star_index_py310.py.snap000064400000000000000000000241701046102023000337360ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_star_index_py310.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..94, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 44..93, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 44..89, value: Name( ExprName { node_index: NodeIndex(None), range: 44..47, id: Name("out"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 48..88, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 49..81, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 50..81, elt: Call( ExprCall { node_index: NodeIndex(None), range: 51..62, func: Name( ExprName { node_index: NodeIndex(None), range: 51..56, id: Name("slice"), ctx: Load, }, ), arguments: Arguments { range: 56..62, node_index: NodeIndex(None), args: [ NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 57..61, }, ), ], keywords: [], }, }, ), generators: [ Comprehension { range: 63..80, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("_"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 72..80, func: Name( ExprName { node_index: NodeIndex(None), range: 72..77, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 77..80, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 78..79, value: Int( 2, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 83..87, value: Name( ExprName { node_index: NodeIndex(None), range: 84..87, id: Name("ind"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 92..93, value: Int( 1, ), }, ), }, ), ], }, ) ``` valid_syntax@pep701_f_string_py311.py.snap000064400000000000000000001764011046102023000315660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/pep701_f_string_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..415, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..72, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..72, value: FStringValue { inner: Single( FString( FString { range: 44..72, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 46..52, node_index: NodeIndex(None), value: "outer ", }, ), Interpolation( InterpolatedElement { range: 52..71, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 53..70, value: StringLiteralValue { inner: Single( StringLiteral { range: 53..70, node_index: NodeIndex(None), value: "# not a comment", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 73..106, value: FString( ExprFString { node_index: NodeIndex(None), range: 73..106, value: FStringValue { inner: Single( FString( FString { range: 73..106, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 75..81, node_index: NodeIndex(None), value: "outer ", }, ), Interpolation( InterpolatedElement { range: 81..105, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("x"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 84..104, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 84..103, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 85..102, value: StringLiteralValue { inner: Single( StringLiteral { range: 85..102, node_index: NodeIndex(None), value: "# not a comment", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 103..104, node_index: NodeIndex(None), value: " ", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 107..147, value: FString( ExprFString { node_index: NodeIndex(None), range: 107..147, value: FStringValue { inner: Single( FString( FString { range: 107..147, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 111..144, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 112..143, value: FStringValue { inner: Single( FString( FString { range: 112..143, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 116..140, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 117..139, value: FStringValue { inner: Single( FString( FString { range: 117..139, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 119..138, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 120..137, value: StringLiteralValue { inner: Single( StringLiteral { range: 120..137, node_index: NodeIndex(None), value: "# not a comment", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..230, value: FString( ExprFString { node_index: NodeIndex(None), range: 148..230, value: FStringValue { inner: Single( FString( FString { range: 148..230, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 152..208, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 153..207, value: FStringValue { inner: Single( FString( FString { range: 153..207, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 157..177, node_index: NodeIndex(None), value: "# before expression ", }, ), Interpolation( InterpolatedElement { range: 177..204, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 178..203, value: FStringValue { inner: Single( FString( FString { range: 178..203, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 180..185, node_index: NodeIndex(None), value: "# aro", }, ), Interpolation( InterpolatedElement { range: 185..197, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 186..196, value: FStringValue { inner: Single( FString( FString { range: 186..196, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 188..189, node_index: NodeIndex(None), value: "#", }, ), Interpolation( InterpolatedElement { range: 189..194, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 190..193, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 190..191, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 192..193, value: Int( 1, ), }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 194..195, node_index: NodeIndex(None), value: "#", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 197..202, node_index: NodeIndex(None), value: "und #", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 208..227, node_index: NodeIndex(None), value: " # after expression", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 231..247, value: FString( ExprFString { node_index: NodeIndex(None), range: 231..247, value: FStringValue { inner: Single( FString( FString { range: 231..247, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 235..244, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 248..280, value: FString( ExprFString { node_index: NodeIndex(None), range: 248..280, value: FStringValue { inner: Single( FString( FString { range: 248..280, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 250..271, node_index: NodeIndex(None), value: "escape outside of \t ", }, ), Interpolation( InterpolatedElement { range: 271..277, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 272..276, id: Name("expr"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 277..279, node_index: NodeIndex(None), value: "\n", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 281..294, value: FString( ExprFString { node_index: NodeIndex(None), range: 281..294, value: FStringValue { inner: Single( FString( FString { range: 281..294, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 283..293, node_index: NodeIndex(None), value: "test\"abcd", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 295..306, value: FString( ExprFString { node_index: NodeIndex(None), range: 295..306, value: FStringValue { inner: Single( FString( FString { range: 295..306, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 297..305, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 298..299, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 300..304, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 300..304, node_index: NodeIndex(None), value: "d", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 347..359, value: FString( ExprFString { node_index: NodeIndex(None), range: 347..359, value: FStringValue { inner: Single( FString( FString { range: 347..359, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 349..358, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 350..351, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 352..357, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 352..357, node_index: NodeIndex(None), value: "\"d\"", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` valid_syntax@pep701_f_string_py312.py.snap000064400000000000000000002060041046102023000315600ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/pep701_f_string_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..416, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..74, value: FString( ExprFString { node_index: NodeIndex(None), range: 44..74, value: FStringValue { inner: Single( FString( FString { range: 44..74, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 46..58, node_index: NodeIndex(None), value: "Magic wand: ", }, ), Interpolation( InterpolatedElement { range: 58..73, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 60..71, value: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 64..70, value: StringLiteralValue { inner: Single( StringLiteral { range: 64..70, node_index: NodeIndex(None), value: "wand", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..112, value: FString( ExprFString { node_index: NodeIndex(None), range: 95..112, value: FStringValue { inner: Single( FString( FString { range: 95..112, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 97..111, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 98..110, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 98..107, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 98..102, value: StringLiteralValue { inner: Single( StringLiteral { range: 98..102, node_index: NodeIndex(None), value: "\n", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("join"), range: 103..107, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 107..110, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("a"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..220, value: FString( ExprFString { node_index: NodeIndex(None), range: 148..220, value: FStringValue { inner: Single( FString( FString { range: 148..220, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 152..169, node_index: NodeIndex(None), value: "A complex trick: ", }, ), Interpolation( InterpolatedElement { range: 169..217, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 175..185, value: Name( ExprName { node_index: NodeIndex(None), range: 175..178, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 179..184, value: StringLiteralValue { inner: Single( StringLiteral { range: 179..184, node_index: NodeIndex(None), value: "bag", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 221..254, value: FString( ExprFString { node_index: NodeIndex(None), range: 221..254, value: FStringValue { inner: Single( FString( FString { range: 221..254, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 223..253, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 224..252, value: FStringValue { inner: Single( FString( FString { range: 224..252, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 226..251, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 227..250, value: FStringValue { inner: Single( FString( FString { range: 227..250, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 229..249, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 230..248, value: FStringValue { inner: Single( FString( FString { range: 230..248, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 232..247, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 233..246, value: FStringValue { inner: Single( FString( FString { range: 233..246, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 235..245, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 236..244, value: FStringValue { inner: Single( FString( FString { range: 236..244, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 238..243, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 239..242, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..240, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 1, ), }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 276..310, value: FString( ExprFString { node_index: NodeIndex(None), range: 276..310, value: FStringValue { inner: Single( FString( FString { range: 276..310, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 278..303, node_index: NodeIndex(None), expression: FString( ExprFString { node_index: NodeIndex(None), range: 279..302, value: FStringValue { inner: Single( FString( FString { range: 279..302, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 283..293, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 284..292, value: StringLiteralValue { inner: Single( StringLiteral { range: 284..292, node_index: NodeIndex(None), value: "nested", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 293..299, node_index: NodeIndex(None), value: " inner", }, ), ], flags: FStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 303..309, node_index: NodeIndex(None), value: " outer", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 336..348, value: FString( ExprFString { node_index: NodeIndex(None), range: 336..348, value: FStringValue { inner: Single( FString( FString { range: 336..348, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 338..347, node_index: NodeIndex(None), expression: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 344..345, value: Int( 1, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 349..372, value: FString( ExprFString { node_index: NodeIndex(None), range: 349..372, value: FStringValue { inner: Single( FString( FString { range: 349..372, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 351..356, node_index: NodeIndex(None), value: "test ", }, ), Interpolation( InterpolatedElement { range: 356..366, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 357..358, id: Name("a"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 366..371, node_index: NodeIndex(None), value: " more", }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), ], }, ) ``` valid_syntax@pep750_t_string_py314.py.snap000064400000000000000000001636611046102023000316170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/pep750_t_string_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..403, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..74, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..74, value: TStringValue { inner: Single( TString { range: 44..74, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 46..58, node_index: NodeIndex(None), value: "Magic wand: ", }, ), Interpolation( InterpolatedElement { range: 58..73, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 60..71, value: Name( ExprName { node_index: NodeIndex(None), range: 60..63, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 64..70, value: StringLiteralValue { inner: Single( StringLiteral { range: 64..70, node_index: NodeIndex(None), value: "wand", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 95..112, value: TString( ExprTString { node_index: NodeIndex(None), range: 95..112, value: TStringValue { inner: Single( TString { range: 95..112, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 97..111, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 98..110, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 98..107, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 98..102, value: StringLiteralValue { inner: Single( StringLiteral { range: 98..102, node_index: NodeIndex(None), value: "\n", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("join"), range: 103..107, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 107..110, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("a"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..220, value: TString( ExprTString { node_index: NodeIndex(None), range: 148..220, value: TStringValue { inner: Single( TString { range: 148..220, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 152..169, node_index: NodeIndex(None), value: "A complex trick: ", }, ), Interpolation( InterpolatedElement { range: 169..217, node_index: NodeIndex(None), expression: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 175..185, value: Name( ExprName { node_index: NodeIndex(None), range: 175..178, id: Name("bag"), ctx: Load, }, ), slice: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 179..184, value: StringLiteralValue { inner: Single( StringLiteral { range: 179..184, node_index: NodeIndex(None), value: "bag", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 221..254, value: TString( ExprTString { node_index: NodeIndex(None), range: 221..254, value: TStringValue { inner: Single( TString { range: 221..254, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 223..253, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 224..252, value: TStringValue { inner: Single( TString { range: 224..252, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 226..251, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 227..250, value: TStringValue { inner: Single( TString { range: 227..250, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 229..249, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 230..248, value: TStringValue { inner: Single( TString { range: 230..248, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 232..247, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 233..246, value: TStringValue { inner: Single( TString { range: 233..246, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 235..245, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 236..244, value: TStringValue { inner: Single( TString { range: 236..244, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 238..243, node_index: NodeIndex(None), expression: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 239..242, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..240, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 241..242, value: Int( 1, ), }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 276..310, value: TString( ExprTString { node_index: NodeIndex(None), range: 276..310, value: TStringValue { inner: Single( TString { range: 276..310, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 278..303, node_index: NodeIndex(None), expression: TString( ExprTString { node_index: NodeIndex(None), range: 279..302, value: TStringValue { inner: Single( TString { range: 279..302, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 283..293, node_index: NodeIndex(None), expression: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 284..292, value: StringLiteralValue { inner: Single( StringLiteral { range: 284..292, node_index: NodeIndex(None), value: "nested", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 293..299, node_index: NodeIndex(None), value: " inner", }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 303..309, node_index: NodeIndex(None), value: " outer", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 336..359, value: TString( ExprTString { node_index: NodeIndex(None), range: 336..359, value: TStringValue { inner: Single( TString { range: 336..359, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 338..343, node_index: NodeIndex(None), value: "test ", }, ), Interpolation( InterpolatedElement { range: 343..353, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 344..345, id: Name("a"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 353..358, node_index: NodeIndex(None), value: " more", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` valid_syntax@pep_798_unpacking_comprehensions_py315.py.snap000064400000000000000000000542651046102023000352340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/pep_798_unpacking_comprehensions_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..215, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..59, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 44..59, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 45..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 48..58, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..75, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 60..75, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 61..63, value: Name( ExprName { node_index: NodeIndex(None), range: 62..63, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 64..74, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 76..92, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 76..92, key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 79..80, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 81..91, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 85..86, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 93..108, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 93..108, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 97..107, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 101..102, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 109..125, value: Call( ExprCall { node_index: NodeIndex(None), range: 109..125, func: Name( ExprName { node_index: NodeIndex(None), range: 109..110, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 110..125, node_index: NodeIndex(None), args: [ Generator( ExprGenerator { node_index: NodeIndex(None), range: 111..124, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 111..113, value: Name( ExprName { node_index: NodeIndex(None), range: 112..113, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 114..124, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 118..119, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 123..124, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: false, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 126..147, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 126..147, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 127..129, value: Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 130..146, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 140..141, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 145..146, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..169, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 148..169, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 149..151, value: Name( ExprName { node_index: NodeIndex(None), range: 150..151, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 152..168, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 162..163, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 167..168, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 170..192, value: DictComp( ExprDictComp { node_index: NodeIndex(None), range: 170..192, key: None, value: Name( ExprName { node_index: NodeIndex(None), range: 173..174, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 175..191, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 185..186, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: true, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 193..214, value: Generator( ExprGenerator { node_index: NodeIndex(None), range: 193..214, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 194..196, value: Name( ExprName { node_index: NodeIndex(None), range: 195..196, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 197..213, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 207..208, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 212..213, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: true, }, ], parenthesized: true, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@pos_only_py38.py.snap000064400000000000000000000047501046102023000305230ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/pos_only_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..62, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 43..61, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 47..50, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 50..56, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 51..52, node_index: NodeIndex(None), parameter: Parameter { range: 51..52, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 51..52, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@read_from_debug.py.snap000064400000000000000000000042701046102023000310770ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/read_from_debug.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..32, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..17, test: Name( ExprName { node_index: NodeIndex(None), range: 3..12, id: Name("__debug__"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 14..17, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 14..17, }, ), }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 18..31, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("x"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 22..31, id: Name("__debug__"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@simple_stmts_in_block.py.snap000064400000000000000000000111511046102023000322730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/simple_stmts_in_block.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..84, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..13, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 3..7, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 9..13, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 14..27, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 17..21, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 23..27, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 29..52, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 32..36, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 38..42, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 44..52, }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 53..76, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 56..60, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 62..66, }, ), Continue( StmtContinue { node_index: NodeIndex(None), range: 68..76, }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 78..83, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 78..79, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 1, ), }, ), }, ), ], }, ) ``` valid_syntax@simple_stmts_with_semicolons.py.snap000064400000000000000000000065571046102023000337370ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/simple_stmts_with_semicolons.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..51, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 0..6, value: None, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 8..16, names: [ Alias { range: 15..16, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 15..16, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 18..33, module: Some( Identifier { id: Name("x"), range: 23..24, node_index: NodeIndex(None), }, ), names: [ Alias { range: 32..33, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 32..33, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 35..36, value: Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("z"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 38..50, name: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("T"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 47..50, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@single_parenthesized_item_context_manager_py38.py.snap000064400000000000000000000176111046102023000372640ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/single_parenthesized_item_context_manager_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ With( StmtWith { node_index: NodeIndex(None), range: 43..80, is_async: false, items: [ WithItem { range: 48..75, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 52..67, func: Name( ExprName { node_index: NodeIndex(None), range: 52..56, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 56..67, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 57..66, value: StringLiteralValue { inner: Single( StringLiteral { range: 57..66, node_index: NodeIndex(None), value: "foo.txt", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 72..75, id: Name("foo"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 77..80, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 77..80, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 81..111, is_async: false, items: [ WithItem { range: 90..105, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 90..105, func: Name( ExprName { node_index: NodeIndex(None), range: 90..94, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 94..105, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 95..104, value: StringLiteralValue { inner: Single( StringLiteral { range: 95..104, node_index: NodeIndex(None), value: "foo.txt", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 108..111, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 108..111, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@single_star_in_tuple.py.snap000064400000000000000000000253731046102023000321340ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/single_star_in_tuple.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..84, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..20, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..20, value: Yield( ExprYield { node_index: NodeIndex(None), range: 9..20, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 15..20, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 16..18, value: Name( ExprName { node_index: NodeIndex(None), range: 17..18, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 21..42, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 25..26, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 26..28, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 30..42, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 37..42, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 38..40, value: Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), ], }, ), For( StmtFor { node_index: NodeIndex(None), range: 43..62, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("_"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 52..57, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 53..55, value: Name( ExprName { node_index: NodeIndex(None), range: 54..55, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 59..62, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 59..62, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 63..83, is_async: false, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 67..72, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 68..70, value: Name( ExprName { node_index: NodeIndex(None), range: 69..70, id: Name("x"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 76..78, id: Name("xs"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 80..83, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 80..83, }, ), }, ), ], orelse: [], }, ), ], }, ) ``` valid_syntax@single_starred_assignment_target.py.snap000064400000000000000000000157641046102023000345310ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/single_starred_assignment_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..36, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..12, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 0..5, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1..3, value: Name( ExprName { node_index: NodeIndex(None), range: 2..3, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 8..12, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 13..23, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 13..16, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 13..15, value: Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 19..23, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 20..21, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 24..35, targets: [ List( ExprList { node_index: NodeIndex(None), range: 24..28, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 25..27, value: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("a"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 31..35, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 32..33, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@star_index_py311.py.snap000064400000000000000000000474131046102023000310760ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/star_index_py311.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..293, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..55, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 44..55, value: Name( ExprName { node_index: NodeIndex(None), range: 44..47, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 48..54, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 48..54, value: Name( ExprName { node_index: NodeIndex(None), range: 49..54, id: Name("index"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 72..112, decorator_list: [], name: Identifier { id: Name("Array"), range: 78..83, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 83..107, node_index: NodeIndex(None), args: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 84..106, value: Name( ExprName { node_index: NodeIndex(None), range: 84..91, id: Name("Generic"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 92..105, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 92..97, id: Name("DType"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 99..105, value: Name( ExprName { node_index: NodeIndex(None), range: 100..105, id: Name("Shape"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 109..112, }, ), }, ), ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 148..161, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 148..161, value: Name( ExprName { node_index: NodeIndex(None), range: 148..151, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 152..160, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 152..153, id: Name("a"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 155..157, value: Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 159..160, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 185..198, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 185..198, value: Name( ExprName { node_index: NodeIndex(None), range: 185..188, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 189..197, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 192..193, id: Name("b"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 195..197, value: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("c"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 222..233, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 222..233, value: Name( ExprName { node_index: NodeIndex(None), range: 222..225, id: Name("lst"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 226..232, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 226..228, value: Name( ExprName { node_index: NodeIndex(None), range: 227..228, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 230..232, value: Name( ExprName { node_index: NodeIndex(None), range: 231..232, id: Name("b"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 254..271, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 254..271, value: Name( ExprName { node_index: NodeIndex(None), range: 254..259, id: Name("array"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 260..270, elts: [ Slice( ExprSlice { node_index: NodeIndex(None), range: 260..263, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 260..261, value: Int( 3, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 262..263, value: Int( 5, ), }, ), ), step: None, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 265..270, value: Name( ExprName { node_index: NodeIndex(None), range: 266..270, id: Name("idxs"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@starred_comprehension_target.py.snap000064400000000000000000000065331046102023000336630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/starred_comprehension_target.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..31, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 0..30, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 0..30, elt: Name( ExprName { node_index: NodeIndex(None), range: 1..5, id: Name("item"), ctx: Load, }, ), generators: [ Comprehension { range: 6..29, node_index: NodeIndex(None), target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 10..19, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 11..17, value: Name( ExprName { node_index: NodeIndex(None), range: 12..17, id: Name("items"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 23..29, id: Name("source"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@starred_list_comp_py315.py.snap000064400000000000000000000132171046102023000323730ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/starred_list_comp_py315.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..95, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..59, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 44..59, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 45..47, value: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 48..58, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 52..53, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("y"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 60..94, value: ListComp( ExprListComp { node_index: NodeIndex(None), range: 60..94, elt: Starred( ExprStarred { node_index: NodeIndex(None), range: 61..73, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 62..73, value: Name( ExprName { node_index: NodeIndex(None), range: 62..68, id: Name("factor"), ctx: Load, }, ), attr: Identifier { id: Name("dims"), range: 69..73, node_index: NodeIndex(None), }, ctx: Load, }, ), ctx: Load, }, ), generators: [ Comprehension { range: 74..93, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 78..84, id: Name("factor"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 88..93, id: Name("bases"), ctx: Load, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@statement__ambiguous_lpar_with_items.py.snap000064400000000000000000006660251046102023000354200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/ambiguous_lpar_with_items.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..3620, body: [ With( StmtWith { node_index: NodeIndex(None), range: 588..604, is_async: false, items: [ WithItem { range: 594..598, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 594..598, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 601..604, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 601..604, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 605..622, is_async: false, items: [ WithItem { range: 611..615, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 611..615, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 619..622, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 619..622, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 648..668, is_async: false, items: [ WithItem { range: 654..662, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 656..660, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 665..668, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 665..668, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 669..693, is_async: false, items: [ WithItem { range: 675..680, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 675..680, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 682..687, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 682..687, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 690..693, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 690..693, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 694..719, is_async: false, items: [ WithItem { range: 700..705, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 700..705, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 707..712, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 707..712, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 716..719, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 716..719, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 745..794, is_async: false, items: [ WithItem { range: 751..758, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 752..757, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 760..767, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 761..766, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 769..779, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 769..774, id: Name("item3"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 778..779, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 781..788, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 782..787, id: Name("item4"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 791..794, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 791..794, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 795..828, is_async: false, items: [ WithItem { range: 801..815, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 801..815, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 802..807, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 809..814, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 817..822, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 817..822, id: Name("item3"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 825..828, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 825..828, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 829..852, is_async: false, items: [ WithItem { range: 835..846, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 835..841, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 836..837, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 839..840, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 845..846, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 849..852, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 849..852, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 853..889, is_async: false, items: [ WithItem { range: 859..870, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 859..864, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 868..870, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 872..883, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 872..877, id: Name("item2"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 881..883, id: Name("f2"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 886..889, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 886..889, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 890..927, is_async: false, items: [ WithItem { range: 896..907, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 896..901, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 905..907, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 909..920, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 909..914, id: Name("item2"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 918..920, id: Name("f2"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 924..927, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 924..927, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 953..976, is_async: false, items: [ WithItem { range: 959..969, node_index: NodeIndex(None), context_expr: Compare( ExprCompare { node_index: NodeIndex(None), range: 959..969, left: Name( ExprName { node_index: NodeIndex(None), range: 959..963, id: Name("item"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 967..969, value: Int( 10, ), }, ), ], }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 973..976, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 973..976, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 977..1001, is_async: false, items: [ WithItem { range: 983..995, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 984..994, target: Name( ExprName { node_index: NodeIndex(None), range: 984..988, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 992..994, value: Int( 10, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 998..1001, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 998..1001, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1002..1027, is_async: false, items: [ WithItem { range: 1008..1021, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1008..1021, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 1009..1019, target: Name( ExprName { node_index: NodeIndex(None), range: 1009..1013, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1017..1019, value: Int( 10, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1024..1027, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1024..1027, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1028..1048, is_async: false, items: [ WithItem { range: 1034..1042, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1034..1042, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1035..1040, value: Name( ExprName { node_index: NodeIndex(None), range: 1036..1040, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1045..1048, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1045..1048, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1049..1081, is_async: false, items: [ WithItem { range: 1055..1068, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1056..1067, target: Name( ExprName { node_index: NodeIndex(None), range: 1056..1061, id: Name("item1"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1065..1067, value: Int( 10, ), }, ), }, ), optional_vars: None, }, WithItem { range: 1070..1075, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1070..1075, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1078..1081, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1078..1081, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1082..1119, is_async: false, items: [ WithItem { range: 1088..1098, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1088..1093, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1097..1098, id: Name("f"), ctx: Store, }, ), ), }, WithItem { range: 1100..1113, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1101..1112, target: Name( ExprName { node_index: NodeIndex(None), range: 1101..1106, id: Name("item2"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1110..1112, value: Int( 10, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1116..1119, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1116..1119, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1120..1137, is_async: false, items: [ WithItem { range: 1126..1131, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1126..1131, func: Name( ExprName { node_index: NodeIndex(None), range: 1126..1129, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 1129..1131, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1134..1137, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1134..1137, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1138..1156, is_async: false, items: [ WithItem { range: 1144..1149, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1144..1149, func: Name( ExprName { node_index: NodeIndex(None), range: 1144..1147, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 1147..1149, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1153..1156, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1153..1156, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1157..1179, is_async: false, items: [ WithItem { range: 1163..1173, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1163..1168, func: Name( ExprName { node_index: NodeIndex(None), range: 1163..1166, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 1166..1168, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1172..1173, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1176..1179, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1176..1179, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1180..1207, is_async: false, items: [ WithItem { range: 1186..1201, node_index: NodeIndex(None), context_expr: FString( ExprFString { node_index: NodeIndex(None), range: 1186..1201, value: FStringValue { inner: Single( FString( FString { range: 1186..1201, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 1188..1200, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 1189..1193, id: Name("item"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: Some( InterpolatedStringFormatSpec { range: 1195..1199, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 1195..1199, node_index: NodeIndex(None), value: "= 42", }, ), ], }, ), }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1204..1207, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1204..1207, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1208..1237, is_async: false, items: [ WithItem { range: 1214..1231, node_index: NodeIndex(None), context_expr: FString( ExprFString { node_index: NodeIndex(None), range: 1214..1231, value: FStringValue { inner: Single( FString( FString { range: 1214..1231, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 1216..1230, node_index: NodeIndex(None), expression: Named( ExprNamed { node_index: NodeIndex(None), range: 1218..1228, target: Name( ExprName { node_index: NodeIndex(None), range: 1218..1222, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1226..1228, value: Int( 42, ), }, ), }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1234..1237, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1234..1237, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1238..1278, is_async: false, items: [ WithItem { range: 1244..1266, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 1244..1266, elt: Name( ExprName { node_index: NodeIndex(None), range: 1245..1246, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 1247..1265, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 1251..1252, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 1256..1265, func: Name( ExprName { node_index: NodeIndex(None), range: 1256..1261, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 1261..1265, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1262..1264, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 1268..1272, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1268..1272, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1275..1278, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1275..1278, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1279..1319, is_async: false, items: [ WithItem { range: 1285..1289, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1285..1289, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 1291..1313, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 1291..1313, elt: Name( ExprName { node_index: NodeIndex(None), range: 1292..1293, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 1294..1312, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 1298..1299, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 1303..1312, func: Name( ExprName { node_index: NodeIndex(None), range: 1303..1308, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 1308..1312, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1309..1311, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1316..1319, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1316..1319, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1320..1366, is_async: false, items: [ WithItem { range: 1326..1330, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1326..1330, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 1332..1354, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 1332..1354, elt: Name( ExprName { node_index: NodeIndex(None), range: 1333..1334, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 1335..1353, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 1339..1340, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 1344..1353, func: Name( ExprName { node_index: NodeIndex(None), range: 1344..1349, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 1349..1353, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1350..1352, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 1356..1360, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1356..1360, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1363..1366, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1363..1366, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1367..1388, is_async: false, items: [ WithItem { range: 1373..1382, node_index: NodeIndex(None), context_expr: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1373..1382, value: Name( ExprName { node_index: NodeIndex(None), range: 1373..1377, id: Name("data"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 1378..1381, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1378..1379, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1380..1381, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1385..1388, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1385..1388, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1389..1415, is_async: false, items: [ WithItem { range: 1395..1409, node_index: NodeIndex(None), context_expr: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1395..1404, value: Name( ExprName { node_index: NodeIndex(None), range: 1395..1399, id: Name("data"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 1400..1403, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1400..1401, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1402..1403, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1408..1409, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1412..1415, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1412..1415, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1416..1450, is_async: false, items: [ WithItem { range: 1422..1444, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 1422..1439, elt: Name( ExprName { node_index: NodeIndex(None), range: 1423..1424, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 1425..1438, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 1429..1430, id: Name("x"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 1434..1438, id: Name("iter"), ctx: Load, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1443..1444, id: Name("y"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1447..1450, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1447..1450, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1663..1684, is_async: false, items: [ WithItem { range: 1668..1679, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1669..1673, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1678..1679, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1681..1684, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1681..1684, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1685..1707, is_async: false, items: [ WithItem { range: 1690..1702, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1691..1701, target: Name( ExprName { node_index: NodeIndex(None), range: 1691..1695, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1699..1701, value: Int( 10, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1704..1707, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1704..1707, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1708..1735, is_async: false, items: [ WithItem { range: 1713..1730, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1714..1724, target: Name( ExprName { node_index: NodeIndex(None), range: 1714..1718, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1722..1724, value: Int( 10, ), }, ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1729..1730, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1732..1735, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1732..1735, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1736..1762, is_async: false, items: [ WithItem { range: 1741..1757, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1744..1753, target: Name( ExprName { node_index: NodeIndex(None), range: 1744..1748, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1752..1753, value: Int( 1, ), }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1759..1762, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1759..1762, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1763..1793, is_async: false, items: [ WithItem { range: 1768..1781, node_index: NodeIndex(None), context_expr: Named( ExprNamed { node_index: NodeIndex(None), range: 1769..1780, target: Name( ExprName { node_index: NodeIndex(None), range: 1769..1774, id: Name("item1"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1778..1780, value: Int( 42, ), }, ), }, ), optional_vars: None, }, WithItem { range: 1783..1788, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 1783..1788, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1790..1793, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1790..1793, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1794..1828, is_async: false, items: [ WithItem { range: 1799..1823, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1799..1823, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1799..1821, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1800..1815, left: Name( ExprName { node_index: NodeIndex(None), range: 1800..1804, id: Name("root"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1807..1815, id: Name("filename"), ctx: Load, }, ), }, ), attr: Identifier { id: Name("read"), range: 1817..1821, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 1821..1823, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1825..1828, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1825..1828, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1851..1890, is_async: false, items: [ WithItem { range: 1856..1885, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1856..1880, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1856..1878, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1857..1872, left: Name( ExprName { node_index: NodeIndex(None), range: 1857..1861, id: Name("root"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1864..1872, id: Name("filename"), ctx: Load, }, ), }, ), attr: Identifier { id: Name("read"), range: 1874..1878, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 1878..1880, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1884..1885, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1887..1890, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1887..1890, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1913..1930, is_async: false, items: [ WithItem { range: 1918..1925, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1918..1925, func: Name( ExprName { node_index: NodeIndex(None), range: 1919..1922, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 1923..1925, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1927..1930, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1927..1930, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1953..1975, is_async: false, items: [ WithItem { range: 1958..1970, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 1958..1965, func: Name( ExprName { node_index: NodeIndex(None), range: 1959..1962, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 1963..1965, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 1969..1970, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1972..1975, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1972..1975, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 1998..2020, is_async: false, items: [ WithItem { range: 2003..2015, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 2004..2009, func: Name( ExprName { node_index: NodeIndex(None), range: 2004..2007, id: Name("foo"), ctx: Load, }, ), arguments: Arguments { range: 2007..2009, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2014..2015, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2017..2020, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2017..2020, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2021..2047, is_async: false, items: [ WithItem { range: 2026..2042, node_index: NodeIndex(None), context_expr: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 2027..2036, value: Name( ExprName { node_index: NodeIndex(None), range: 2027..2031, id: Name("data"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 2032..2035, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2032..2033, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2034..2035, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2041..2042, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2044..2047, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2044..2047, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2048..2070, is_async: false, items: [ WithItem { range: 2053..2065, node_index: NodeIndex(None), context_expr: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 2053..2065, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2053..2062, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2054..2055, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2057..2058, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2060..2061, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2063..2064, value: Int( 0, ), }, ), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2067..2070, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2067..2070, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2093..2120, is_async: false, items: [ WithItem { range: 2098..2115, node_index: NodeIndex(None), context_expr: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 2098..2110, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2098..2107, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2099..2100, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2102..2103, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2105..2106, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2108..2109, value: Int( 0, ), }, ), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2114..2115, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2117..2120, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2117..2120, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2143..2169, is_async: false, items: [ WithItem { range: 2148..2155, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 2149..2154, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 2157..2164, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 2158..2163, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2166..2169, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2166..2169, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2170..2210, is_async: false, items: [ WithItem { range: 2175..2189, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 2176..2188, func: Name( ExprName { node_index: NodeIndex(None), range: 2176..2180, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 2180..2188, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2181..2187, value: StringLiteralValue { inner: Single( StringLiteral { range: 2181..2187, node_index: NodeIndex(None), value: "a.py", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), optional_vars: None, }, WithItem { range: 2191..2205, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 2192..2204, func: Name( ExprName { node_index: NodeIndex(None), range: 2192..2196, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 2196..2204, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2197..2203, value: StringLiteralValue { inner: Single( StringLiteral { range: 2197..2203, node_index: NodeIndex(None), value: "b.py", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2207..2210, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2207..2210, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2211..2230, is_async: false, items: [ WithItem { range: 2216..2225, node_index: NodeIndex(None), context_expr: Yield( ExprYield { node_index: NodeIndex(None), range: 2217..2224, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 2223..2224, id: Name("x"), ctx: Load, }, ), ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2227..2230, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2227..2230, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2231..2252, is_async: false, items: [ WithItem { range: 2237..2246, node_index: NodeIndex(None), context_expr: Yield( ExprYield { node_index: NodeIndex(None), range: 2238..2245, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 2244..2245, id: Name("x"), ctx: Load, }, ), ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2249..2252, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2249..2252, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2253..2277, is_async: false, items: [ WithItem { range: 2258..2272, node_index: NodeIndex(None), context_expr: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 2259..2271, value: Name( ExprName { node_index: NodeIndex(None), range: 2270..2271, id: Name("x"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2274..2277, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2274..2277, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2278..2304, is_async: false, items: [ WithItem { range: 2284..2298, node_index: NodeIndex(None), context_expr: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 2285..2297, value: Name( ExprName { node_index: NodeIndex(None), range: 2296..2297, id: Name("x"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2301..2304, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2301..2304, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2305..2329, is_async: false, items: [ WithItem { range: 2310..2324, node_index: NodeIndex(None), context_expr: Yield( ExprYield { node_index: NodeIndex(None), range: 2311..2318, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 2317..2318, id: Name("x"), ctx: Load, }, ), ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2323..2324, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2326..2329, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2326..2329, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2330..2355, is_async: false, items: [ WithItem { range: 2335..2350, node_index: NodeIndex(None), context_expr: Yield( ExprYield { node_index: NodeIndex(None), range: 2336..2344, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 2342..2344, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2342..2343, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2349..2350, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2352..2355, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2352..2355, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2741..2753, is_async: false, items: [ WithItem { range: 2746..2748, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2746..2748, elts: [], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2750..2753, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2750..2753, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2754..2771, is_async: false, items: [ WithItem { range: 2759..2766, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2759..2761, elts: [], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2765..2766, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2768..2771, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2768..2771, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2772..2795, is_async: false, items: [ WithItem { range: 2777..2790, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2777..2790, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 2778..2788, target: Name( ExprName { node_index: NodeIndex(None), range: 2778..2782, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2786..2788, value: Int( 42, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2792..2795, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2792..2795, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2796..2820, is_async: false, items: [ WithItem { range: 2801..2815, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2801..2815, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2802..2803, value: Int( 1, ), }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 2805..2814, target: Name( ExprName { node_index: NodeIndex(None), range: 2805..2809, id: Name("item"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2813..2814, value: Int( 2, ), }, ), }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2817..2820, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2817..2820, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2821..2851, is_async: false, items: [ WithItem { range: 2826..2846, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2826..2846, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 2827..2838, target: Name( ExprName { node_index: NodeIndex(None), range: 2827..2832, id: Name("item1"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2836..2838, value: Int( 10, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 2840..2845, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2848..2851, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2848..2851, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2852..2893, is_async: false, items: [ WithItem { range: 2857..2888, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2857..2883, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2858..2863, id: Name("item1"), ctx: Load, }, ), Named( ExprNamed { node_index: NodeIndex(None), range: 2865..2875, target: Name( ExprName { node_index: NodeIndex(None), range: 2865..2870, id: Name("item2"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2874..2875, value: Int( 2, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 2877..2882, id: Name("item3"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2887..2888, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2890..2893, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2890..2893, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2894..2916, is_async: false, items: [ WithItem { range: 2899..2911, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2899..2906, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2900..2904, id: Name("item"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2910..2911, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2913..2916, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2913..2916, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2917..2935, is_async: false, items: [ WithItem { range: 2922..2930, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2922..2930, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 2923..2928, value: Name( ExprName { node_index: NodeIndex(None), range: 2924..2928, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2932..2935, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2932..2935, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2936..2959, is_async: false, items: [ WithItem { range: 2941..2954, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2941..2949, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 2942..2947, value: Name( ExprName { node_index: NodeIndex(None), range: 2943..2947, id: Name("item"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2953..2954, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2956..2959, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2956..2959, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2960..2989, is_async: false, items: [ WithItem { range: 2965..2984, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2965..2979, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2966..2971, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 2973..2978, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 2983..2984, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2986..2989, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2986..2989, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 2990..3020, is_async: false, items: [ WithItem { range: 2995..3015, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2995..3010, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2996..3001, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3003..3008, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3014..3015, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3017..3020, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3017..3020, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3021..3052, is_async: false, items: [ WithItem { range: 3026..3040, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3026..3040, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3027..3032, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3034..3039, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 3042..3047, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 3042..3047, id: Name("item3"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3049..3052, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3049..3052, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3053..3091, is_async: false, items: [ WithItem { range: 3058..3086, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3058..3081, elts: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 3059..3073, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3060..3065, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3067..3072, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3075..3080, id: Name("item3"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3085..3086, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3088..3091, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3088..3091, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3092..3138, is_async: false, items: [ WithItem { range: 3097..3105, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3097..3105, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3098..3103, id: Name("item1"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 3107..3112, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 3107..3112, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 3114..3133, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3114..3128, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3115..3120, id: Name("item3"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3122..3127, id: Name("item4"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3132..3133, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3135..3138, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3135..3138, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3139..3182, is_async: false, items: [ WithItem { range: 3144..3164, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3144..3158, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3145..3150, id: Name("item1"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3152..3157, id: Name("item2"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3162..3164, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 3166..3177, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 3166..3171, id: Name("item3"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3175..3177, id: Name("f2"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3179..3182, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3179..3182, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3183..3208, is_async: false, items: [ WithItem { range: 3188..3203, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3188..3203, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3189..3194, id: Name("item1"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 3196..3202, value: Name( ExprName { node_index: NodeIndex(None), range: 3197..3202, id: Name("item2"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3205..3208, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3205..3208, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3209..3239, is_async: false, items: [ WithItem { range: 3214..3234, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3214..3229, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3215..3220, id: Name("item1"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 3222..3228, value: Name( ExprName { node_index: NodeIndex(None), range: 3223..3228, id: Name("item2"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 3233..3234, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3236..3239, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3236..3239, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3240..3271, is_async: false, items: [ WithItem { range: 3245..3266, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3245..3266, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 3246..3257, target: Name( ExprName { node_index: NodeIndex(None), range: 3246..3251, id: Name("item1"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3255..3257, value: Int( 10, ), }, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 3259..3265, value: Name( ExprName { node_index: NodeIndex(None), range: 3260..3265, id: Name("item2"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3268..3271, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3268..3271, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3272..3305, is_async: false, items: [ WithItem { range: 3277..3300, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3277..3300, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 3279..3290, target: Name( ExprName { node_index: NodeIndex(None), range: 3279..3284, id: Name("item1"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3288..3290, value: Int( 10, ), }, ), }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 3293..3299, value: Name( ExprName { node_index: NodeIndex(None), range: 3294..3299, id: Name("item2"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3302..3305, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3302..3305, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3510..3542, is_async: false, items: [ WithItem { range: 3515..3537, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 3515..3537, elt: Name( ExprName { node_index: NodeIndex(None), range: 3516..3517, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 3518..3536, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 3522..3523, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 3527..3536, func: Name( ExprName { node_index: NodeIndex(None), range: 3527..3532, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 3532..3536, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3533..3535, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3539..3542, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3539..3542, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3543..3581, is_async: false, items: [ WithItem { range: 3548..3576, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 3548..3576, elt: Name( ExprName { node_index: NodeIndex(None), range: 3549..3550, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 3551..3575, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 3561..3562, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 3566..3575, func: Name( ExprName { node_index: NodeIndex(None), range: 3566..3571, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 3571..3575, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3572..3574, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: true, }, ], parenthesized: true, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3578..3581, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3578..3581, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 3582..3620, is_async: false, items: [ WithItem { range: 3587..3609, node_index: NodeIndex(None), context_expr: Generator( ExprGenerator { node_index: NodeIndex(None), range: 3587..3609, elt: Name( ExprName { node_index: NodeIndex(None), range: 3588..3589, id: Name("x"), ctx: Load, }, ), generators: [ Comprehension { range: 3590..3608, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 3594..3595, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 3599..3608, func: Name( ExprName { node_index: NodeIndex(None), range: 3599..3604, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 3604..3608, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3605..3607, value: Int( 10, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], parenthesized: true, }, ), optional_vars: None, }, WithItem { range: 3611..3615, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 3611..3615, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3617..3620, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3617..3620, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@statement__annotated_assignment.py.snap000064400000000000000000000303551046102023000343470ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/annotated_assignment.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..103, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 0..6, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 3..6, id: Name("int"), ctx: Load, }, ), value: None, simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 7..17, target: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Store, }, ), annotation: Name( ExprName { node_index: NodeIndex(None), range: 10..13, id: Name("int"), ctx: Load, }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 16..17, value: Int( 1, ), }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 18..28, target: Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("x"), ctx: Store, }, ), annotation: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 23..28, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 23..24, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 27..28, value: Int( 2, ), }, ), }, ), value: None, simple: false, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 29..55, target: Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("x"), ctx: Store, }, ), annotation: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 32..48, left: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 32..42, value: Name( ExprName { node_index: NodeIndex(None), range: 32..37, id: Name("tuple"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 38..41, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 45..48, id: Name("int"), ctx: Load, }, ), }, ), value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 51..55, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 1, ), }, ), ], ctx: Load, parenthesized: true, }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 56..83, target: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Store, }, ), annotation: If( ExprIf { node_index: NodeIndex(None), range: 59..79, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 66..70, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 59..62, id: Name("int"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("str"), ctx: Load, }, ), }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 82..83, value: Int( 1, ), }, ), ), simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 84..102, target: Name( ExprName { node_index: NodeIndex(None), range: 84..85, id: Name("x"), ctx: Store, }, ), annotation: Lambda( ExprLambda { node_index: NodeIndex(None), range: 87..98, parameters: Some( Parameters { range: 94..95, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 94..95, node_index: NodeIndex(None), parameter: Parameter { range: 94..95, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 94..95, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 97..98, id: Name("y"), ctx: Load, }, ), }, ), value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 101..102, value: Int( 1, ), }, ), ), simple: true, }, ), ], }, ) ``` valid_syntax@statement__assert.py.snap000064400000000000000000000374101046102023000314420ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/assert.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..186, body: [ Assert( StmtAssert { node_index: NodeIndex(None), range: 0..12, test: Compare( ExprCompare { node_index: NodeIndex(None), range: 7..12, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 7..8, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 2, ), }, ), ], }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 13..26, test: Call( ExprCall { node_index: NodeIndex(None), range: 20..26, func: Name( ExprName { node_index: NodeIndex(None), range: 20..24, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 24..26, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 27..41, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 34..41, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 34..35, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 40..41, id: Name("b"), ctx: Load, }, ), ], }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 42..60, test: Lambda( ExprLambda { node_index: NodeIndex(None), range: 49..60, parameters: Some( Parameters { range: 56..57, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 56..57, node_index: NodeIndex(None), parameter: Parameter { range: 56..57, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 56..57, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("y"), ctx: Load, }, ), }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 61..75, test: Await( ExprAwait { node_index: NodeIndex(None), range: 68..75, value: Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("x"), ctx: Load, }, ), }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 76..99, test: If( ExprIf { node_index: NodeIndex(None), range: 83..99, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 88..92, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("y"), ctx: Load, }, ), }, ), msg: None, }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 101..118, test: Name( ExprName { node_index: NodeIndex(None), range: 108..109, id: Name("x"), ctx: Load, }, ), msg: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 111..118, value: StringLiteralValue { inner: Single( StringLiteral { range: 111..118, node_index: NodeIndex(None), value: "error", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 119..140, test: Name( ExprName { node_index: NodeIndex(None), range: 126..127, id: Name("x"), ctx: Load, }, ), msg: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 129..140, parameters: Some( Parameters { range: 136..137, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 136..137, node_index: NodeIndex(None), parameter: Parameter { range: 136..137, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 136..137, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 139..140, id: Name("y"), ctx: Load, }, ), }, ), ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 141..158, test: Name( ExprName { node_index: NodeIndex(None), range: 148..149, id: Name("x"), ctx: Load, }, ), msg: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 151..158, value: Name( ExprName { node_index: NodeIndex(None), range: 157..158, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), Assert( StmtAssert { node_index: NodeIndex(None), range: 159..185, test: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("x"), ctx: Load, }, ), msg: Some( If( ExprIf { node_index: NodeIndex(None), range: 169..185, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 174..178, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 184..185, id: Name("y"), ctx: Load, }, ), }, ), ), }, ), ], }, ) ``` valid_syntax@statement__assignment.py.snap000064400000000000000000001335201046102023000323100ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/assignment.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..729, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 0..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 4..13, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 8..9, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 11..12, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 15..33, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 15..21, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 16..17, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 19..20, id: Name("y"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 24..33, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 25..26, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 28..29, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 31..32, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 35..53, targets: [ List( ExprList { node_index: NodeIndex(None), range: 35..41, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("y"), ctx: Store, }, ), ], ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 44..53, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 48..49, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 55..70, targets: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 55..58, value: Name( ExprName { node_index: NodeIndex(None), range: 55..56, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("y"), range: 57..58, node_index: NodeIndex(None), }, ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 61..70, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 62..63, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 65..66, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 68..69, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 72..88, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 72..76, value: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 74..75, id: Name("y"), ctx: Load, }, ), ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 79..88, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 80..81, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..87, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 90..109, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 90..97, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("x"), ctx: Store, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 94..96, value: Name( ExprName { node_index: NodeIndex(None), range: 95..96, id: Name("y"), ctx: Store, }, ), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 100..109, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 101..102, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..105, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 107..108, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 259..280, targets: [ List( ExprList { node_index: NodeIndex(None), range: 259..268, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 260..261, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 263..264, id: Name("y"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 266..267, id: Name("z"), ctx: Store, }, ), ], ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 271..280, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 272..273, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 275..276, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 278..279, value: Int( 3, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 282..303, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 282..291, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 283..284, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 286..287, id: Name("y"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 289..290, id: Name("z"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 294..303, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 295..296, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 298..299, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 301..302, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 304..313, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 304..308, value: Name( ExprName { node_index: NodeIndex(None), range: 304..305, id: Name("x"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 306..307, value: Int( 0, ), }, ), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 311..313, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 410..419, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 410..414, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 410..411, value: Int( 5, ), }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 412..413, value: Int( 0, ), }, ), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 417..419, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 420..433, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 420..426, value: Name( ExprName { node_index: NodeIndex(None), range: 420..421, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 422..425, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 422..423, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 424..425, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 429..433, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 430..432, value: Int( 42, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 529..542, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 529..535, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 529..530, value: Int( 5, ), }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 531..534, lower: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 531..532, value: Int( 1, ), }, ), ), upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 533..534, value: Int( 2, ), }, ), ), step: None, }, ), ctx: Store, }, ), ], value: List( ExprList { node_index: NodeIndex(None), range: 538..542, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 539..541, value: Int( 42, ), }, ), ], ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 544..556, targets: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 544..551, value: Name( ExprName { node_index: NodeIndex(None), range: 544..547, id: Name("foo"), ctx: Load, }, ), attr: Identifier { id: Name("bar"), range: 548..551, node_index: NodeIndex(None), }, ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 554..556, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 658..670, targets: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 658..665, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 658..663, value: StringLiteralValue { inner: Single( StringLiteral { range: 658..663, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), attr: Identifier { id: Name("y"), range: 664..665, node_index: NodeIndex(None), }, ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 668..670, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 672..680, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 672..675, id: Name("foo"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 678..680, value: Int( 42, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 682..695, targets: [ List( ExprList { node_index: NodeIndex(None), range: 682..684, elts: [], ctx: Store, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 687..695, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 688..693, value: Name( ExprName { node_index: NodeIndex(None), range: 689..693, id: Name("data"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 696..709, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 696..698, elts: [], ctx: Store, parenthesized: true, }, ), ], value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 701..709, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 702..707, value: Name( ExprName { node_index: NodeIndex(None), range: 703..707, id: Name("data"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 710..719, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 710..714, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 710..711, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 713..714, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 717..719, id: Name("ab"), ctx: Load, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 720..729, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 720..721, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 724..725, id: Name("b"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 728..729, id: Name("c"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@statement__augmented_assignment.py.snap000064400000000000000000000511031046102023000343350ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/augmented_assignment.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..212, body: [ AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 0..6, target: Name( ExprName { node_index: NodeIndex(None), range: 0..1, id: Name("x"), ctx: Store, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5..6, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 7..23, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 7..10, value: Name( ExprName { node_index: NodeIndex(None), range: 7..8, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("y"), range: 9..10, node_index: NodeIndex(None), }, ctx: Store, }, ), op: Add, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 14..23, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 15..16, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 18..19, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 21..22, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 24..41, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 24..28, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 26..27, id: Name("y"), ctx: Load, }, ), ctx: Store, }, ), op: Add, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 32..41, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 33..34, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 36..37, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 39..40, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 86..92, target: Name( ExprName { node_index: NodeIndex(None), range: 86..87, id: Name("x"), ctx: Store, }, ), op: Add, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 91..92, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 93..99, target: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("x"), ctx: Store, }, ), op: Sub, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 98..99, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 100..106, target: Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("x"), ctx: Store, }, ), op: Mult, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 107..113, target: Name( ExprName { node_index: NodeIndex(None), range: 107..108, id: Name("x"), ctx: Store, }, ), op: Div, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 112..113, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 114..121, target: Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("x"), ctx: Store, }, ), op: FloorDiv, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 120..121, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 122..128, target: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("x"), ctx: Store, }, ), op: Mod, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 127..128, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 129..136, target: Name( ExprName { node_index: NodeIndex(None), range: 129..130, id: Name("x"), ctx: Store, }, ), op: Pow, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 135..136, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 137..143, target: Name( ExprName { node_index: NodeIndex(None), range: 137..138, id: Name("x"), ctx: Store, }, ), op: BitAnd, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 142..143, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 144..150, target: Name( ExprName { node_index: NodeIndex(None), range: 144..145, id: Name("x"), ctx: Store, }, ), op: BitOr, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 149..150, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 151..157, target: Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("x"), ctx: Store, }, ), op: BitXor, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 156..157, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 158..165, target: Name( ExprName { node_index: NodeIndex(None), range: 158..159, id: Name("x"), ctx: Store, }, ), op: LShift, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 164..165, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 166..173, target: Name( ExprName { node_index: NodeIndex(None), range: 166..167, id: Name("x"), ctx: Store, }, ), op: RShift, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 172..173, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 174..180, target: Name( ExprName { node_index: NodeIndex(None), range: 174..175, id: Name("x"), ctx: Store, }, ), op: MatMult, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 179..180, value: Int( 1, ), }, ), }, ), AugAssign( StmtAugAssign { node_index: NodeIndex(None), range: 190..212, target: Name( ExprName { node_index: NodeIndex(None), range: 190..191, id: Name("a"), ctx: Store, }, ), op: FloorDiv, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 196..212, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 197..202, left: Name( ExprName { node_index: NodeIndex(None), range: 197..198, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 201..202, id: Name("b"), ctx: Load, }, ), }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 206..212, left: Name( ExprName { node_index: NodeIndex(None), range: 206..207, id: Name("c"), ctx: Load, }, ), op: Pow, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 211..212, value: Int( 2, ), }, ), }, ), }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__class.py.snap000064400000000000000000002125661046102023000313340ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/class.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..1023, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..19, decorator_list: [], name: Identifier { id: Name("Test"), range: 6..10, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 16..19, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 16..19, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 22..80, decorator_list: [], name: Identifier { id: Name("Test"), range: 28..32, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 32..34, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..80, is_async: false, decorator_list: [], name: Identifier { id: Name("__init__"), range: 48..56, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 56..62, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 57..61, node_index: NodeIndex(None), parameter: Parameter { range: 57..61, node_index: NodeIndex(None), name: Identifier { id: Name("self"), range: 57..61, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 76..80, }, ), ], }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 83..116, decorator_list: [], name: Identifier { id: Name("Test"), range: 89..93, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 93..107, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 99..101, value: Name( ExprName { node_index: NodeIndex(None), range: 100..101, id: Name("A"), ctx: Load, }, ), ctx: Load, }, ), ], keywords: [ Keyword { range: 94..97, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("a"), range: 94..95, node_index: NodeIndex(None), }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 96..97, value: Int( 1, ), }, ), }, Keyword { range: 103..106, node_index: NodeIndex(None), arg: None, value: Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("k"), ctx: Load, }, ), }, ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 113..116, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 113..116, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 119..168, decorator_list: [], name: Identifier { id: Name("Test"), range: 125..129, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 135..168, is_async: false, decorator_list: [], name: Identifier { id: Name("method"), range: 139..145, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 145..147, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 157..168, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 157..161, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 157..158, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 164..168, id: Name("data"), ctx: Load, }, ), }, ), ], }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 171..289, decorator_list: [], name: Identifier { id: Name("Test"), range: 177..181, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 181..187, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 182..183, id: Name("A"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 185..186, id: Name("B"), ctx: Load, }, ), ], keywords: [], }, ), body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 193..225, is_async: false, decorator_list: [], name: Identifier { id: Name("__init__"), range: 197..205, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 205..211, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 206..210, node_index: NodeIndex(None), parameter: Parameter { range: 206..210, node_index: NodeIndex(None), name: Identifier { id: Name("self"), range: 206..210, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 221..225, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 231..289, is_async: false, decorator_list: [], name: Identifier { id: Name("method_with_default"), range: 235..254, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 254..275, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 255..259, node_index: NodeIndex(None), parameter: Parameter { range: 255..259, node_index: NodeIndex(None), name: Identifier { id: Name("self"), range: 255..259, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 261..274, node_index: NodeIndex(None), parameter: Parameter { range: 261..264, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 261..264, node_index: NodeIndex(None), }, annotation: None, }, default: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 265..274, value: StringLiteralValue { inner: Single( StringLiteral { range: 265..274, node_index: NodeIndex(None), value: "default", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 285..289, }, ), ], }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 331..351, decorator_list: [], name: Identifier { id: Name("Test"), range: 337..341, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 341..344, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 342..343, name: Identifier { id: Name("T"), range: 342..343, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 344..346, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 348..351, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 348..351, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 376..402, decorator_list: [], name: Identifier { id: Name("Test"), range: 382..386, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 386..395, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 387..394, name: Identifier { id: Name("T"), range: 387..388, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 391..394, id: Name("str"), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 395..397, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 399..402, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 399..402, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 425..450, decorator_list: [], name: Identifier { id: Name("Test"), range: 431..435, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 435..443, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 436..442, name: Identifier { id: Name("T"), range: 436..437, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 439..442, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), ], }, ), arguments: Some( Arguments { range: 443..445, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 447..450, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 447..450, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 485..522, decorator_list: [], name: Identifier { id: Name("Test"), range: 491..495, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 495..515, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 496..514, name: Identifier { id: Name("T"), range: 496..497, node_index: NodeIndex(None), }, bound: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 499..508, left: Name( ExprName { node_index: NodeIndex(None), range: 499..502, id: Name("int"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 505..508, id: Name("str"), ctx: Load, }, ), }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 511..514, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 515..517, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 519..522, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 519..522, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 551..585, decorator_list: [], name: Identifier { id: Name("Test"), range: 557..561, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 561..578, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 562..577, name: Identifier { id: Name("T"), range: 562..563, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 565..577, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 566..569, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 571..576, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), ], }, ), arguments: Some( Arguments { range: 578..580, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 582..585, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 582..585, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 606..629, decorator_list: [], name: Identifier { id: Name("Test"), range: 612..616, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 616..622, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 617..618, name: Identifier { id: Name("T"), range: 617..618, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 620..621, name: Identifier { id: Name("U"), range: 620..621, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 622..624, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 626..629, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 626..629, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 648..672, decorator_list: [], name: Identifier { id: Name("Test"), range: 654..658, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 658..665, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 659..660, name: Identifier { id: Name("T"), range: 659..660, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 662..663, name: Identifier { id: Name("U"), range: 662..663, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 665..667, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 669..672, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 669..672, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 689..711, decorator_list: [], name: Identifier { id: Name("Test"), range: 695..699, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 699..704, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 700..703, name: Identifier { id: Name("Ts"), range: 701..703, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 704..706, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 708..711, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 708..711, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 741..789, decorator_list: [], name: Identifier { id: Name("Test"), range: 747..751, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 751..782, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 752..781, name: Identifier { id: Name("Ts"), range: 753..755, node_index: NodeIndex(None), }, default: Some( Subscript( ExprSubscript { node_index: NodeIndex(None), range: 758..781, value: Name( ExprName { node_index: NodeIndex(None), range: 758..764, id: Name("Unpack"), ctx: Load, }, ), slice: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 765..780, value: Name( ExprName { node_index: NodeIndex(None), range: 765..770, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 771..779, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 771..774, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 776..779, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 782..784, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 786..789, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 786..789, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 827..868, decorator_list: [], name: Identifier { id: Name("Test"), range: 833..837, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 837..861, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 838..860, name: Identifier { id: Name("Ts"), range: 839..841, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 844..860, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 845..860, value: Name( ExprName { node_index: NodeIndex(None), range: 845..850, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 851..859, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 851..854, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 856..859, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 861..863, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 865..868, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 865..868, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 882..904, decorator_list: [], name: Identifier { id: Name("Test"), range: 888..892, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 892..897, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 893..896, name: Identifier { id: Name("P"), range: 895..896, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 897..899, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 901..904, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 901..904, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 931..966, decorator_list: [], name: Identifier { id: Name("Test"), range: 937..941, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 941..959, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 942..958, name: Identifier { id: Name("P"), range: 944..945, node_index: NodeIndex(None), }, default: Some( List( ExprList { node_index: NodeIndex(None), range: 948..958, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 949..952, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 954..957, id: Name("str"), ctx: Load, }, ), ], ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 959..961, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 963..966, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 963..966, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 982..1022, decorator_list: [], name: Identifier { id: Name("Test"), range: 988..992, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 992..1012, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 993..994, name: Identifier { id: Name("X"), range: 993..994, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 996..1002, name: Identifier { id: Name("Y"), range: 996..997, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 999..1002, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 1004..1006, name: Identifier { id: Name("U"), range: 1005..1006, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 1008..1011, name: Identifier { id: Name("P"), range: 1010..1011, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), arguments: Some( Arguments { range: 1012..1014, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1018..1022, }, ), ], }, ), ], }, ) ``` valid_syntax@statement__delete.py.snap000064400000000000000000000345641046102023000314120ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/delete.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..122, body: [ Delete( StmtDelete { node_index: NodeIndex(None), range: 0..5, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 4..5, id: Name("x"), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 6..13, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 11..12, id: Name("x"), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 14..23, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("a"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("b"), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 24..40, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("a"), ctx: Del, }, ), Tuple( ExprTuple { node_index: NodeIndex(None), range: 31..37, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("b"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 35..36, id: Name("c"), ctx: Del, }, ), ], ctx: Del, parenthesized: true, }, ), Name( ExprName { node_index: NodeIndex(None), range: 39..40, id: Name("d"), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 41..51, targets: [ List( ExprList { node_index: NodeIndex(None), range: 45..51, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("a"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("b"), ctx: Del, }, ), ], ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 52..70, targets: [ List( ExprList { node_index: NodeIndex(None), range: 56..70, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 57..58, id: Name("a"), ctx: Del, }, ), List( ExprList { node_index: NodeIndex(None), range: 60..66, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 61..62, id: Name("b"), ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 64..65, id: Name("c"), ctx: Del, }, ), ], ctx: Del, }, ), Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("d"), ctx: Del, }, ), ], ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 71..78, targets: [ Attribute( ExprAttribute { node_index: NodeIndex(None), range: 75..78, value: Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("y"), range: 77..78, node_index: NodeIndex(None), }, ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 79..87, targets: [ Subscript( ExprSubscript { node_index: NodeIndex(None), range: 83..87, value: Name( ExprName { node_index: NodeIndex(None), range: 83..84, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 85..86, id: Name("y"), ctx: Load, }, ), ctx: Del, }, ), ], }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 88..121, targets: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 92..121, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("x"), ctx: Del, }, ), Attribute( ExprAttribute { node_index: NodeIndex(None), range: 105..108, value: Name( ExprName { node_index: NodeIndex(None), range: 105..106, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("y"), range: 107..108, node_index: NodeIndex(None), }, ctx: Del, }, ), Subscript( ExprSubscript { node_index: NodeIndex(None), range: 114..118, value: Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("x"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 116..117, id: Name("y"), ctx: Load, }, ), ctx: Del, }, ), ], ctx: Del, parenthesized: true, }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__for.py.snap000064400000000000000000000705321046102023000310100ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/for.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..523, body: [ For( StmtFor { node_index: NodeIndex(None), range: 0..28, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 4..10, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 14..18, id: Name("iter"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 24..28, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 30..63, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 34..40, id: Name("target"), ctx: Store, }, ), iter: Tuple( ExprTuple { node_index: NodeIndex(None), range: 44..53, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 48..49, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 3, ), }, ), ], ctx: Load, parenthesized: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 59..63, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 65..100, is_async: false, target: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 69..80, value: Name( ExprName { node_index: NodeIndex(None), range: 69..75, id: Name("target"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 76..80, node_index: NodeIndex(None), }, ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 84..90, func: Name( ExprName { node_index: NodeIndex(None), range: 84..88, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 88..90, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 96..100, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 102..135, is_async: false, target: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 106..115, value: Name( ExprName { node_index: NodeIndex(None), range: 106..112, id: Name("target"), ctx: Load, }, ), slice: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 113..114, value: Int( 0, ), }, ), ctx: Store, }, ), iter: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 119..125, value: Name( ExprName { node_index: NodeIndex(None), range: 119..120, id: Name("x"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 121..125, node_index: NodeIndex(None), }, ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 131..135, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 137..167, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 141..147, id: Name("target"), ctx: Store, }, ), iter: Compare( ExprCompare { node_index: NodeIndex(None), range: 151..157, left: Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("x"), ctx: Load, }, ), ops: [ LtE, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("y"), ctx: Load, }, ), ], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 163..167, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 169..200, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 173..179, id: Name("target"), ctx: Store, }, ), iter: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 183..190, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 183..184, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 189..190, id: Name("b"), ctx: Load, }, ), ], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 196..200, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 202..232, is_async: false, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 206..214, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 206..207, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 209..210, id: Name("b"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 212..213, id: Name("c"), ctx: Store, }, ), ], ctx: Store, parenthesized: false, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 218..222, id: Name("iter"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 228..232, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 234..262, is_async: false, target: Tuple( ExprTuple { node_index: NodeIndex(None), range: 238..244, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 239..240, id: Name("a"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 242..243, id: Name("b"), ctx: Store, }, ), ], ctx: Store, parenthesized: true, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 248..252, id: Name("iter"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 258..262, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 264..294, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 268..274, id: Name("target"), ctx: Store, }, ), iter: List( ExprList { node_index: NodeIndex(None), range: 278..284, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 279..280, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 282..283, value: Int( 2, ), }, ), ], ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 290..294, }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 296..322, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 300..306, id: Name("target"), ctx: Store, }, ), iter: Await( ExprAwait { node_index: NodeIndex(None), range: 310..317, value: Name( ExprName { node_index: NodeIndex(None), range: 316..317, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 319..322, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 319..322, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 323..353, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 327..333, id: Name("target"), ctx: Store, }, ), iter: Lambda( ExprLambda { node_index: NodeIndex(None), range: 337..348, parameters: Some( Parameters { range: 344..345, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 344..345, node_index: NodeIndex(None), parameter: Parameter { range: 344..345, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 344..345, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 347..348, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 350..353, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 350..353, }, ), }, ), ], orelse: [], }, ), For( StmtFor { node_index: NodeIndex(None), range: 354..389, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 358..364, id: Name("target"), ctx: Store, }, ), iter: If( ExprIf { node_index: NodeIndex(None), range: 368..384, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 373..377, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 368..369, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 383..384, id: Name("y"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 386..389, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 386..389, }, ), }, ), ], orelse: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 391..522, test: Name( ExprName { node_index: NodeIndex(None), range: 394..395, id: Name("x"), ctx: Load, }, ), body: [ For( StmtFor { node_index: NodeIndex(None), range: 401..433, is_async: false, target: Name( ExprName { node_index: NodeIndex(None), range: 405..411, id: Name("target"), ctx: Store, }, ), iter: Name( ExprName { node_index: NodeIndex(None), range: 415..419, id: Name("iter"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 429..433, }, ), ], orelse: [], }, ), ], elif_else_clauses: [ ElifElseClause { range: 508..522, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 518..522, }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@statement__from_import.py.snap000064400000000000000000000247311046102023000325000ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/from_import.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..259, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..15, module: Some( Identifier { id: Name("a"), range: 5..6, node_index: NodeIndex(None), }, ), names: [ Alias { range: 14..15, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 14..15, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 27..42, module: None, names: [ Alias { range: 41..42, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 41..42, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 43..85, module: Some( Identifier { id: Name("foo.bar"), range: 48..55, node_index: NodeIndex(None), }, ), names: [ Alias { range: 63..71, node_index: NodeIndex(None), name: Identifier { id: Name("baz"), range: 63..66, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("b"), range: 70..71, node_index: NodeIndex(None), }, ), }, Alias { range: 73..85, node_index: NodeIndex(None), name: Identifier { id: Name("FooBar"), range: 73..79, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("fb"), range: 83..85, node_index: NodeIndex(None), }, ), }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 86..102, module: Some( Identifier { id: Name("a"), range: 92..93, node_index: NodeIndex(None), }, ), names: [ Alias { range: 101..102, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 101..102, node_index: NodeIndex(None), }, asname: None, }, ], level: 1, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 103..120, module: None, names: [ Alias { range: 119..120, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 119..120, node_index: NodeIndex(None), }, asname: None, }, ], level: 3, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 121..161, module: None, names: [ Alias { range: 160..161, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 160..161, node_index: NodeIndex(None), }, asname: None, }, ], level: 26, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 162..207, module: Some( Identifier { id: Name("a.b.c"), range: 193..198, node_index: NodeIndex(None), }, ), names: [ Alias { range: 206..207, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 206..207, node_index: NodeIndex(None), }, asname: None, }, ], level: 26, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 208..242, module: Some( Identifier { id: Name("module"), range: 213..219, node_index: NodeIndex(None), }, ), names: [ Alias { range: 228..229, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 228..229, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 231..237, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 231..232, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("B"), range: 236..237, node_index: NodeIndex(None), }, ), }, Alias { range: 239..240, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 239..240, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 243..258, module: Some( Identifier { id: Name("a"), range: 248..249, node_index: NodeIndex(None), }, ), names: [ Alias { range: 257..258, node_index: NodeIndex(None), name: Identifier { id: Name("*"), range: 257..258, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` valid_syntax@statement__function.py.snap000064400000000000000000005363731046102023000320020ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/function.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..2399, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..29, is_async: false, decorator_list: [], name: Identifier { id: Name("no_parameters"), range: 4..17, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 17..19, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 25..29, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 32..76, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_parameters"), range: 36..57, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 57..66, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 58..59, node_index: NodeIndex(None), parameter: Parameter { range: 58..59, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 58..59, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 61..62, node_index: NodeIndex(None), parameter: Parameter { range: 61..62, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 61..62, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 64..65, node_index: NodeIndex(None), parameter: Parameter { range: 64..65, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 64..65, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 72..76, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 79..149, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_parameters_with_default_values"), range: 83..124, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 124..139, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 125..126, node_index: NodeIndex(None), parameter: Parameter { range: 125..126, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 125..126, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 128..132, node_index: NodeIndex(None), parameter: Parameter { range: 128..129, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 128..129, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 130..132, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 134..138, node_index: NodeIndex(None), parameter: Parameter { range: 134..135, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 134..135, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 136..138, value: Int( 30, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 145..149, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 152..226, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_parameters_with_default_values2"), range: 156..198, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 198..216, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 199..200, node_index: NodeIndex(None), parameter: Parameter { range: 199..200, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 199..200, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 202..206, node_index: NodeIndex(None), parameter: Parameter { range: 202..203, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 202..203, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 204..206, value: Int( 20, ), }, ), ), }, ], args: [ ParameterWithDefault { range: 211..215, node_index: NodeIndex(None), parameter: Parameter { range: 211..212, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 211..212, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..215, value: Int( 30, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 222..226, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 229..296, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_only_and_positional_parameters"), range: 233..274, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 274..286, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 275..276, node_index: NodeIndex(None), parameter: Parameter { range: 275..276, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 275..276, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 281..282, node_index: NodeIndex(None), parameter: Parameter { range: 281..282, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 281..282, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 284..285, node_index: NodeIndex(None), parameter: Parameter { range: 284..285, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 284..285, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 292..296, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 299..393, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_args_with_defaults_and_varargs_and_kwargs"), range: 303..348, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 348..383, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 349..350, node_index: NodeIndex(None), parameter: Parameter { range: 349..350, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 349..350, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 352..356, node_index: NodeIndex(None), parameter: Parameter { range: 352..353, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 352..353, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 354..356, value: Int( 20, ), }, ), ), }, ], args: [ ParameterWithDefault { range: 361..365, node_index: NodeIndex(None), parameter: Parameter { range: 361..362, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 361..362, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 363..365, value: Int( 30, ), }, ), ), }, ], vararg: Some( Parameter { range: 367..372, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 368..372, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 374..382, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 376..382, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 389..393, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 396..445, is_async: false, decorator_list: [], name: Identifier { id: Name("keyword_only_parameters"), range: 400..423, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 423..435, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 427..428, node_index: NodeIndex(None), parameter: Parameter { range: 427..428, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 427..428, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 430..431, node_index: NodeIndex(None), parameter: Parameter { range: 430..431, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 430..431, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 433..434, node_index: NodeIndex(None), parameter: Parameter { range: 433..434, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 433..434, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 441..445, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 448..517, is_async: false, decorator_list: [], name: Identifier { id: Name("keyword_only_parameters_with_defaults"), range: 452..489, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 489..507, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 493..494, node_index: NodeIndex(None), parameter: Parameter { range: 493..494, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 493..494, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 496..500, node_index: NodeIndex(None), parameter: Parameter { range: 496..497, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 496..497, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 498..500, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 502..506, node_index: NodeIndex(None), parameter: Parameter { range: 502..503, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 502..503, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 504..506, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 513..517, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 520..594, is_async: false, decorator_list: [], name: Identifier { id: Name("kw_only_args_with_defaults_and_varargs"), range: 524..562, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 562..584, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 563..568, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 564..568, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 570..571, node_index: NodeIndex(None), parameter: Parameter { range: 570..571, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 570..571, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 573..577, node_index: NodeIndex(None), parameter: Parameter { range: 573..574, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 573..574, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 575..577, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 579..583, node_index: NodeIndex(None), parameter: Parameter { range: 579..580, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 579..580, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 581..583, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 590..594, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 597..676, is_async: false, decorator_list: [], name: Identifier { id: Name("kw_only_args_with_defaults_and_kwargs"), range: 601..638, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 638..666, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 642..643, node_index: NodeIndex(None), parameter: Parameter { range: 642..643, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 642..643, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 645..649, node_index: NodeIndex(None), parameter: Parameter { range: 645..646, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 645..646, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 647..649, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 651..655, node_index: NodeIndex(None), parameter: Parameter { range: 651..652, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 651..652, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 653..655, value: Int( 30, ), }, ), ), }, ], kwarg: Some( Parameter { range: 657..665, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 659..665, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 672..676, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 679..774, is_async: false, decorator_list: [], name: Identifier { id: Name("kw_only_args_with_defaults_and_varargs_and_kwargs"), range: 683..732, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 732..764, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 733..738, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 734..738, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 740..741, node_index: NodeIndex(None), parameter: Parameter { range: 740..741, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 740..741, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 743..747, node_index: NodeIndex(None), parameter: Parameter { range: 743..744, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 743..744, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 745..747, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 749..753, node_index: NodeIndex(None), parameter: Parameter { range: 749..750, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 749..750, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 751..753, value: Int( 30, ), }, ), ), }, ], kwarg: Some( Parameter { range: 755..763, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 757..763, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 770..774, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 777..835, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_and_kw_only_args"), range: 781..801, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 801..825, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 802..803, node_index: NodeIndex(None), parameter: Parameter { range: 802..803, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 802..803, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 805..806, node_index: NodeIndex(None), parameter: Parameter { range: 805..806, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 805..806, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 811..812, node_index: NodeIndex(None), parameter: Parameter { range: 811..812, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 811..812, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 817..818, node_index: NodeIndex(None), parameter: Parameter { range: 817..818, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 817..818, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 820..821, node_index: NodeIndex(None), parameter: Parameter { range: 820..821, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 820..821, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 823..824, node_index: NodeIndex(None), parameter: Parameter { range: 823..824, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 823..824, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 831..835, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 838..916, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_and_kw_only_args_with_defaults"), range: 842..876, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 876..906, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 877..878, node_index: NodeIndex(None), parameter: Parameter { range: 877..878, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 877..878, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 880..881, node_index: NodeIndex(None), parameter: Parameter { range: 880..881, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 880..881, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 886..887, node_index: NodeIndex(None), parameter: Parameter { range: 886..887, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 886..887, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 892..893, node_index: NodeIndex(None), parameter: Parameter { range: 892..893, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 892..893, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 895..899, node_index: NodeIndex(None), parameter: Parameter { range: 895..896, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 895..896, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 897..899, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 901..905, node_index: NodeIndex(None), parameter: Parameter { range: 901..902, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 901..902, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 903..905, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 912..916, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 919..1013, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_and_kw_only_args_with_defaults_and_varargs"), range: 923..969, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 969..1003, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 970..971, node_index: NodeIndex(None), parameter: Parameter { range: 970..971, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 970..971, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 973..974, node_index: NodeIndex(None), parameter: Parameter { range: 973..974, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 973..974, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 979..980, node_index: NodeIndex(None), parameter: Parameter { range: 979..980, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 979..980, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 982..987, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 983..987, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 989..990, node_index: NodeIndex(None), parameter: Parameter { range: 989..990, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 989..990, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 992..996, node_index: NodeIndex(None), parameter: Parameter { range: 992..993, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 992..993, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 994..996, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 998..1002, node_index: NodeIndex(None), parameter: Parameter { range: 998..999, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 998..999, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1000..1002, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1009..1013, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1016..1121, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_and_kw_only_args_with_defaults_and_kwargs"), range: 1020..1065, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1065..1111, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 1071..1072, node_index: NodeIndex(None), parameter: Parameter { range: 1071..1072, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1071..1072, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1074..1075, node_index: NodeIndex(None), parameter: Parameter { range: 1074..1075, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1074..1075, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 1080..1081, node_index: NodeIndex(None), parameter: Parameter { range: 1080..1081, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1080..1081, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 1086..1087, node_index: NodeIndex(None), parameter: Parameter { range: 1086..1087, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1086..1087, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1089..1093, node_index: NodeIndex(None), parameter: Parameter { range: 1089..1090, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1089..1090, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1091..1093, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 1095..1099, node_index: NodeIndex(None), parameter: Parameter { range: 1095..1096, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1095..1096, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1097..1099, value: Int( 30, ), }, ), ), }, ], kwarg: Some( Parameter { range: 1101..1109, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 1103..1109, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1117..1121, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1124..1245, is_async: false, decorator_list: [], name: Identifier { id: Name("pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs"), range: 1128..1185, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1185..1235, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 1191..1192, node_index: NodeIndex(None), parameter: Parameter { range: 1191..1192, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1191..1192, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1194..1195, node_index: NodeIndex(None), parameter: Parameter { range: 1194..1195, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1194..1195, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 1200..1201, node_index: NodeIndex(None), parameter: Parameter { range: 1200..1201, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1200..1201, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 1203..1208, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 1204..1208, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 1210..1211, node_index: NodeIndex(None), parameter: Parameter { range: 1210..1211, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1210..1211, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1213..1217, node_index: NodeIndex(None), parameter: Parameter { range: 1213..1214, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1213..1214, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1215..1217, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 1219..1223, node_index: NodeIndex(None), parameter: Parameter { range: 1219..1220, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1219..1220, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1221..1223, value: Int( 30, ), }, ), ), }, ], kwarg: Some( Parameter { range: 1225..1233, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 1227..1233, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1241..1245, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1248..1316, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_and_keyword_parameters"), range: 1252..1285, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1285..1306, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1286..1287, node_index: NodeIndex(None), parameter: Parameter { range: 1286..1287, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1286..1287, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1289..1290, node_index: NodeIndex(None), parameter: Parameter { range: 1289..1290, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1289..1290, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1292..1293, node_index: NodeIndex(None), parameter: Parameter { range: 1292..1293, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1292..1293, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 1298..1299, node_index: NodeIndex(None), parameter: Parameter { range: 1298..1299, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1298..1299, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1301..1302, node_index: NodeIndex(None), parameter: Parameter { range: 1301..1302, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1301..1302, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1304..1305, node_index: NodeIndex(None), parameter: Parameter { range: 1304..1305, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1304..1305, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1312..1316, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1319..1407, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_and_keyword_parameters_with_defaults"), range: 1323..1370, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1370..1397, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1371..1372, node_index: NodeIndex(None), parameter: Parameter { range: 1371..1372, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1371..1372, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1374..1375, node_index: NodeIndex(None), parameter: Parameter { range: 1374..1375, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1374..1375, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1377..1378, node_index: NodeIndex(None), parameter: Parameter { range: 1377..1378, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1377..1378, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 1383..1384, node_index: NodeIndex(None), parameter: Parameter { range: 1383..1384, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1383..1384, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1386..1390, node_index: NodeIndex(None), parameter: Parameter { range: 1386..1387, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1386..1387, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1388..1390, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 1392..1396, node_index: NodeIndex(None), parameter: Parameter { range: 1392..1393, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1392..1393, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1394..1396, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1403..1407, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1410..1520, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_and_keyword_parameters_with_defaults_and_varargs"), range: 1414..1473, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1473..1510, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1479..1480, node_index: NodeIndex(None), parameter: Parameter { range: 1479..1480, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1479..1480, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1482..1483, node_index: NodeIndex(None), parameter: Parameter { range: 1482..1483, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1482..1483, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1485..1486, node_index: NodeIndex(None), parameter: Parameter { range: 1485..1486, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1485..1486, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 1488..1493, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 1489..1493, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 1495..1496, node_index: NodeIndex(None), parameter: Parameter { range: 1495..1496, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1495..1496, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1498..1502, node_index: NodeIndex(None), parameter: Parameter { range: 1498..1499, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1498..1499, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1500..1502, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 1504..1508, node_index: NodeIndex(None), parameter: Parameter { range: 1504..1505, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1504..1505, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1506..1508, value: Int( 30, ), }, ), ), }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1516..1520, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1523..1654, is_async: false, decorator_list: [], name: Identifier { id: Name("positional_and_keyword_parameters_with_defaults_and_varargs_and_kwargs"), range: 1527..1597, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1597..1644, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1603..1604, node_index: NodeIndex(None), parameter: Parameter { range: 1603..1604, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1603..1604, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1606..1607, node_index: NodeIndex(None), parameter: Parameter { range: 1606..1607, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 1606..1607, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1609..1610, node_index: NodeIndex(None), parameter: Parameter { range: 1609..1610, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 1609..1610, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: Some( Parameter { range: 1612..1617, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 1613..1617, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [ ParameterWithDefault { range: 1619..1620, node_index: NodeIndex(None), parameter: Parameter { range: 1619..1620, node_index: NodeIndex(None), name: Identifier { id: Name("d"), range: 1619..1620, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 1622..1626, node_index: NodeIndex(None), parameter: Parameter { range: 1622..1623, node_index: NodeIndex(None), name: Identifier { id: Name("e"), range: 1622..1623, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1624..1626, value: Int( 20, ), }, ), ), }, ParameterWithDefault { range: 1628..1632, node_index: NodeIndex(None), parameter: Parameter { range: 1628..1629, node_index: NodeIndex(None), name: Identifier { id: Name("f"), range: 1628..1629, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1630..1632, value: Int( 30, ), }, ), ), }, ], kwarg: Some( Parameter { range: 1634..1642, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 1636..1642, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1650..1654, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1703..1735, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1707..1711, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1711..1714, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1712..1713, name: Identifier { id: Name("T"), range: 1712..1713, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), parameters: Parameters { range: 1714..1720, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1715..1719, node_index: NodeIndex(None), parameter: Parameter { range: 1715..1719, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1715..1716, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 1718..1719, id: Name("T"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 1724..1725, id: Name("T"), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1731..1735, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1738..1775, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1742..1746, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1746..1754, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1747..1753, name: Identifier { id: Name("T"), range: 1747..1748, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 1750..1753, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), ], }, ), parameters: Parameters { range: 1754..1760, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1755..1759, node_index: NodeIndex(None), parameter: Parameter { range: 1755..1759, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1755..1756, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 1758..1759, id: Name("T"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 1764..1765, id: Name("T"), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1771..1775, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1778..1824, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1782..1786, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1786..1803, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1787..1802, name: Identifier { id: Name("T"), range: 1787..1788, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 1790..1802, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 1791..1794, id: Name("str"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 1796..1801, id: Name("bytes"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), ], }, ), parameters: Parameters { range: 1803..1809, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1804..1808, node_index: NodeIndex(None), parameter: Parameter { range: 1804..1808, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1804..1805, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 1807..1808, id: Name("T"), ctx: Load, }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 1813..1814, id: Name("T"), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1820..1824, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1827..1873, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1831..1835, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1835..1840, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 1836..1839, name: Identifier { id: Name("Ts"), range: 1837..1839, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 1840..1849, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 1841..1848, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 1842..1843, node_index: NodeIndex(None), }, annotation: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 1845..1848, value: Name( ExprName { node_index: NodeIndex(None), range: 1846..1848, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: None, }, returns: Some( Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1853..1863, value: Name( ExprName { node_index: NodeIndex(None), range: 1853..1858, id: Name("Tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1859..1862, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1859..1862, value: Name( ExprName { node_index: NodeIndex(None), range: 1860..1862, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1869..1873, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1876..1934, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1880..1884, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1884..1889, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 1885..1888, name: Identifier { id: Name("P"), range: 1887..1888, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 1889..1924, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 1890..1903, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 1891..1895, node_index: NodeIndex(None), }, annotation: Some( Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1897..1903, value: Name( ExprName { node_index: NodeIndex(None), range: 1897..1898, id: Name("P"), ctx: Load, }, ), attr: Identifier { id: Name("args"), range: 1899..1903, node_index: NodeIndex(None), }, ctx: Load, }, ), ), }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 1905..1923, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 1907..1913, node_index: NodeIndex(None), }, annotation: Some( Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1915..1923, value: Name( ExprName { node_index: NodeIndex(None), range: 1915..1916, id: Name("P"), ctx: Load, }, ), attr: Identifier { id: Name("kwargs"), range: 1917..1923, node_index: NodeIndex(None), }, ctx: Load, }, ), ), }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1930..1934, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1937..1978, is_async: false, decorator_list: [], name: Identifier { id: Name("func"), range: 1941..1945, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 1945..1966, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1946..1947, name: Identifier { id: Name("T"), range: 1946..1947, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1949..1955, name: Identifier { id: Name("U"), range: 1949..1950, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 1952..1955, id: Name("str"), ctx: Load, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 1957..1960, name: Identifier { id: Name("Ts"), range: 1958..1960, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 1962..1965, name: Identifier { id: Name("P"), range: 1964..1965, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), parameters: Parameters { range: 1966..1968, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1974..1978, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 1981..2000, is_async: false, decorator_list: [], name: Identifier { id: Name("ellipsis"), range: 1985..1993, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 1993..1995, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 1997..2000, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 1997..2000, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2003..2064, is_async: false, decorator_list: [], name: Identifier { id: Name("multiple_statements"), range: 2007..2026, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2026..2028, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Name( ExprName { node_index: NodeIndex(None), range: 2032..2035, id: Name("int"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 2041..2047, value: Call( ExprCall { node_index: NodeIndex(None), range: 2041..2047, func: Name( ExprName { node_index: NodeIndex(None), range: 2041..2045, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 2045..2047, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 2052..2056, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 2061..2064, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 2061..2064, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2067..2091, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2071..2074, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2074..2081, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 2075..2080, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 2076..2080, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2087..2091, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2094..2121, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2098..2101, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2101..2111, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: Some( Parameter { range: 2102..2110, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 2104..2110, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2117..2121, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2124..2158, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2128..2131, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2131..2148, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: Some( Parameter { range: 2132..2137, node_index: NodeIndex(None), name: Identifier { id: Name("args"), range: 2133..2137, node_index: NodeIndex(None), }, annotation: None, }, ), kwonlyargs: [], kwarg: Some( Parameter { range: 2139..2147, node_index: NodeIndex(None), name: Identifier { id: Name("kwargs"), range: 2141..2147, node_index: NodeIndex(None), }, annotation: None, }, ), }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2154..2158, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2161..2184, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2165..2168, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2168..2174, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 2169..2170, node_index: NodeIndex(None), parameter: Parameter { range: 2169..2170, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2169..2170, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2180..2184, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2187..2213, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2191..2194, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2194..2203, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 2195..2196, node_index: NodeIndex(None), parameter: Parameter { range: 2195..2196, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2195..2196, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [ ParameterWithDefault { range: 2201..2202, node_index: NodeIndex(None), parameter: Parameter { range: 2201..2202, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 2201..2202, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2209..2213, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2216..2242, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2220..2223, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2223..2232, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 2224..2227, node_index: NodeIndex(None), parameter: Parameter { range: 2224..2225, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2224..2225, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2226..2227, value: Int( 1, ), }, ), ), }, ], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2238..2242, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2245..2277, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2249..2252, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2252..2267, node_index: NodeIndex(None), posonlyargs: [ ParameterWithDefault { range: 2253..2254, node_index: NodeIndex(None), parameter: Parameter { range: 2253..2254, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2253..2254, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 2256..2257, node_index: NodeIndex(None), parameter: Parameter { range: 2256..2257, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 2256..2257, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], args: [], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 2265..2266, node_index: NodeIndex(None), parameter: Parameter { range: 2265..2266, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 2265..2266, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2273..2277, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2280..2309, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2284..2287, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2287..2299, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 2288..2292, node_index: NodeIndex(None), parameter: Parameter { range: 2288..2290, node_index: NodeIndex(None), name: Identifier { id: Name("kw"), range: 2288..2290, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2291..2292, value: Int( 1, ), }, ), ), }, ], vararg: None, kwonlyargs: [ ParameterWithDefault { range: 2297..2298, node_index: NodeIndex(None), parameter: Parameter { range: 2297..2298, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2297..2298, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2305..2309, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2312..2357, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2316..2319, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2319..2347, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 2320..2326, node_index: NodeIndex(None), parameter: Parameter { range: 2320..2326, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 2320..2321, node_index: NodeIndex(None), }, annotation: Some( Name( ExprName { node_index: NodeIndex(None), range: 2323..2326, id: Name("int"), ctx: Load, }, ), ), }, default: None, }, ParameterWithDefault { range: 2328..2336, node_index: NodeIndex(None), parameter: Parameter { range: 2328..2336, node_index: NodeIndex(None), name: Identifier { id: Name("y"), range: 2328..2329, node_index: NodeIndex(None), }, annotation: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2331..2336, value: StringLiteralValue { inner: Single( StringLiteral { range: 2331..2336, node_index: NodeIndex(None), value: "str", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), }, default: None, }, ParameterWithDefault { range: 2338..2346, node_index: NodeIndex(None), parameter: Parameter { range: 2338..2346, node_index: NodeIndex(None), name: Identifier { id: Name("z"), range: 2338..2339, node_index: NodeIndex(None), }, annotation: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 2341..2346, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2341..2342, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2345..2346, value: Int( 2, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2353..2357, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 2360..2398, is_async: false, decorator_list: [], name: Identifier { id: Name("foo"), range: 2364..2367, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 2367..2388, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 2368..2372, node_index: NodeIndex(None), parameter: Parameter { range: 2368..2372, node_index: NodeIndex(None), name: Identifier { id: Name("self"), range: 2368..2372, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ParameterWithDefault { range: 2374..2377, node_index: NodeIndex(None), parameter: Parameter { range: 2374..2375, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 2374..2375, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2376..2377, value: Int( 1, ), }, ), ), }, ParameterWithDefault { range: 2379..2382, node_index: NodeIndex(None), parameter: Parameter { range: 2379..2380, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 2379..2380, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2381..2382, value: Int( 2, ), }, ), ), }, ParameterWithDefault { range: 2384..2387, node_index: NodeIndex(None), parameter: Parameter { range: 2384..2385, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 2384..2385, node_index: NodeIndex(None), }, annotation: None, }, default: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2386..2387, value: Int( 3, ), }, ), ), }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2394..2398, }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__if.py.snap000064400000000000000000001050301046102023000306100ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/if.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..375, body: [ If( StmtIf { node_index: NodeIndex(None), range: 0..28, test: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3..4, value: Int( 1, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 6..8, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 6..8, value: Int( 10, ), }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 9..19, node_index: NodeIndex(None), test: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 14..15, value: Int( 2, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 17..19, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 17..19, value: Int( 20, ), }, ), }, ), ], }, ElifElseClause { range: 20..28, node_index: NodeIndex(None), test: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 26..28, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 26..28, value: Int( 30, ), }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 30..52, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 33..37, value: true, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..44, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 49..52, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 49..52, }, ), }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 53..85, test: Compare( ExprCompare { node_index: NodeIndex(None), range: 56..61, left: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("x"), ctx: Load, }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 60..61, value: Int( 1, ), }, ), ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 67..70, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 67..70, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 71..85, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 81..85, }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 87..117, test: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("a"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 97..101, }, ), ], elif_else_clauses: [ ElifElseClause { range: 102..117, node_index: NodeIndex(None), test: Some( Name( ExprName { node_index: NodeIndex(None), range: 107..108, id: Name("b"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 114..117, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 114..117, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 119..203, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 122..129, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 128..129, id: Name("b"), ctx: Load, }, ), ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 135..138, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 135..138, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 139..157, node_index: NodeIndex(None), test: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 144..148, value: true, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 154..157, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 154..157, }, ), }, ), ], }, ElifElseClause { range: 158..173, node_index: NodeIndex(None), test: Some( Name( ExprName { node_index: NodeIndex(None), range: 163..164, id: Name("c"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 170..173, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 170..173, }, ), }, ), ], }, ElifElseClause { range: 174..189, node_index: NodeIndex(None), test: Some( Name( ExprName { node_index: NodeIndex(None), range: 179..180, id: Name("d"), ctx: Load, }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 186..189, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 186..189, }, ), }, ), ], }, ElifElseClause { range: 190..203, node_index: NodeIndex(None), test: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 200..203, value: Call( ExprCall { node_index: NodeIndex(None), range: 200..203, func: Name( ExprName { node_index: NodeIndex(None), range: 200..201, id: Name("f"), ctx: Load, }, ), arguments: Arguments { range: 201..203, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 229..260, test: Named( ExprNamed { node_index: NodeIndex(None), range: 232..238, target: Name( ExprName { node_index: NodeIndex(None), range: 232..233, id: Name("a"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 237..238, id: Name("b"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 240..243, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 240..243, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 244..260, node_index: NodeIndex(None), test: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 249..255, target: Name( ExprName { node_index: NodeIndex(None), range: 249..250, id: Name("a"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 254..255, id: Name("b"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 257..260, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 257..260, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 261..302, test: Lambda( ExprLambda { node_index: NodeIndex(None), range: 264..275, parameters: Some( Parameters { range: 271..272, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 271..272, node_index: NodeIndex(None), parameter: Parameter { range: 271..272, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 271..272, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 274..275, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 277..280, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 277..280, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 281..302, node_index: NodeIndex(None), test: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 286..297, parameters: Some( Parameters { range: 293..294, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 293..294, node_index: NodeIndex(None), parameter: Parameter { range: 293..294, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 293..294, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 296..297, id: Name("x"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 299..302, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 299..302, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 303..336, test: Await( ExprAwait { node_index: NodeIndex(None), range: 306..313, value: Name( ExprName { node_index: NodeIndex(None), range: 312..313, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 315..318, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 315..318, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 319..336, node_index: NodeIndex(None), test: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 324..331, value: Name( ExprName { node_index: NodeIndex(None), range: 330..331, id: Name("x"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 333..336, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 333..336, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 337..374, test: Yield( ExprYield { node_index: NodeIndex(None), range: 341..348, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 347..348, id: Name("x"), ctx: Load, }, ), ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 351..354, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 351..354, }, ), }, ), ], elif_else_clauses: [ ElifElseClause { range: 355..374, node_index: NodeIndex(None), test: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 361..368, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 367..368, id: Name("x"), ctx: Load, }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 371..374, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 371..374, }, ), }, ), ], }, ], }, ), ], }, ) ``` valid_syntax@statement__import.py.snap000064400000000000000000000133521046102023000314520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/import.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..92, body: [ Import( StmtImport { node_index: NodeIndex(None), range: 0..8, names: [ Alias { range: 7..8, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 7..8, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 9..21, names: [ Alias { range: 16..21, node_index: NodeIndex(None), name: Identifier { id: Name("a.b.c"), range: 16..21, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 22..39, names: [ Alias { range: 29..39, node_index: NodeIndex(None), name: Identifier { id: Name("a.b.c"), range: 29..34, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("d"), range: 38..39, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 40..54, names: [ Alias { range: 47..48, node_index: NodeIndex(None), name: Identifier { id: Name("a"), range: 47..48, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 50..51, node_index: NodeIndex(None), name: Identifier { id: Name("b"), range: 50..51, node_index: NodeIndex(None), }, asname: None, }, Alias { range: 53..54, node_index: NodeIndex(None), name: Identifier { id: Name("c"), range: 53..54, node_index: NodeIndex(None), }, asname: None, }, ], is_lazy: false, }, ), Import( StmtImport { node_index: NodeIndex(None), range: 55..91, names: [ Alias { range: 62..74, node_index: NodeIndex(None), name: Identifier { id: Name("foo.bar"), range: 62..69, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("a"), range: 73..74, node_index: NodeIndex(None), }, ), }, Alias { range: 76..91, node_index: NodeIndex(None), name: Identifier { id: Name("a.b.c.d"), range: 76..83, node_index: NodeIndex(None), }, asname: Some( Identifier { id: Name("abcd"), range: 87..91, node_index: NodeIndex(None), }, ), }, ], is_lazy: false, }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__match.py.snap000064400000000000000000016734531046102023000313320ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/match.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..5770, body: [ Match( StmtMatch { node_index: NodeIndex(None), range: 67..103, subject: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 80..103, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 85..88, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 85..88, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..88, value: Complex { real: 0.0, imag: 0.0, }, }, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 98..103, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 98..99, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 102..103, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 126..167, subject: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 139..167, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 144..152, cls: Name( ExprName { node_index: NodeIndex(None), range: 144..149, id: Name("bytes"), ctx: Load, }, ), arguments: PatternArguments { range: 149..152, node_index: NodeIndex(None), patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 150..151, pattern: None, name: Some( Identifier { id: Name("z"), range: 150..151, node_index: NodeIndex(None), }, ), }, ), ], keywords: [], }, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 162..167, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 162..163, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 166..167, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 190..260, subject: Name( ExprName { node_index: NodeIndex(None), range: 196..197, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 203..229, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 208..209, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 208..209, value: Int( 0, ), }, ), }, ), guard: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 213..214, value: Int( 0, ), }, ), ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 224..229, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 224..225, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 228..229, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 234..260, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 239..240, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 239..240, value: Int( 0, ), }, ), }, ), guard: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 244..245, value: Int( 1, ), }, ), ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 255..260, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 255..256, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 259..260, value: Int( 1, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 283..332, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 289..290, value: Int( 3, ), }, ), cases: [ MatchCase { range: 296..332, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 301..314, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 301..302, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 301..302, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 305..306, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 305..306, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 309..310, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 309..310, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 313..314, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 313..314, value: Int( 3, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 324..332, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 324..325, id: Name("x"), ctx: Store, }, ), ], value: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 328..332, value: true, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 355..403, subject: Name( ExprName { node_index: NodeIndex(None), range: 361..362, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 368..403, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 373..388, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 373..379, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 374..375, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 374..375, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 377..378, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 377..378, value: Int( 1, ), }, ), }, ), ], }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 382..388, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 383..384, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 383..384, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 386..387, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 386..387, value: Int( 0, ), }, ), }, ), ], }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 398..403, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 398..399, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 402..403, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 445..523, subject: Name( ExprName { node_index: NodeIndex(None), range: 451..452, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 458..489, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 463..467, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 464..466, name: None, }, ), ], }, ), guard: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 477..489, value: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 484..489, value: StringLiteralValue { inner: Single( StringLiteral { range: 484..489, node_index: NodeIndex(None), value: "seq", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), }, ), ], }, MatchCase { range: 494..523, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 499..501, keys: [], patterns: [], rest: None, }, ), guard: None, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 511..523, value: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 518..523, value: StringLiteralValue { inner: Single( StringLiteral { range: 518..523, node_index: NodeIndex(None), value: "map", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 546..714, subject: Name( ExprName { node_index: NodeIndex(None), range: 552..553, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 559..594, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 564..579, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 565..566, value: Int( 0, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 568..578, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 569..570, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 569..570, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 572..573, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 572..573, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 575..577, keys: [], patterns: [], rest: None, }, ), ], }, ), ], rest: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 589..594, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 589..590, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 593..594, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 599..687, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 604..672, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 604..626, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 605..606, value: Int( 0, ), }, ), ], patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 608..625, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 608..618, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 609..610, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 609..610, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 612..613, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 612..613, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 615..617, keys: [], patterns: [], rest: None, }, ), ], }, ), MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 621..625, value: True, }, ), ], }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 629..638, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 630..631, value: Int( 1, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 633..637, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 634..636, patterns: [], }, ), ], }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 641..656, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 642..643, value: Int( 0, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 645..655, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 646..647, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 646..647, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 649..650, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 649..650, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 652..654, keys: [], patterns: [], rest: None, }, ), ], }, ), ], rest: None, }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 659..661, patterns: [], }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 664..667, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 664..667, value: StringLiteralValue { inner: Single( StringLiteral { range: 664..667, node_index: NodeIndex(None), value: "X", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 670..672, keys: [], patterns: [], rest: None, }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 682..687, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 682..683, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 686..687, value: Int( 1, ), }, ), }, ), ], }, MatchCase { range: 692..714, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 697..699, patterns: [], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 709..714, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 709..710, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 713..714, value: Int( 2, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 737..782, subject: Name( ExprName { node_index: NodeIndex(None), range: 743..744, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 750..782, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 755..767, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 755..767, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 755..759, value: Float( 0.25, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 762..767, value: Complex { real: 0.0, imag: 1.75, }, }, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 777..782, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 777..778, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 781..782, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 805..841, subject: Name( ExprName { node_index: NodeIndex(None), range: 811..812, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 818..841, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 823..826, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 823..826, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 824..826, value: Complex { real: 0.0, imag: 0.0, }, }, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 836..841, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 836..837, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 840..841, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 864..913, subject: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 870..871, value: Int( 4, ), }, ), cases: [ MatchCase { range: 877..913, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 882..895, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 882..883, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 882..883, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 886..887, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 886..887, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 890..891, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 890..891, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 894..895, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 894..895, value: Int( 3, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 905..913, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 905..906, id: Name("x"), ctx: Store, }, ), ], value: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 909..913, value: true, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 936..975, subject: Name( ExprName { node_index: NodeIndex(None), range: 942..943, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 949..975, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 954..955, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 954..955, value: Int( 0, ), }, ), }, ), guard: Some( Name( ExprName { node_index: NodeIndex(None), range: 959..960, id: Name("x"), ctx: Load, }, ), ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 970..975, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 970..971, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 974..975, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 998..1098, subject: Name( ExprName { node_index: NodeIndex(None), range: 1004..1005, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1011..1037, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 1016..1022, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1017..1018, value: Int( 1, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1020..1021, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1020..1021, value: Int( 0, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1032..1037, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1032..1033, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1036..1037, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 1042..1068, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 1047..1053, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1048..1049, value: Int( 0, ), }, ), ], patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1051..1052, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1051..1052, value: Int( 0, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1063..1068, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1063..1064, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1067..1068, value: Int( 1, ), }, ), }, ), ], }, MatchCase { range: 1073..1098, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 1078..1083, keys: [], patterns: [], rest: Some( Identifier { id: Name("z"), range: 1081..1082, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1093..1098, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1093..1094, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1097..1098, value: Int( 2, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1121..1162, subject: Call( ExprCall { node_index: NodeIndex(None), range: 1127..1132, func: Name( ExprName { node_index: NodeIndex(None), range: 1127..1130, id: Name("Seq"), ctx: Load, }, ), arguments: Arguments { range: 1130..1132, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), cases: [ MatchCase { range: 1138..1162, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1143..1147, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 1144..1146, name: None, }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1157..1162, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1157..1158, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1161..1162, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1185..1245, subject: Name( ExprName { node_index: NodeIndex(None), range: 1191..1192, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1198..1219, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1203..1204, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1203..1204, value: Int( 1, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1214..1219, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1214..1215, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1218..1219, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 1224..1245, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1229..1230, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1229..1230, value: Int( 1, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1240..1245, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1240..1241, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1244..1245, value: Int( 1, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1268..1315, subject: Name( ExprName { node_index: NodeIndex(None), range: 1274..1275, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1281..1315, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 1286..1298, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 1287..1292, value: StringLiteralValue { inner: Single( StringLiteral { range: 1287..1292, node_index: NodeIndex(None), value: "foo", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 1294..1297, pattern: None, name: Some( Identifier { id: Name("bar"), range: 1294..1297, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1308..1315, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1308..1309, id: Name("y"), ctx: Store, }, ), ], value: Name( ExprName { node_index: NodeIndex(None), range: 1312..1315, id: Name("bar"), ctx: Load, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1338..1392, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1344..1353, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1345..1346, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1348..1349, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1351..1352, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), cases: [ MatchCase { range: 1359..1392, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1364..1377, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1365..1366, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1365..1366, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1368..1369, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1368..1369, value: Int( 1, ), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 1371..1373, name: Some( Identifier { id: Name("x"), range: 1372..1373, node_index: NodeIndex(None), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1375..1376, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1375..1376, value: Int( 2, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1387..1392, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1387..1388, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1391..1392, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1415..1529, subject: Name( ExprName { node_index: NodeIndex(None), range: 1421..1422, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1428..1451, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1433..1436, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1434..1435, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1434..1435, value: Int( 0, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1446..1451, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1446..1447, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1450..1451, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 1456..1498, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1461..1467, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1462..1463, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1462..1463, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1465..1466, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1465..1466, value: Int( 0, ), }, ), }, ), ], }, ), guard: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 1472..1482, target: Name( ExprName { node_index: NodeIndex(None), range: 1472..1473, id: Name("x"), ctx: Store, }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1477..1482, value: Name( ExprName { node_index: NodeIndex(None), range: 1477..1478, id: Name("x"), ctx: Load, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 1479..1481, lower: None, upper: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1480..1481, value: Int( 0, ), }, ), ), step: None, }, ), ctx: Load, }, ), }, ), ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1493..1498, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1493..1494, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1497..1498, value: Int( 1, ), }, ), }, ), ], }, MatchCase { range: 1503..1529, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1508..1514, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1509..1510, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1509..1510, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1512..1513, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1512..1513, value: Int( 0, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1524..1529, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1524..1525, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1528..1529, value: Int( 2, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1552..1595, subject: Name( ExprName { node_index: NodeIndex(None), range: 1558..1559, id: Name("w"), ctx: Load, }, ), cases: [ MatchCase { range: 1565..1595, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1570..1580, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 1571..1572, pattern: None, name: Some( Identifier { id: Name("x"), range: 1571..1572, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 1574..1575, pattern: None, name: Some( Identifier { id: Name("y"), range: 1574..1575, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 1577..1579, name: None, }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1590..1595, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1590..1591, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1594..1595, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1618..1664, subject: Name( ExprName { node_index: NodeIndex(None), range: 1624..1625, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1631..1664, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1636..1649, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1636..1649, left: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 1636..1641, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1637..1641, value: Float( 0.25, ), }, ), }, ), op: Sub, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1644..1649, value: Complex { real: 0.0, imag: 1.75, }, }, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1659..1664, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1659..1660, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1663..1664, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1687..1726, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1693..1697, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 1694..1695, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), cases: [ MatchCase { range: 1703..1726, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 1708..1711, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 1709..1710, pattern: None, name: Some( Identifier { id: Name("y"), range: 1709..1710, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1721..1726, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1721..1722, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1725..1726, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1749..1789, subject: Name( ExprName { node_index: NodeIndex(None), range: 1755..1756, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1762..1789, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1767..1774, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1767..1774, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1767..1772, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1767..1770, value: Name( ExprName { node_index: NodeIndex(None), range: 1767..1768, id: Name("A"), ctx: Load, }, ), attr: Identifier { id: Name("B"), range: 1769..1770, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("C"), range: 1771..1772, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("D"), range: 1773..1774, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1784..1789, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1784..1785, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1788..1789, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1812..1849, subject: Name( ExprName { node_index: NodeIndex(None), range: 1818..1819, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1825..1849, node_index: NodeIndex(None), pattern: MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 1830..1834, value: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1844..1849, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1844..1845, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1848..1849, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1872..1906, subject: Name( ExprName { node_index: NodeIndex(None), range: 1878..1879, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1885..1906, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 1890..1891, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1890..1891, value: Int( 0, ), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1901..1906, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1901..1902, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1905..1906, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1929..1967, subject: Name( ExprName { node_index: NodeIndex(None), range: 1935..1936, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 1942..1967, node_index: NodeIndex(None), pattern: MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 1947..1952, value: False, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 1962..1967, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1962..1963, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1966..1967, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 1990..2081, subject: Name( ExprName { node_index: NodeIndex(None), range: 1996..1997, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 2003..2025, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2008..2010, patterns: [], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2020..2025, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2020..2021, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2024..2025, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 2030..2054, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2035..2039, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2036..2038, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2036..2038, value: StringLiteralValue { inner: Single( StringLiteral { range: 2036..2038, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2049..2054, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2049..2050, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2053..2054, value: Int( 1, ), }, ), }, ), ], }, MatchCase { range: 2059..2081, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2064..2066, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2064..2066, value: StringLiteralValue { inner: Single( StringLiteral { range: 2064..2066, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2076..2081, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2076..2077, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2080..2081, value: Int( 2, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2104..2138, subject: Name( ExprName { node_index: NodeIndex(None), range: 2110..2111, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 2117..2138, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2122..2123, pattern: None, name: Some( Identifier { id: Name("z"), range: 2122..2123, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2133..2138, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2133..2134, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2137..2138, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2161..2207, subject: Name( ExprName { node_index: NodeIndex(None), range: 2167..2168, id: Name("w"), ctx: Load, }, ), cases: [ MatchCase { range: 2174..2207, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2179..2192, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2180..2181, pattern: None, name: Some( Identifier { id: Name("x"), range: 2180..2181, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2183..2184, pattern: None, name: Some( Identifier { id: Name("y"), range: 2183..2184, node_index: NodeIndex(None), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 2186..2191, name: Some( Identifier { id: Name("rest"), range: 2187..2191, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2202..2207, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2202..2203, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2206..2207, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2230..2307, subject: Name( ExprName { node_index: NodeIndex(None), range: 2236..2237, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 2243..2307, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 2248..2278, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2249..2255, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2249..2250, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2249..2250, value: Int( 0, ), }, ), }, ), ), name: Some( Identifier { id: Name("z"), range: 2254..2255, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2260..2266, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2260..2261, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2260..2261, value: Int( 1, ), }, ), }, ), ), name: Some( Identifier { id: Name("z"), range: 2265..2266, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2271..2277, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2271..2272, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2271..2272, value: Int( 2, ), }, ), }, ), ), name: Some( Identifier { id: Name("z"), range: 2276..2277, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 2282..2292, left: Name( ExprName { node_index: NodeIndex(None), range: 2282..2283, id: Name("z"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 2287..2292, left: Name( ExprName { node_index: NodeIndex(None), range: 2287..2288, id: Name("x"), ctx: Load, }, ), op: Mod, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2291..2292, value: Int( 2, ), }, ), }, ), ], }, ), ), body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2302..2307, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2302..2303, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2306..2307, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2330..2499, subject: Name( ExprName { node_index: NodeIndex(None), range: 2336..2337, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 2343..2378, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2348..2363, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2349..2350, value: Int( 0, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2352..2362, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2353..2354, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2353..2354, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2356..2357, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2356..2357, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2359..2361, keys: [], patterns: [], rest: None, }, ), ], }, ), ], rest: None, }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2373..2378, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2373..2374, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2377..2378, value: Int( 0, ), }, ), }, ), ], }, MatchCase { range: 2383..2472, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 2388..2457, patterns: [ MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2388..2411, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2389..2390, value: Int( 0, ), }, ), ], patterns: [ MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 2392..2410, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2392..2402, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2393..2394, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2393..2394, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2396..2397, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2396..2397, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2399..2401, keys: [], patterns: [], rest: None, }, ), ], }, ), MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 2405..2410, value: False, }, ), ], }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2414..2423, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2415..2416, value: Int( 1, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2418..2422, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2419..2421, patterns: [], }, ), ], }, ), ], rest: None, }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2426..2441, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2427..2428, value: Int( 0, ), }, ), ], patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2430..2440, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2431..2432, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2431..2432, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2434..2435, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2434..2435, value: Int( 2, ), }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2437..2439, keys: [], patterns: [], rest: None, }, ), ], }, ), ], rest: None, }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2444..2446, patterns: [], }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2449..2452, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2449..2452, value: StringLiteralValue { inner: Single( StringLiteral { range: 2449..2452, node_index: NodeIndex(None), value: "X", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2455..2457, keys: [], patterns: [], rest: None, }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2467..2472, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2467..2468, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2471..2472, value: Int( 1, ), }, ), }, ), ], }, MatchCase { range: 2477..2499, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2482..2484, patterns: [], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2494..2499, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2494..2495, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2498..2499, value: Int( 2, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2522..2568, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2528..2537, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2529..2530, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2532..2533, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2535..2536, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), cases: [ MatchCase { range: 2543..2568, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2548..2553, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2548..2549, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2548..2549, value: Int( 0, ), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 2551..2553, name: Some( Identifier { id: Name("x"), range: 2552..2553, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2563..2568, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2563..2564, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2567..2568, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2591..2638, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2597..2606, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2598..2599, value: Int( 0, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2601..2602, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2604..2605, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: true, }, ), cases: [ MatchCase { range: 2612..2638, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2617..2623, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 2617..2619, name: Some( Identifier { id: Name("x"), range: 2618..2619, node_index: NodeIndex(None), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2621..2622, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2621..2622, value: Int( 2, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2633..2638, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2633..2634, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2637..2638, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2661..2697, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2667..2669, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2667..2668, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 2675..2697, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2680..2682, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2680..2681, pattern: None, name: Some( Identifier { id: Name("y"), range: 2680..2681, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2692..2697, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2692..2693, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2696..2697, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2720..2760, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2726..2730, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 2726..2727, id: Name("w"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 2729..2730, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 2736..2760, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2741..2745, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2741..2742, pattern: None, name: Some( Identifier { id: Name("y"), range: 2741..2742, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2744..2745, pattern: None, name: Some( Identifier { id: Name("z"), range: 2744..2745, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2755..2760, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2755..2756, id: Name("v"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2759..2760, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2783..2829, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 2789..2796, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 2789..2795, target: Name( ExprName { node_index: NodeIndex(None), range: 2789..2790, id: Name("w"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 2794..2795, id: Name("x"), ctx: Load, }, ), }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 2802..2829, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 2807..2814, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2807..2813, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 2807..2808, pattern: None, name: Some( Identifier { id: Name("y"), range: 2807..2808, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("v"), range: 2812..2813, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 2824..2829, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 2824..2825, id: Name("z"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2828..2829, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2831..2952, subject: Name( ExprName { node_index: NodeIndex(None), range: 2837..2838, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 2927..2952, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 2932..2938, value: FString( ExprFString { node_index: NodeIndex(None), range: 2932..2938, value: FStringValue { inner: Single( FString( FString { range: 2932..2938, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 2934..2937, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 2935..2936, id: Name("y"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 2948..2952, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 2953..3025, subject: Dict( ExprDict { node_index: NodeIndex(None), range: 2959..2970, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 2960..2966, value: StringLiteralValue { inner: Single( StringLiteral { range: 2960..2966, node_index: NodeIndex(None), value: "test", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 2968..2969, value: Int( 1, ), }, ), }, ], }, ), cases: [ MatchCase { range: 2976..3025, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 2981..3004, keys: [], patterns: [], rest: Some( Identifier { id: Name("rest"), range: 2993..2997, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3014..3025, value: Call( ExprCall { node_index: NodeIndex(None), range: 3014..3025, func: Name( ExprName { node_index: NodeIndex(None), range: 3014..3019, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 3019..3025, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 3020..3024, id: Name("rest"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3026..3129, subject: Dict( ExprDict { node_index: NodeIndex(None), range: 3032..3049, items: [ DictItem { key: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 3033..3040, value: StringLiteralValue { inner: Single( StringLiteral { range: 3033..3040, node_index: NodeIndex(None), value: "label", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 3042..3048, value: StringLiteralValue { inner: Single( StringLiteral { range: 3042..3048, node_index: NodeIndex(None), value: "test", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ], }, ), cases: [ MatchCase { range: 3055..3129, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 3060..3107, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 3070..3077, value: StringLiteralValue { inner: Single( StringLiteral { range: 3070..3077, node_index: NodeIndex(None), value: "label", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3079..3100, pattern: Some( MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 3079..3091, patterns: [ MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 3079..3084, cls: Name( ExprName { node_index: NodeIndex(None), range: 3079..3082, id: Name("str"), ctx: Load, }, ), arguments: PatternArguments { range: 3082..3084, node_index: NodeIndex(None), patterns: [], keywords: [], }, }, ), MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 3087..3091, value: None, }, ), ], }, ), ), name: Some( Identifier { id: Name("label"), range: 3095..3100, node_index: NodeIndex(None), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3117..3129, value: Call( ExprCall { node_index: NodeIndex(None), range: 3117..3129, func: Name( ExprName { node_index: NodeIndex(None), range: 3117..3122, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 3122..3129, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 3123..3128, id: Name("label"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3130..3170, subject: Name( ExprName { node_index: NodeIndex(None), range: 3136..3137, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3143..3170, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 3148..3155, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3149..3150, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3149..3150, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3152..3153, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3152..3153, value: Int( 1, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 3165..3170, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 3165..3166, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3169..3170, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3171..3211, subject: Name( ExprName { node_index: NodeIndex(None), range: 3177..3178, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3184..3211, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 3189..3196, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3190..3191, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3190..3191, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3193..3194, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3193..3194, value: Int( 1, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 3206..3211, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 3206..3207, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3210..3211, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3212..3249, subject: Name( ExprName { node_index: NodeIndex(None), range: 3218..3219, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3225..3249, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 3230..3234, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3231..3232, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3231..3232, value: Int( 0, ), }, ), }, ), ], }, ), guard: None, body: [ Assign( StmtAssign { node_index: NodeIndex(None), range: 3244..3249, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 3244..3245, id: Name("y"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3248..3249, value: Int( 0, ), }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3250..3284, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3256..3258, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3256..3257, id: Name("x"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 3264..3284, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3269..3270, pattern: None, name: Some( Identifier { id: Name("z"), range: 3269..3270, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 3280..3284, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3285..3321, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3291..3295, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3291..3292, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3294..3295, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 3301..3321, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3306..3307, pattern: None, name: Some( Identifier { id: Name("z"), range: 3306..3307, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 3317..3321, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3322..3359, subject: Tuple( ExprTuple { node_index: NodeIndex(None), range: 3328..3333, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 3328..3329, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 3331..3332, id: Name("y"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), cases: [ MatchCase { range: 3339..3359, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3344..3345, pattern: None, name: Some( Identifier { id: Name("z"), range: 3344..3345, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 3355..3359, }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3385..3475, subject: Name( ExprName { node_index: NodeIndex(None), range: 3391..3392, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3398..3420, node_index: NodeIndex(None), pattern: MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 3403..3407, value: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3417..3420, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3417..3420, }, ), }, ), ], }, MatchCase { range: 3425..3447, node_index: NodeIndex(None), pattern: MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 3430..3434, value: True, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3444..3447, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3444..3447, }, ), }, ), ], }, MatchCase { range: 3452..3475, node_index: NodeIndex(None), pattern: MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 3457..3462, value: False, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3472..3475, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3472..3475, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3497..3821, subject: Name( ExprName { node_index: NodeIndex(None), range: 3503..3504, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3510..3531, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3515..3518, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 3515..3518, value: Name( ExprName { node_index: NodeIndex(None), range: 3515..3516, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 3517..3518, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3528..3531, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3528..3531, }, ), }, ), ], }, MatchCase { range: 3536..3559, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3541..3546, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 3541..3546, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 3541..3544, value: Name( ExprName { node_index: NodeIndex(None), range: 3541..3542, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 3543..3544, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("c"), range: 3545..3546, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3556..3559, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3556..3559, }, ), }, ), ], }, MatchCase { range: 3564..3584, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3569..3571, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 3569..3571, value: StringLiteralValue { inner: Single( StringLiteral { range: 3569..3571, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3581..3584, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3581..3584, }, ), }, ), ], }, MatchCase { range: 3589..3610, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3594..3597, value: BytesLiteral( ExprBytesLiteral { node_index: NodeIndex(None), range: 3594..3597, value: BytesLiteralValue { inner: Single( BytesLiteral { range: 3594..3597, node_index: NodeIndex(None), value: [], flags: BytesLiteralFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3607..3610, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3607..3610, }, ), }, ), ], }, MatchCase { range: 3615..3634, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3620..3621, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3620..3621, value: Int( 1, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3631..3634, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3631..3634, }, ), }, ), ], }, MatchCase { range: 3639..3660, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3644..3647, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3644..3647, value: Float( 1.0, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3657..3660, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3657..3660, }, ), }, ), ], }, MatchCase { range: 3665..3687, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3670..3674, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3670..3674, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3684..3687, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3684..3687, }, ), }, ), ], }, MatchCase { range: 3692..3716, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3697..3703, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 3697..3703, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3697..3698, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3701..3703, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3713..3716, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3713..3716, }, ), }, ), ], }, MatchCase { range: 3721..3741, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3726..3728, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 3726..3728, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3727..3728, value: Int( 1, ), }, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3738..3741, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3738..3741, }, ), }, ), ], }, MatchCase { range: 3746..3767, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3751..3754, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 3751..3754, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3752..3754, value: Float( 1.0, ), }, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3764..3767, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3764..3767, }, ), }, ), ], }, MatchCase { range: 3772..3795, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3777..3782, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 3777..3782, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3778..3782, value: Int( 1, ), }, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3792..3795, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3792..3795, }, ), }, ), ], }, MatchCase { range: 3800..3821, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3806..3807, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3806..3807, value: Int( 1, ), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3818..3821, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3818..3821, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3840..3927, subject: Name( ExprName { node_index: NodeIndex(None), range: 3846..3847, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3853..3876, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 3858..3863, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3858..3859, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3858..3859, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3862..3863, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3862..3863, value: Int( 2, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3873..3876, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3873..3876, }, ), }, ), ], }, MatchCase { range: 3881..3927, node_index: NodeIndex(None), pattern: MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 3886..3914, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3886..3888, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 3886..3888, value: StringLiteralValue { inner: Single( StringLiteral { range: 3886..3888, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3891..3894, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3891..3894, value: Float( 1.1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3897..3899, value: UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 3897..3899, op: USub, operand: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3898..3899, value: Int( 1, ), }, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3902..3908, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 3902..3908, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3902..3903, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 3906..3908, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 3911..3914, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 3911..3914, value: Name( ExprName { node_index: NodeIndex(None), range: 3911..3912, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 3913..3914, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3924..3927, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3924..3927, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3946..3978, subject: Name( ExprName { node_index: NodeIndex(None), range: 3952..3953, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3959..3978, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3964..3965, pattern: None, name: Some( Identifier { id: Name("a"), range: 3964..3965, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 3975..3978, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 3975..3978, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 3979..4016, subject: Name( ExprName { node_index: NodeIndex(None), range: 3985..3986, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 3992..4016, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3997..4003, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 3997..3998, pattern: None, name: Some( Identifier { id: Name("a"), range: 3997..3998, node_index: NodeIndex(None), }, ), }, ), ), name: Some( Identifier { id: Name("b"), range: 4002..4003, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4013..4016, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4013..4016, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4017..4157, subject: Name( ExprName { node_index: NodeIndex(None), range: 4023..4024, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 4030..4060, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4035..4047, pattern: Some( MatchOr( PatternMatchOr { node_index: NodeIndex(None), range: 4035..4040, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4035..4036, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4035..4036, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4039..4040, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4039..4040, value: Int( 2, ), }, ), }, ), ], }, ), ), name: Some( Identifier { id: Name("two"), range: 4044..4047, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4057..4060, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4057..4060, }, ), }, ), ], }, MatchCase { range: 4065..4096, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4070..4083, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4070..4076, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4070..4076, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4070..4071, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4074..4076, value: Complex { real: 0.0, imag: 3.0, }, }, ), }, ), }, ), ), name: Some( Identifier { id: Name("sum"), range: 4080..4083, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4093..4096, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4093..4096, }, ), }, ), ], }, MatchCase { range: 4101..4128, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4106..4115, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4106..4109, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 4106..4109, value: Name( ExprName { node_index: NodeIndex(None), range: 4106..4107, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 4108..4109, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ), name: Some( Identifier { id: Name("ab"), range: 4113..4115, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4125..4128, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4125..4128, }, ), }, ), ], }, MatchCase { range: 4133..4157, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4138..4144, pattern: Some( MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4138..4139, pattern: None, name: None, }, ), ), name: Some( Identifier { id: Name("x"), range: 4143..4144, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4154..4157, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4154..4157, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4158..4190, subject: Name( ExprName { node_index: NodeIndex(None), range: 4164..4165, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 4171..4190, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4176..4177, pattern: None, name: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4187..4190, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4187..4190, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4215..4466, subject: Name( ExprName { node_index: NodeIndex(None), range: 4221..4222, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 4228..4253, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4233..4240, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4233..4234, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4233..4234, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4236..4237, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4236..4237, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4239..4240, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4239..4240, value: Int( 3, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4250..4253, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4250..4253, }, ), }, ), ], }, MatchCase { range: 4258..4286, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4263..4273, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4264..4265, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4264..4265, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4267..4268, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4267..4268, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4270..4271, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4270..4271, value: Int( 3, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4283..4286, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4283..4286, }, ), }, ), ], }, MatchCase { range: 4291..4331, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4296..4318, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4297..4303, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4297..4303, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4297..4298, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4301..4303, value: Complex { real: 0.0, imag: 2.0, }, }, ), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4305..4306, pattern: None, name: Some( Identifier { id: Name("a"), range: 4305..4306, node_index: NodeIndex(None), }, ), }, ), MatchSingleton( PatternMatchSingleton { node_index: NodeIndex(None), range: 4308..4312, value: None, }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4314..4317, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 4314..4317, value: Name( ExprName { node_index: NodeIndex(None), range: 4314..4315, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 4316..4317, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4328..4331, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4328..4331, }, ), }, ), ], }, MatchCase { range: 4336..4370, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4341..4357, pattern: Some( MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4341..4352, patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4342..4348, pattern: Some( MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4342..4343, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4342..4343, value: Int( 1, ), }, ), }, ), ), name: Some( Identifier { id: Name("X"), range: 4347..4348, node_index: NodeIndex(None), }, ), }, ), MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4350..4351, pattern: None, name: Some( Identifier { id: Name("b"), range: 4350..4351, node_index: NodeIndex(None), }, ), }, ), ], }, ), ), name: Some( Identifier { id: Name("S"), range: 4356..4357, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4367..4370, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4367..4370, }, ), }, ), ], }, MatchCase { range: 4375..4407, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4380..4394, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4381..4382, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4381..4382, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4384..4385, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4384..4385, value: Int( 2, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4387..4393, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 4387..4393, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4387..4388, value: Int( 3, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4391..4393, value: Complex { real: 0.0, imag: 1.0, }, }, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4404..4407, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4404..4407, }, ), }, ), ], }, MatchCase { range: 4412..4440, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4417..4427, patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4418..4423, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4419..4420, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4419..4420, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4421..4422, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4421..4422, value: Int( 2, ), }, ), }, ), ], }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4425..4426, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4425..4426, value: Int( 3, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4437..4440, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4437..4440, }, ), }, ), ], }, MatchCase { range: 4445..4466, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4450..4453, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4451..4452, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4451..4452, value: Int( 1, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4463..4466, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4463..4466, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4487..4616, subject: Name( ExprName { node_index: NodeIndex(None), range: 4493..4494, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 4500..4521, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4505..4508, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 4505..4507, name: Some( Identifier { id: Name("a"), range: 4506..4507, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4518..4521, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4518..4521, }, ), }, ), ], }, MatchCase { range: 4526..4547, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4531..4534, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 4531..4533, name: None, }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4544..4547, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4544..4547, }, ), }, ), ], }, MatchCase { range: 4552..4583, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4557..4570, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4558..4559, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4558..4559, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4561..4562, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4561..4562, value: Int( 2, ), }, ), }, ), MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 4564..4569, name: Some( Identifier { id: Name("rest"), range: 4565..4569, node_index: NodeIndex(None), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4580..4583, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4580..4583, }, ), }, ), ], }, MatchCase { range: 4588..4616, node_index: NodeIndex(None), pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4593..4603, patterns: [ MatchStar( PatternMatchStar { node_index: NodeIndex(None), range: 4594..4596, name: None, }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4598..4599, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4598..4599, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4601..4602, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4601..4602, value: Int( 2, ), }, ), }, ), ], }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4613..4616, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4613..4616, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4638..4910, subject: Name( ExprName { node_index: NodeIndex(None), range: 4644..4645, id: Name("x"), ctx: Load, }, ), cases: [ MatchCase { range: 4651..4676, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4656..4663, cls: Name( ExprName { node_index: NodeIndex(None), range: 4656..4661, id: Name("Point"), ctx: Load, }, ), arguments: PatternArguments { range: 4661..4663, node_index: NodeIndex(None), patterns: [], keywords: [], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4673..4676, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4673..4676, }, ), }, ), ], }, MatchCase { range: 4681..4710, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4686..4697, cls: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 4686..4695, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 4686..4689, value: Name( ExprName { node_index: NodeIndex(None), range: 4686..4687, id: Name("a"), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 4688..4689, node_index: NodeIndex(None), }, ctx: Load, }, ), attr: Identifier { id: Name("Point"), range: 4690..4695, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: PatternArguments { range: 4695..4697, node_index: NodeIndex(None), patterns: [], keywords: [], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4707..4710, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4707..4710, }, ), }, ), ], }, MatchCase { range: 4715..4745, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4720..4732, cls: Name( ExprName { node_index: NodeIndex(None), range: 4720..4727, id: Name("Point2D"), ctx: Load, }, ), arguments: PatternArguments { range: 4727..4732, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 4728..4731, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 4728..4729, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4730..4731, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4730..4731, value: Int( 0, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4742..4745, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4742..4745, }, ), }, ), ], }, MatchCase { range: 4750..4786, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4755..4773, cls: Name( ExprName { node_index: NodeIndex(None), range: 4755..4762, id: Name("Point2D"), ctx: Load, }, ), arguments: PatternArguments { range: 4762..4773, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 4763..4766, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 4763..4764, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4765..4766, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4765..4766, value: Int( 0, ), }, ), }, ), }, PatternKeyword { range: 4768..4771, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 4768..4769, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4770..4771, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4770..4771, value: Int( 0, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4783..4786, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4783..4786, }, ), }, ), ], }, MatchCase { range: 4791..4822, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4796..4809, cls: Name( ExprName { node_index: NodeIndex(None), range: 4796..4803, id: Name("Point2D"), ctx: Load, }, ), arguments: PatternArguments { range: 4803..4809, node_index: NodeIndex(None), patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4804..4805, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4804..4805, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4807..4808, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4807..4808, value: Int( 1, ), }, ), }, ), ], keywords: [], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4819..4822, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4819..4822, }, ), }, ), ], }, MatchCase { range: 4827..4865, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4832..4852, cls: Name( ExprName { node_index: NodeIndex(None), range: 4832..4839, id: Name("Point2D"), ctx: Load, }, ), arguments: PatternArguments { range: 4839..4852, node_index: NodeIndex(None), patterns: [ MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4840..4846, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4841..4842, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4841..4842, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4844..4845, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4844..4845, value: Int( 1, ), }, ), }, ), ], }, ), ], keywords: [ PatternKeyword { range: 4848..4851, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 4848..4849, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4850..4851, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4850..4851, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4862..4865, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4862..4865, }, ), }, ), ], }, MatchCase { range: 4870..4910, node_index: NodeIndex(None), pattern: MatchClass( PatternMatchClass { node_index: NodeIndex(None), range: 4875..4897, cls: Name( ExprName { node_index: NodeIndex(None), range: 4875..4882, id: Name("Point2D"), ctx: Load, }, ), arguments: PatternArguments { range: 4882..4897, node_index: NodeIndex(None), patterns: [], keywords: [ PatternKeyword { range: 4883..4891, node_index: NodeIndex(None), attr: Identifier { id: Name("x"), range: 4883..4884, node_index: NodeIndex(None), }, pattern: MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 4885..4891, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4886..4887, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4886..4887, value: Int( 0, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4889..4890, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4889..4890, value: Int( 1, ), }, ), }, ), ], }, ), }, PatternKeyword { range: 4893..4896, node_index: NodeIndex(None), attr: Identifier { id: Name("y"), range: 4893..4894, node_index: NodeIndex(None), }, pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 4895..4896, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4895..4896, value: Int( 1, ), }, ), }, ), }, ], }, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4907..4910, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4907..4910, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 4934..5028, subject: Named( ExprNamed { node_index: NodeIndex(None), range: 4940..4946, target: Name( ExprName { node_index: NodeIndex(None), range: 4940..4941, id: Name("x"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 4945..4946, id: Name("b"), ctx: Load, }, ), }, ), cases: [ MatchCase { range: 4952..4976, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 4957..4963, keys: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 4958..4959, value: Int( 1, ), }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4961..4962, pattern: None, name: None, }, ), ], rest: None, }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 4973..4976, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 4973..4976, }, ), }, ), ], }, MatchCase { range: 4981..5028, node_index: NodeIndex(None), pattern: MatchMapping( PatternMatchMapping { node_index: NodeIndex(None), range: 4986..5015, keys: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 4987..4989, value: StringLiteralValue { inner: Single( StringLiteral { range: 4987..4989, node_index: NodeIndex(None), value: "", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 4994..4998, }, ), ], patterns: [ MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 4991..4992, pattern: None, name: Some( Identifier { id: Name("a"), range: 4991..4992, node_index: NodeIndex(None), }, ), }, ), MatchSequence( PatternMatchSequence { node_index: NodeIndex(None), range: 5000..5006, patterns: [ MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 5001..5002, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5001..5002, value: Int( 1, ), }, ), }, ), MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 5004..5005, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5004..5005, value: Int( 2, ), }, ), }, ), ], }, ), ], rest: Some( Identifier { id: Name("rest"), range: 5010..5014, node_index: NodeIndex(None), }, ), }, ), guard: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5025..5028, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5025..5028, }, ), }, ), ], }, ], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 5046..5106, subject: Name( ExprName { node_index: NodeIndex(None), range: 5052..5053, id: Name("y"), ctx: Load, }, ), cases: [ MatchCase { range: 5059..5080, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 5064..5065, pattern: None, name: Some( Identifier { id: Name("a"), range: 5064..5065, node_index: NodeIndex(None), }, ), }, ), guard: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 5069..5075, target: Name( ExprName { node_index: NodeIndex(None), range: 5069..5070, id: Name("b"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 5074..5075, id: Name("c"), ctx: Load, }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5077..5080, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5077..5080, }, ), }, ), ], }, MatchCase { range: 5085..5106, node_index: NodeIndex(None), pattern: MatchAs( PatternMatchAs { node_index: NodeIndex(None), range: 5090..5091, pattern: None, name: Some( Identifier { id: Name("e"), range: 5090..5091, node_index: NodeIndex(None), }, ), }, ), guard: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 5096..5101, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5096..5097, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5100..5101, value: Int( 2, ), }, ), ], }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 5103..5106, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 5103..5106, }, ), }, ), ], }, ], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5135..5150, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 5135..5150, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5135..5147, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5135..5143, left: Name( ExprName { node_index: NodeIndex(None), range: 5135..5140, id: Name("match"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 5142..5143, id: Name("a"), ctx: Load, }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5146..5147, id: Name("b"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 5149..5150, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5176..5193, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 5176..5193, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5176..5190, left: Name( ExprName { node_index: NodeIndex(None), range: 5176..5181, id: Name("match"), ctx: Load, }, ), op: Mult, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5184..5189, left: Name( ExprName { node_index: NodeIndex(None), range: 5184..5185, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5188..5189, id: Name("b"), ctx: Load, }, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 5192..5193, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5219..5236, value: Call( ExprCall { node_index: NodeIndex(None), range: 5219..5236, func: Name( ExprName { node_index: NodeIndex(None), range: 5219..5224, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5225..5236, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 5226..5232, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5227..5232, left: Name( ExprName { node_index: NodeIndex(None), range: 5227..5228, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5231..5232, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 5234..5235, id: Name("c"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5263..5279, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5263..5279, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5263..5275, left: Name( ExprName { node_index: NodeIndex(None), range: 5263..5268, id: Name("match"), ctx: Load, }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5270..5275, left: Name( ExprName { node_index: NodeIndex(None), range: 5270..5271, id: Name("a"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 5274..5275, id: Name("b"), ctx: Load, }, ), }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5278..5279, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5306..5324, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5306..5324, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5306..5320, left: Name( ExprName { node_index: NodeIndex(None), range: 5306..5311, id: Name("match"), ctx: Load, }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5314..5319, left: Name( ExprName { node_index: NodeIndex(None), range: 5314..5315, id: Name("a"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 5318..5319, id: Name("b"), ctx: Load, }, ), }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5323..5324, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5351..5369, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5351..5369, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 5351..5365, left: Call( ExprCall { node_index: NodeIndex(None), range: 5351..5361, func: Name( ExprName { node_index: NodeIndex(None), range: 5351..5356, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5357..5361, node_index: NodeIndex(None), args: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 5358..5360, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 5359..5360, id: Name("a"), ctx: Load, }, ), }, ), ], keywords: [], }, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 5364..5365, id: Name("b"), ctx: Load, }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 5368..5369, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5397..5407, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5397..5407, value: Call( ExprCall { node_index: NodeIndex(None), range: 5397..5405, func: Name( ExprName { node_index: NodeIndex(None), range: 5397..5402, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5403..5405, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 5406..5407, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5424..5436, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5424..5436, value: Call( ExprCall { node_index: NodeIndex(None), range: 5424..5434, func: Name( ExprName { node_index: NodeIndex(None), range: 5424..5429, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5430..5434, node_index: NodeIndex(None), args: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 5431..5433, elts: [], ctx: Load, parenthesized: true, }, ), ], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 5435..5436, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5455..5468, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5455..5468, value: Call( ExprCall { node_index: NodeIndex(None), range: 5455..5466, func: Name( ExprName { node_index: NodeIndex(None), range: 5455..5460, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5461..5466, node_index: NodeIndex(None), args: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 5462..5464, elts: [], ctx: Load, parenthesized: true, }, ), ], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 5467..5468, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5487..5498, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5487..5498, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 5487..5496, value: Name( ExprName { node_index: NodeIndex(None), range: 5487..5492, id: Name("match"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 5494..5495, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 5497..5498, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5516..5528, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5516..5528, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 5516..5526, value: Name( ExprName { node_index: NodeIndex(None), range: 5516..5521, id: Name("match"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 5523..5525, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 5523..5524, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 5527..5528, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5569..5583, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 5569..5583, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 5569..5581, value: Name( ExprName { node_index: NodeIndex(None), range: 5569..5574, id: Name("match"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 5576..5580, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 5577..5578, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 5582..5583, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5604..5621, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 5604..5621, value: Call( ExprCall { node_index: NodeIndex(None), range: 5604..5611, func: Name( ExprName { node_index: NodeIndex(None), range: 5604..5609, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5609..5611, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 5612..5620, lower: Some( Name( ExprName { node_index: NodeIndex(None), range: 5612..5613, id: Name("a"), ctx: Load, }, ), ), upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 5619..5620, id: Name("b"), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 5641..5660, test: Named( ExprNamed { node_index: NodeIndex(None), range: 5644..5654, target: Name( ExprName { node_index: NodeIndex(None), range: 5644..5649, id: Name("match"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5653..5654, value: Int( 1, ), }, ), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 5656..5660, }, ), ], elif_else_clauses: [], }, ), Match( StmtMatch { node_index: NodeIndex(None), range: 5661..5715, subject: Name( ExprName { node_index: NodeIndex(None), range: 5667..5672, id: Name("match"), ctx: Load, }, ), cases: [ MatchCase { range: 5678..5690, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 5683..5684, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5683..5684, value: Int( 1, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 5686..5690, }, ), ], }, MatchCase { range: 5695..5715, node_index: NodeIndex(None), pattern: MatchValue( PatternMatchValue { node_index: NodeIndex(None), range: 5700..5701, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5700..5701, value: Int( 2, ), }, ), }, ), guard: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 5711..5715, }, ), ], }, ], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 5716..5752, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 5716..5721, id: Name("match"), ctx: Store, }, ), ], value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 5724..5752, parameters: Some( Parameters { range: 5731..5736, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 5731..5736, node_index: NodeIndex(None), parameter: Parameter { range: 5731..5736, node_index: NodeIndex(None), name: Identifier { id: Name("query"), range: 5731..5736, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Compare( ExprCompare { node_index: NodeIndex(None), range: 5738..5752, left: Name( ExprName { node_index: NodeIndex(None), range: 5738..5743, id: Name("query"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 5747..5752, id: Name("event"), ctx: Load, }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 5753..5769, value: Call( ExprCall { node_index: NodeIndex(None), range: 5753..5769, func: Name( ExprName { node_index: NodeIndex(None), range: 5753..5758, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 5758..5769, node_index: NodeIndex(None), args: [ Call( ExprCall { node_index: NodeIndex(None), range: 5759..5768, func: Name( ExprName { node_index: NodeIndex(None), range: 5759..5764, id: Name("match"), ctx: Load, }, ), arguments: Arguments { range: 5764..5768, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 5765..5767, value: Int( 12, ), }, ), ], keywords: [], }, }, ), ], keywords: [], }, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__raise.py.snap000064400000000000000000000554761046102023000313370ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/raise.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..289, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 8..13, exc: None, cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 14..21, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 20..21, id: Name("a"), ctx: Load, }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 22..34, exc: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 28..34, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 29..30, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 32..33, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 35..46, exc: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 41..46, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 41..42, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 45..46, value: Int( 2, ), }, ), ], }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 47..60, exc: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 53..60, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 53..54, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 59..60, id: Name("b"), ctx: Load, }, ), ], }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 61..78, exc: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 67..78, parameters: Some( Parameters { range: 74..75, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 74..75, node_index: NodeIndex(None), parameter: Parameter { range: 74..75, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 74..75, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 77..78, id: Name("y"), ctx: Load, }, ), }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 79..92, exc: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 85..92, value: Name( ExprName { node_index: NodeIndex(None), range: 91..92, id: Name("x"), ctx: Load, }, ), }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 93..115, exc: Some( If( ExprIf { node_index: NodeIndex(None), range: 99..115, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 104..108, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 99..100, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 114..115, id: Name("y"), ctx: Load, }, ), }, ), ), cause: None, }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 138..152, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 144..145, id: Name("x"), ctx: Load, }, ), ), cause: Some( Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("a"), ctx: Load, }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 153..172, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 159..160, id: Name("x"), ctx: Load, }, ), ), cause: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 166..172, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 167..168, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("b"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 173..191, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 179..180, id: Name("x"), ctx: Load, }, ), ), cause: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 186..191, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 186..187, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 190..191, value: Int( 2, ), }, ), ], }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 192..212, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 198..199, id: Name("x"), ctx: Load, }, ), ), cause: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 205..212, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 205..206, id: Name("a"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 211..212, id: Name("b"), ctx: Load, }, ), ], }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 213..237, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 219..220, id: Name("x"), ctx: Load, }, ), ), cause: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 226..237, parameters: Some( Parameters { range: 233..234, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 233..234, node_index: NodeIndex(None), parameter: Parameter { range: 233..234, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 233..234, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("y"), ctx: Load, }, ), }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 238..258, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 244..245, id: Name("x"), ctx: Load, }, ), ), cause: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 251..258, value: Name( ExprName { node_index: NodeIndex(None), range: 257..258, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), Raise( StmtRaise { node_index: NodeIndex(None), range: 259..288, exc: Some( Name( ExprName { node_index: NodeIndex(None), range: 265..266, id: Name("x"), ctx: Load, }, ), ), cause: Some( If( ExprIf { node_index: NodeIndex(None), range: 272..288, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 277..281, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 272..273, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 287..288, id: Name("y"), ctx: Load, }, ), }, ), ), }, ), ], }, ) ``` valid_syntax@statement__return.py.snap000064400000000000000000000374211046102023000314620ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/return.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..167, body: [ Return( StmtReturn { node_index: NodeIndex(None), range: 0..6, value: None, }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 7..15, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 14..15, id: Name("x"), ctx: Load, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 16..29, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 23..29, elts: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 23..25, value: Name( ExprName { node_index: NodeIndex(None), range: 24..25, id: Name("x"), ctx: Load, }, ), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 27..29, value: Name( ExprName { node_index: NodeIndex(None), range: 28..29, id: Name("y"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 30..45, value: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 38..44, target: Name( ExprName { node_index: NodeIndex(None), range: 38..39, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 43..44, value: Int( 1, ), }, ), }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 46..57, value: Some( NoneLiteral( ExprNoneLiteral { node_index: NodeIndex(None), range: 53..57, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 58..72, value: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 65..72, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 65..66, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 71..72, id: Name("y"), ctx: Load, }, ), ], }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 73..85, value: Some( Compare( ExprCompare { node_index: NodeIndex(None), range: 80..85, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 80..81, value: Int( 1, ), }, ), ops: [ Lt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 84..85, value: Int( 2, ), }, ), ], }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 86..98, value: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 93..98, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 93..94, value: Int( 1, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 96..97, value: Int( 2, ), }, ), ], ctx: Load, parenthesized: false, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 99..112, value: Some( Call( ExprCall { node_index: NodeIndex(None), range: 106..112, func: Name( ExprName { node_index: NodeIndex(None), range: 106..110, id: Name("call"), ctx: Load, }, ), arguments: Arguments { range: 110..112, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 113..132, value: Some( Call( ExprCall { node_index: NodeIndex(None), range: 120..132, func: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 120..130, value: Name( ExprName { node_index: NodeIndex(None), range: 120..124, id: Name("attr"), ctx: Load, }, ), attr: Identifier { id: Name("value"), range: 125..130, node_index: NodeIndex(None), }, ctx: Load, }, ), arguments: Arguments { range: 130..132, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 133..147, value: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 140..147, value: Name( ExprName { node_index: NodeIndex(None), range: 146..147, id: Name("x"), ctx: Load, }, ), }, ), ), }, ), Return( StmtReturn { node_index: NodeIndex(None), range: 148..166, value: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 155..166, parameters: Some( Parameters { range: 162..163, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 162..163, node_index: NodeIndex(None), parameter: Parameter { range: 162..163, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 162..163, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("y"), ctx: Load, }, ), }, ), ), }, ), ], }, ) ``` valid_syntax@statement__simple.py.snap000064400000000000000000000247111046102023000314320ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/simple.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..172, body: [ Continue( StmtContinue { node_index: NodeIndex(None), range: 61..69, }, ), Break( StmtBreak { node_index: NodeIndex(None), range: 70..75, }, ), If( StmtIf { node_index: NodeIndex(None), range: 77..86, test: Name( ExprName { node_index: NodeIndex(None), range: 80..81, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 83..86, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 83..86, }, ), }, ), ], elif_else_clauses: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 87..100, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 90..94, value: true, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 96..100, }, ), ], elif_else_clauses: [], }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 101..102, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 101..102, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 104..105, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 104..105, value: Int( 2, ), }, ), }, ), Pass( StmtPass { node_index: NodeIndex(None), range: 107..111, }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 112..113, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 112..113, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 115..118, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 115..118, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 120..133, value: If( ExprIf { node_index: NodeIndex(None), range: 120..133, test: Name( ExprName { node_index: NodeIndex(None), range: 125..126, id: Name("b"), ctx: Load, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 120..121, id: Name("a"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 132..133, id: Name("c"), ctx: Load, }, ), }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 135..157, test: Name( ExprName { node_index: NodeIndex(None), range: 138..139, id: Name("c"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 141..142, value: Name( ExprName { node_index: NodeIndex(None), range: 141..142, id: Name("B"), ctx: Load, }, ), }, ), Delete( StmtDelete { node_index: NodeIndex(None), range: 144..149, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 148..149, id: Name("A"), ctx: Del, }, ), ], }, ), ], elif_else_clauses: [ ElifElseClause { range: 150..157, node_index: NodeIndex(None), test: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 156..157, value: Name( ExprName { node_index: NodeIndex(None), range: 156..157, id: Name("C"), ctx: Load, }, ), }, ), ], }, ], }, ), If( StmtIf { node_index: NodeIndex(None), range: 158..171, test: Name( ExprName { node_index: NodeIndex(None), range: 161..162, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 164..171, value: Yield( ExprYield { node_index: NodeIndex(None), range: 164..171, value: Some( Name( ExprName { node_index: NodeIndex(None), range: 170..171, id: Name("x"), ctx: Load, }, ), ), }, ), }, ), ], elif_else_clauses: [], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__try.py.snap000064400000000000000000003371671046102023000310520ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/try.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..1223, body: [ Try( StmtTry { node_index: NodeIndex(None), range: 0..28, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..12, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 9..12, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 13..28, node_index: NodeIndex(None), type_: None, name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 25..28, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 25..28, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 30..106, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 39..42, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 39..42, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 43..74, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 50..60, id: Name("Exception1"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 64..65, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 71..74, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 71..74, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 75..106, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 82..92, id: Name("Exception2"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 96..97, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 103..106, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 103..106, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 108..184, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 117..120, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 117..120, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 121..151, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 128..137, id: Name("Exception"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 141..142, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 148..151, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 148..151, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 152..167, node_index: NodeIndex(None), type_: None, name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 164..167, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 164..167, }, ), }, ), ], }, ), ], orelse: [], finalbody: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 181..184, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 181..184, }, ), }, ), ], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 186..228, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 195..198, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 195..198, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 199..214, node_index: NodeIndex(None), type_: None, name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 211..214, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 211..214, }, ), }, ), ], }, ), ], orelse: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 225..228, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 225..228, }, ), }, ), ], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 230..289, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 239..242, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 239..242, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 243..258, node_index: NodeIndex(None), type_: None, name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 255..258, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 255..258, }, ), }, ), ], }, ), ], orelse: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 269..272, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 269..272, }, ), }, ), ], finalbody: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 286..289, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 286..289, }, ), }, ), ], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 291..320, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 300..303, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 300..303, }, ), }, ), ], handlers: [], orelse: [], finalbody: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 317..320, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 317..320, }, ), }, ), ], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 322..365, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 331..334, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 331..334, }, ), }, ), ], handlers: [], orelse: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 345..348, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 345..348, }, ), }, ), ], finalbody: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 362..365, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 362..365, }, ), }, ), ], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 367..441, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 376..379, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 376..379, }, ), }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 380..409, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 388..394, id: Name("GroupA"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("eg"), range: 398..400, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 406..409, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 406..409, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 410..441, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 418..432, id: Name("ExceptionGroup"), ctx: Load, }, ), ), name: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 438..441, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 438..441, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 443..577, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 452..471, exc: Some( Call( ExprCall { node_index: NodeIndex(None), range: 458..471, func: Name( ExprName { node_index: NodeIndex(None), range: 458..468, id: Name("ValueError"), ctx: Load, }, ), arguments: Arguments { range: 468..471, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 469..470, value: Int( 1, ), }, ), ], keywords: [], }, }, ), ), cause: None, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 472..525, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 479..488, id: Name("TypeError"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 492..493, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 499..525, value: Call( ExprCall { node_index: NodeIndex(None), range: 499..525, func: Name( ExprName { node_index: NodeIndex(None), range: 499..504, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 504..525, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 505..524, value: FStringValue { inner: Single( FString( FString { range: 505..524, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 507..514, node_index: NodeIndex(None), value: "caught ", }, ), Interpolation( InterpolatedElement { range: 514..523, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 515..522, func: Name( ExprName { node_index: NodeIndex(None), range: 515..519, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 519..522, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 520..521, id: Name("e"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], keywords: [], }, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 526..577, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 533..540, id: Name("OSError"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 544..545, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 551..577, value: Call( ExprCall { node_index: NodeIndex(None), range: 551..577, func: Name( ExprName { node_index: NodeIndex(None), range: 551..556, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 556..577, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 557..576, value: FStringValue { inner: Single( FString( FString { range: 557..576, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 559..566, node_index: NodeIndex(None), value: "caught ", }, ), Interpolation( InterpolatedElement { range: 566..575, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 567..574, func: Name( ExprName { node_index: NodeIndex(None), range: 567..571, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 571..574, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 572..573, id: Name("e"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], keywords: [], }, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 579..831, body: [ Raise( StmtRaise { node_index: NodeIndex(None), range: 588..669, exc: Some( Call( ExprCall { node_index: NodeIndex(None), range: 594..669, func: Name( ExprName { node_index: NodeIndex(None), range: 594..608, id: Name("ExceptionGroup"), ctx: Load, }, ), arguments: Arguments { range: 608..669, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 609..613, value: StringLiteralValue { inner: Single( StringLiteral { range: 609..613, node_index: NodeIndex(None), value: "eg", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), List( ExprList { node_index: NodeIndex(None), range: 615..668, elts: [ Call( ExprCall { node_index: NodeIndex(None), range: 616..629, func: Name( ExprName { node_index: NodeIndex(None), range: 616..626, id: Name("ValueError"), ctx: Load, }, ), arguments: Arguments { range: 626..629, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 627..628, value: Int( 1, ), }, ), ], keywords: [], }, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 631..643, func: Name( ExprName { node_index: NodeIndex(None), range: 631..640, id: Name("TypeError"), ctx: Load, }, ), arguments: Arguments { range: 640..643, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 641..642, value: Int( 2, ), }, ), ], keywords: [], }, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 645..655, func: Name( ExprName { node_index: NodeIndex(None), range: 645..652, id: Name("OSError"), ctx: Load, }, ), arguments: Arguments { range: 652..655, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 653..654, value: Int( 3, ), }, ), ], keywords: [], }, }, ), Call( ExprCall { node_index: NodeIndex(None), range: 657..667, func: Name( ExprName { node_index: NodeIndex(None), range: 657..664, id: Name("OSError"), ctx: Load, }, ), arguments: Arguments { range: 664..667, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 665..666, value: Int( 4, ), }, ), ], keywords: [], }, }, ), ], ctx: Load, }, ), ], keywords: [], }, }, ), ), cause: None, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 670..751, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 678..687, id: Name("TypeError"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 691..692, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 698..751, value: Call( ExprCall { node_index: NodeIndex(None), range: 698..751, func: Name( ExprName { node_index: NodeIndex(None), range: 698..703, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 703..751, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 704..750, value: FStringValue { inner: Single( FString( FString { range: 704..750, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 706..713, node_index: NodeIndex(None), value: "caught ", }, ), Interpolation( InterpolatedElement { range: 713..722, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 714..721, func: Name( ExprName { node_index: NodeIndex(None), range: 714..718, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 718..721, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 719..720, id: Name("e"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 722..735, node_index: NodeIndex(None), value: " with nested ", }, ), Interpolation( InterpolatedElement { range: 735..749, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 736..748, value: Name( ExprName { node_index: NodeIndex(None), range: 736..737, id: Name("e"), ctx: Load, }, ), attr: Identifier { id: Name("exceptions"), range: 738..748, node_index: NodeIndex(None), }, ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], keywords: [], }, }, ), }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 752..831, node_index: NodeIndex(None), type_: Some( Name( ExprName { node_index: NodeIndex(None), range: 760..767, id: Name("OSError"), ctx: Load, }, ), ), name: Some( Identifier { id: Name("e"), range: 771..772, node_index: NodeIndex(None), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 778..831, value: Call( ExprCall { node_index: NodeIndex(None), range: 778..831, func: Name( ExprName { node_index: NodeIndex(None), range: 778..783, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 783..831, node_index: NodeIndex(None), args: [ FString( ExprFString { node_index: NodeIndex(None), range: 784..830, value: FStringValue { inner: Single( FString( FString { range: 784..830, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 786..793, node_index: NodeIndex(None), value: "caught ", }, ), Interpolation( InterpolatedElement { range: 793..802, node_index: NodeIndex(None), expression: Call( ExprCall { node_index: NodeIndex(None), range: 794..801, func: Name( ExprName { node_index: NodeIndex(None), range: 794..798, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 798..801, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 799..800, id: Name("e"), ctx: Load, }, ), ], keywords: [], }, }, ), debug_text: None, conversion: None, format_spec: None, }, ), Literal( InterpolatedStringLiteralElement { range: 802..815, node_index: NodeIndex(None), value: " with nested ", }, ), Interpolation( InterpolatedElement { range: 815..829, node_index: NodeIndex(None), expression: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 816..828, value: Name( ExprName { node_index: NodeIndex(None), range: 816..817, id: Name("e"), ctx: Load, }, ), attr: Identifier { id: Name("exceptions"), range: 818..828, node_index: NodeIndex(None), }, ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), ), }, }, ), ], keywords: [], }, }, ), }, ), ], }, ), ], orelse: [], finalbody: [], is_star: true, }, ), Try( StmtTry { node_index: NodeIndex(None), range: 833..1075, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 842..846, }, ), ], handlers: [ ExceptHandler( ExceptHandlerExceptHandler { range: 847..875, node_index: NodeIndex(None), type_: Some( StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 854..865, value: StringLiteralValue { inner: Single( StringLiteral { range: 854..865, node_index: NodeIndex(None), value: "exception", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 871..875, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 876..894, node_index: NodeIndex(None), type_: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 883..884, value: Int( 1, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 890..894, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 895..916, node_index: NodeIndex(None), type_: Some( BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 902..906, value: true, }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 912..916, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 917..939, node_index: NodeIndex(None), type_: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 924..929, left: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 924..925, value: Int( 1, ), }, ), op: Add, right: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 928..929, value: Int( 1, ), }, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 935..939, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 940..962, node_index: NodeIndex(None), type_: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 947..952, left: Name( ExprName { node_index: NodeIndex(None), range: 947..948, id: Name("a"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 951..952, id: Name("b"), ctx: Load, }, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 958..962, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 963..987, node_index: NodeIndex(None), type_: Some( BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 970..977, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 970..971, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 976..977, id: Name("y"), ctx: Load, }, ), ], }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 983..987, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 988..1012, node_index: NodeIndex(None), type_: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 995..1002, value: Name( ExprName { node_index: NodeIndex(None), range: 1001..1002, id: Name("x"), ctx: Load, }, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1008..1012, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 1013..1041, node_index: NodeIndex(None), type_: Some( Lambda( ExprLambda { node_index: NodeIndex(None), range: 1020..1031, parameters: Some( Parameters { range: 1027..1028, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1027..1028, node_index: NodeIndex(None), parameter: Parameter { range: 1027..1028, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 1027..1028, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 1030..1031, id: Name("x"), ctx: Load, }, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1037..1041, }, ), ], }, ), ExceptHandler( ExceptHandlerExceptHandler { range: 1042..1075, node_index: NodeIndex(None), type_: Some( If( ExprIf { node_index: NodeIndex(None), range: 1049..1065, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 1054..1058, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 1049..1050, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 1064..1065, id: Name("y"), ctx: Load, }, ), }, ), ), name: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1071..1075, }, ), ], }, ), ], orelse: [], finalbody: [], is_star: false, }, ), If( StmtIf { node_index: NodeIndex(None), range: 1077..1222, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 1080..1084, value: true, }, ), body: [ Try( StmtTry { node_index: NodeIndex(None), range: 1090..1133, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1103..1107, }, ), ], handlers: [], orelse: [], finalbody: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1129..1133, }, ), ], is_star: false, }, ), ], elif_else_clauses: [ ElifElseClause { range: 1208..1222, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1218..1222, }, ), ], }, ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__type.py.snap000064400000000000000000004375341046102023000312140ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/type.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..1828, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..12, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 9..12, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 13..31, name: Name( ExprName { node_index: NodeIndex(None), range: 18..19, id: Name("X"), ctx: Store, }, ), type_params: None, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 22..31, left: Name( ExprName { node_index: NodeIndex(None), range: 22..25, id: Name("int"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 28..31, id: Name("str"), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 32..60, name: Name( ExprName { node_index: NodeIndex(None), range: 37..38, id: Name("X"), ctx: Store, }, ), type_params: None, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 41..60, left: Name( ExprName { node_index: NodeIndex(None), range: 41..44, id: Name("int"), ctx: Load, }, ), op: BitOr, right: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 47..60, value: StringLiteralValue { inner: Single( StringLiteral { range: 47..60, node_index: NodeIndex(None), value: "ForwardRefY", flags: StringLiteralFlags { quote_style: Double, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 61..87, name: Name( ExprName { node_index: NodeIndex(None), range: 66..67, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 67..70, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 68..69, name: Identifier { id: Name("T"), range: 68..69, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 73..87, left: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("T"), ctx: Load, }, ), op: BitOr, right: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 77..87, value: Name( ExprName { node_index: NodeIndex(None), range: 77..81, id: Name("list"), ctx: Load, }, ), slice: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 82..86, value: Name( ExprName { node_index: NodeIndex(None), range: 82..83, id: Name("X"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 84..85, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 101..116, name: Name( ExprName { node_index: NodeIndex(None), range: 106..107, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 107..110, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 108..109, name: Identifier { id: Name("T"), range: 108..109, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 113..116, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 117..145, name: Name( ExprName { node_index: NodeIndex(None), range: 122..123, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 123..126, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 124..125, name: Identifier { id: Name("T"), range: 124..125, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 129..145, left: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 129..136, value: Name( ExprName { node_index: NodeIndex(None), range: 129..133, id: Name("list"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 134..135, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), op: BitOr, right: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 139..145, value: Name( ExprName { node_index: NodeIndex(None), range: 139..142, id: Name("set"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 143..144, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 146..178, name: Name( ExprName { node_index: NodeIndex(None), range: 151..152, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 152..165, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 153..154, name: Identifier { id: Name("T"), range: 153..154, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 156..159, name: Identifier { id: Name("Ts"), range: 157..159, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 161..164, name: Identifier { id: Name("P"), range: 163..164, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 168..178, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 169..170, id: Name("T"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 172..174, id: Name("Ts"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 176..177, id: Name("P"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 179..216, name: Name( ExprName { node_index: NodeIndex(None), range: 184..185, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 185..203, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 186..192, name: Identifier { id: Name("T"), range: 186..187, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 189..192, id: Name("int"), ctx: Load, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 194..197, name: Identifier { id: Name("Ts"), range: 195..197, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 199..202, name: Identifier { id: Name("P"), range: 201..202, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 206..216, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 207..208, id: Name("T"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 210..212, id: Name("Ts"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("P"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 217..261, name: Name( ExprName { node_index: NodeIndex(None), range: 222..223, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 223..248, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 224..237, name: Identifier { id: Name("T"), range: 224..225, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 227..237, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 228..231, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 233..236, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 239..242, name: Identifier { id: Name("Ts"), range: 240..242, node_index: NodeIndex(None), }, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 244..247, name: Identifier { id: Name("P"), range: 246..247, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 251..261, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 252..253, id: Name("T"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 255..257, id: Name("Ts"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 259..260, id: Name("P"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 262..287, name: Name( ExprName { node_index: NodeIndex(None), range: 267..268, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 268..277, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 269..276, name: Identifier { id: Name("T"), range: 269..270, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 273..276, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 280..287, left: Name( ExprName { node_index: NodeIndex(None), range: 280..281, id: Name("T"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 284..287, id: Name("str"), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 288..330, name: Name( ExprName { node_index: NodeIndex(None), range: 293..294, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 294..314, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 295..313, name: Identifier { id: Name("T"), range: 295..296, node_index: NodeIndex(None), }, bound: Some( BinOp( ExprBinOp { node_index: NodeIndex(None), range: 298..307, left: Name( ExprName { node_index: NodeIndex(None), range: 298..301, id: Name("int"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 304..307, id: Name("str"), ctx: Load, }, ), }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 310..313, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 317..330, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 317..324, left: Name( ExprName { node_index: NodeIndex(None), range: 317..318, id: Name("T"), ctx: Load, }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 321..324, id: Name("int"), ctx: Load, }, ), }, ), op: BitOr, right: Name( ExprName { node_index: NodeIndex(None), range: 327..330, id: Name("str"), ctx: Load, }, ), }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 331..384, name: Name( ExprName { node_index: NodeIndex(None), range: 336..337, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 337..361, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 338..360, name: Identifier { id: Name("Ts"), range: 339..341, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 344..360, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 345..360, value: Name( ExprName { node_index: NodeIndex(None), range: 345..350, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 351..359, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 351..354, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 356..359, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 364..384, value: Name( ExprName { node_index: NodeIndex(None), range: 364..369, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 370..383, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 370..373, id: Name("int"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 375..378, value: Name( ExprName { node_index: NodeIndex(None), range: 376..378, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 380..383, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 385..428, name: Name( ExprName { node_index: NodeIndex(None), range: 390..391, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 391..409, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 392..408, name: Identifier { id: Name("P"), range: 394..395, node_index: NodeIndex(None), }, default: Some( List( ExprList { node_index: NodeIndex(None), range: 398..408, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 399..402, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 404..407, id: Name("str"), ctx: Load, }, ), ], ctx: Load, }, ), ), }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 412..428, value: Name( ExprName { node_index: NodeIndex(None), range: 412..420, id: Name("Callable"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 421..427, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 421..422, id: Name("P"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 424..427, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 459..474, name: Name( ExprName { node_index: NodeIndex(None), range: 464..468, id: Name("type"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 471..474, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 475..491, name: Name( ExprName { node_index: NodeIndex(None), range: 480..485, id: Name("match"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 488..491, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 492..507, name: Name( ExprName { node_index: NodeIndex(None), range: 497..501, id: Name("case"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 504..507, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 533..548, name: Name( ExprName { node_index: NodeIndex(None), range: 538..541, id: Name("foo"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 544..548, id: Name("type"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 549..565, name: Name( ExprName { node_index: NodeIndex(None), range: 554..557, id: Name("foo"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 560..565, id: Name("match"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 566..581, name: Name( ExprName { node_index: NodeIndex(None), range: 571..574, id: Name("foo"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 577..581, id: Name("case"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 605..620, name: Name( ExprName { node_index: NodeIndex(None), range: 613..614, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 617..620, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 621..636, name: Name( ExprName { node_index: NodeIndex(None), range: 626..627, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 633..636, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 637..652, name: Name( ExprName { node_index: NodeIndex(None), range: 642..643, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 649..652, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 653..673, name: Name( ExprName { node_index: NodeIndex(None), range: 658..659, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 668..671, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 674..693, name: Name( ExprName { node_index: NodeIndex(None), range: 685..686, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 686..689, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 687..688, name: Identifier { id: Name("T"), range: 687..688, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 692..693, id: Name("T"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 694..714, name: Name( ExprName { node_index: NodeIndex(None), range: 699..700, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 707..710, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 708..709, name: Identifier { id: Name("T"), range: 708..709, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 713..714, id: Name("T"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 715..734, name: Name( ExprName { node_index: NodeIndex(None), range: 720..721, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 721..724, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 722..723, name: Identifier { id: Name("T"), range: 722..723, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 733..734, id: Name("T"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 756..768, name: Name( ExprName { node_index: NodeIndex(None), range: 761..762, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 765..768, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 770..782, name: Name( ExprName { node_index: NodeIndex(None), range: 775..776, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 779..782, id: Name("str"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 784..797, name: Name( ExprName { node_index: NodeIndex(None), range: 789..790, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 793..797, id: Name("type"), ctx: Load, }, ), }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 798..819, decorator_list: [], name: Identifier { id: Name("X"), range: 804..805, node_index: NodeIndex(None), }, type_params: None, arguments: None, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 807..819, name: Name( ExprName { node_index: NodeIndex(None), range: 812..813, id: Name("X"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 816..819, id: Name("int"), ctx: Load, }, ), }, ), ], }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 821..853, name: Name( ExprName { node_index: NodeIndex(None), range: 826..831, id: Name("Point"), ctx: Store, }, ), type_params: None, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 834..853, value: Name( ExprName { node_index: NodeIndex(None), range: 834..839, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 840..852, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 840..845, id: Name("float"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 847..852, id: Name("float"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 854..881, name: Name( ExprName { node_index: NodeIndex(None), range: 859..864, id: Name("Point"), ctx: Store, }, ), type_params: Some( TypeParams { range: 864..867, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 865..866, name: Identifier { id: Name("T"), range: 865..866, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 870..881, value: Name( ExprName { node_index: NodeIndex(None), range: 870..875, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 876..880, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 876..877, id: Name("T"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 879..880, id: Name("T"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 882..918, name: Name( ExprName { node_index: NodeIndex(None), range: 887..894, id: Name("IntFunc"), ctx: Store, }, ), type_params: Some( TypeParams { range: 894..899, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 895..898, name: Identifier { id: Name("P"), range: 897..898, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 902..918, value: Name( ExprName { node_index: NodeIndex(None), range: 902..910, id: Name("Callable"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 911..917, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 911..912, id: Name("P"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 914..917, id: Name("int"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 932..972, name: Name( ExprName { node_index: NodeIndex(None), range: 937..949, id: Name("LabeledTuple"), ctx: Store, }, ), type_params: Some( TypeParams { range: 949..954, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 950..953, name: Identifier { id: Name("Ts"), range: 951..953, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 957..972, value: Name( ExprName { node_index: NodeIndex(None), range: 957..962, id: Name("tuple"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 963..971, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 963..966, id: Name("str"), ctx: Load, }, ), Starred( ExprStarred { node_index: NodeIndex(None), range: 968..971, value: Name( ExprName { node_index: NodeIndex(None), range: 969..971, id: Name("Ts"), ctx: Load, }, ), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 989..1037, name: Name( ExprName { node_index: NodeIndex(None), range: 994..1010, id: Name("HashableSequence"), ctx: Store, }, ), type_params: Some( TypeParams { range: 1010..1023, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1011..1022, name: Identifier { id: Name("T"), range: 1011..1012, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 1014..1022, id: Name("Hashable"), ctx: Load, }, ), ), default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1026..1037, value: Name( ExprName { node_index: NodeIndex(None), range: 1026..1034, id: Name("Sequence"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 1035..1036, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 1060..1110, name: Name( ExprName { node_index: NodeIndex(None), range: 1065..1081, id: Name("IntOrStrSequence"), ctx: Store, }, ), type_params: Some( TypeParams { range: 1081..1096, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 1082..1095, name: Identifier { id: Name("T"), range: 1082..1083, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 1085..1095, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 1086..1089, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 1091..1094, id: Name("str"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: None, }, ), ], }, ), value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1099..1110, value: Name( ExprName { node_index: NodeIndex(None), range: 1099..1107, id: Name("Sequence"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 1108..1109, id: Name("T"), ctx: Load, }, ), ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1164..1178, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1164..1178, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1164..1175, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1164..1171, left: Name( ExprName { node_index: NodeIndex(None), range: 1164..1168, id: Name("type"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 1170..1171, id: Name("a"), ctx: Load, }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1174..1175, id: Name("b"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 1177..1178, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1203..1219, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1203..1219, elts: [ BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1203..1216, left: Name( ExprName { node_index: NodeIndex(None), range: 1203..1207, id: Name("type"), ctx: Load, }, ), op: Mult, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1210..1215, left: Name( ExprName { node_index: NodeIndex(None), range: 1210..1211, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1214..1215, id: Name("b"), ctx: Load, }, ), }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 1218..1219, id: Name("c"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1244..1260, value: Call( ExprCall { node_index: NodeIndex(None), range: 1244..1260, func: Name( ExprName { node_index: NodeIndex(None), range: 1244..1248, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1249..1260, node_index: NodeIndex(None), args: [ Starred( ExprStarred { node_index: NodeIndex(None), range: 1250..1256, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1251..1256, left: Name( ExprName { node_index: NodeIndex(None), range: 1251..1252, id: Name("a"), ctx: Load, }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1255..1256, id: Name("b"), ctx: Load, }, ), }, ), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 1258..1259, id: Name("c"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1286..1301, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1286..1301, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1286..1297, left: Name( ExprName { node_index: NodeIndex(None), range: 1286..1290, id: Name("type"), ctx: Load, }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1292..1297, left: Name( ExprName { node_index: NodeIndex(None), range: 1292..1293, id: Name("a"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 1296..1297, id: Name("b"), ctx: Load, }, ), }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1300..1301, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1327..1344, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1327..1344, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1327..1340, left: Name( ExprName { node_index: NodeIndex(None), range: 1327..1331, id: Name("type"), ctx: Load, }, ), op: Sub, right: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1334..1339, left: Name( ExprName { node_index: NodeIndex(None), range: 1334..1335, id: Name("a"), ctx: Load, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 1338..1339, id: Name("b"), ctx: Load, }, ), }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1343..1344, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1370..1387, value: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1370..1387, left: BinOp( ExprBinOp { node_index: NodeIndex(None), range: 1370..1383, left: Call( ExprCall { node_index: NodeIndex(None), range: 1370..1379, func: Name( ExprName { node_index: NodeIndex(None), range: 1370..1374, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1375..1379, node_index: NodeIndex(None), args: [ UnaryOp( ExprUnaryOp { node_index: NodeIndex(None), range: 1376..1378, op: USub, operand: Name( ExprName { node_index: NodeIndex(None), range: 1377..1378, id: Name("a"), ctx: Load, }, ), }, ), ], keywords: [], }, }, ), op: Mult, right: Name( ExprName { node_index: NodeIndex(None), range: 1382..1383, id: Name("b"), ctx: Load, }, ), }, ), op: Add, right: Name( ExprName { node_index: NodeIndex(None), range: 1386..1387, id: Name("c"), ctx: Load, }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1414..1423, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1414..1423, value: Call( ExprCall { node_index: NodeIndex(None), range: 1414..1421, func: Name( ExprName { node_index: NodeIndex(None), range: 1414..1418, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1419..1421, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 1422..1423, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1439..1450, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1439..1450, value: Call( ExprCall { node_index: NodeIndex(None), range: 1439..1448, func: Name( ExprName { node_index: NodeIndex(None), range: 1439..1443, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1444..1448, node_index: NodeIndex(None), args: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 1445..1447, elts: [], ctx: Load, parenthesized: true, }, ), ], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 1449..1450, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1468..1480, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1468..1480, value: Call( ExprCall { node_index: NodeIndex(None), range: 1468..1478, func: Name( ExprName { node_index: NodeIndex(None), range: 1468..1472, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1473..1478, node_index: NodeIndex(None), args: [ Tuple( ExprTuple { node_index: NodeIndex(None), range: 1474..1476, elts: [], ctx: Load, parenthesized: true, }, ), ], keywords: [], }, }, ), attr: Identifier { id: Name("a"), range: 1479..1480, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1498..1508, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1498..1508, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1498..1506, value: Name( ExprName { node_index: NodeIndex(None), range: 1498..1502, id: Name("type"), ctx: Load, }, ), slice: Name( ExprName { node_index: NodeIndex(None), range: 1504..1505, id: Name("a"), ctx: Load, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 1507..1508, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1525..1536, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1525..1536, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1525..1534, value: Name( ExprName { node_index: NodeIndex(None), range: 1525..1529, id: Name("type"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1531..1533, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 1531..1532, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: false, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 1535..1536, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1575..1588, value: Attribute( ExprAttribute { node_index: NodeIndex(None), range: 1575..1588, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1575..1586, value: Name( ExprName { node_index: NodeIndex(None), range: 1575..1579, id: Name("type"), ctx: Load, }, ), slice: Tuple( ExprTuple { node_index: NodeIndex(None), range: 1581..1585, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 1582..1583, id: Name("a"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ctx: Load, }, ), attr: Identifier { id: Name("b"), range: 1587..1588, node_index: NodeIndex(None), }, ctx: Load, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1608..1624, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 1608..1624, value: Call( ExprCall { node_index: NodeIndex(None), range: 1608..1614, func: Name( ExprName { node_index: NodeIndex(None), range: 1608..1612, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1612..1614, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), slice: Slice( ExprSlice { node_index: NodeIndex(None), range: 1615..1623, lower: Some( Name( ExprName { node_index: NodeIndex(None), range: 1615..1616, id: Name("a"), ctx: Load, }, ), ), upper: Some( Name( ExprName { node_index: NodeIndex(None), range: 1622..1623, id: Name("b"), ctx: Load, }, ), ), step: None, }, ), ctx: Load, }, ), }, ), If( StmtIf { node_index: NodeIndex(None), range: 1643..1661, test: Named( ExprNamed { node_index: NodeIndex(None), range: 1646..1655, target: Name( ExprName { node_index: NodeIndex(None), range: 1646..1650, id: Name("type"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1654..1655, value: Int( 1, ), }, ), }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 1657..1661, }, ), ], elif_else_clauses: [], }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1662..1697, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1662..1666, id: Name("type"), ctx: Store, }, ), ], value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 1669..1697, parameters: Some( Parameters { range: 1676..1681, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1676..1681, node_index: NodeIndex(None), parameter: Parameter { range: 1676..1681, node_index: NodeIndex(None), name: Identifier { id: Name("query"), range: 1676..1681, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Compare( ExprCompare { node_index: NodeIndex(None), range: 1683..1697, left: Name( ExprName { node_index: NodeIndex(None), range: 1683..1688, id: Name("query"), ctx: Load, }, ), ops: [ Eq, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 1692..1697, id: Name("event"), ctx: Load, }, ), ], }, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1698..1713, value: Call( ExprCall { node_index: NodeIndex(None), range: 1698..1713, func: Name( ExprName { node_index: NodeIndex(None), range: 1698..1703, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 1703..1713, node_index: NodeIndex(None), args: [ Call( ExprCall { node_index: NodeIndex(None), range: 1704..1712, func: Name( ExprName { node_index: NodeIndex(None), range: 1704..1708, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1708..1712, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1709..1711, value: Int( 12, ), }, ), ], keywords: [], }, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1714..1724, value: Call( ExprCall { node_index: NodeIndex(None), range: 1714..1724, func: Name( ExprName { node_index: NodeIndex(None), range: 1714..1718, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1718..1724, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 1719..1723, id: Name("type"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1725..1743, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1725..1726, id: Name("a"), ctx: Store, }, ), ], value: Compare( ExprCompare { node_index: NodeIndex(None), range: 1732..1741, left: Name( ExprName { node_index: NodeIndex(None), range: 1732..1736, id: Name("type"), ctx: Load, }, ), ops: [ In, ], comparators: [ Name( ExprName { node_index: NodeIndex(None), range: 1740..1741, id: Name("C"), ctx: Load, }, ), ], }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1744..1760, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1744..1745, id: Name("a"), ctx: Store, }, ), ], value: Call( ExprCall { node_index: NodeIndex(None), range: 1751..1758, func: Name( ExprName { node_index: NodeIndex(None), range: 1751..1755, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1755..1758, node_index: NodeIndex(None), args: [ Name( ExprName { node_index: NodeIndex(None), range: 1756..1757, id: Name("b"), ctx: Load, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1761..1778, value: Call( ExprCall { node_index: NodeIndex(None), range: 1761..1778, func: Name( ExprName { node_index: NodeIndex(None), range: 1761..1765, id: Name("type"), ctx: Load, }, ), arguments: Arguments { range: 1766..1778, node_index: NodeIndex(None), args: [], keywords: [ Keyword { range: 1769..1776, node_index: NodeIndex(None), arg: Some( Identifier { id: Name("X"), range: 1769..1770, node_index: NodeIndex(None), }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 1773..1776, id: Name("int"), ctx: Load, }, ), }, ], }, }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1779..1787, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1779..1783, id: Name("type"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1786..1787, value: Int( 1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1788..1800, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1788..1792, id: Name("type"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 1795..1796, id: Name("x"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1799..1800, value: Int( 1, ), }, ), }, ), Assign( StmtAssign { node_index: NodeIndex(None), range: 1801..1813, targets: [ Name( ExprName { node_index: NodeIndex(None), range: 1801..1802, id: Name("x"), ctx: Store, }, ), Name( ExprName { node_index: NodeIndex(None), range: 1805..1809, id: Name("type"), ctx: Store, }, ), ], value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 1812..1813, value: Int( 1, ), }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 1814..1828, value: Lambda( ExprLambda { node_index: NodeIndex(None), range: 1814..1828, parameters: Some( Parameters { range: 1821..1822, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 1821..1822, node_index: NodeIndex(None), parameter: Parameter { range: 1821..1822, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 1821..1822, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 1824..1828, id: Name("type"), ctx: Load, }, ), }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__while.py.snap000064400000000000000000000576371046102023000313450ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/while.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..314, body: [ While( StmtWhile { node_index: NodeIndex(None), range: 0..16, test: Name( ExprName { node_index: NodeIndex(None), range: 6..7, id: Name("x"), ctx: Load, }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 13..16, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 13..16, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 18..61, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 24..37, op: And, values: [ Compare( ExprCompare { node_index: NodeIndex(None), range: 25..30, left: Name( ExprName { node_index: NodeIndex(None), range: 25..26, id: Name("x"), ctx: Load, }, ), ops: [ Gt, ], comparators: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 29..30, value: Int( 1, ), }, ), ], }, ), Name( ExprName { node_index: NodeIndex(None), range: 36..37, id: Name("y"), ctx: Load, }, ), ], }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 43..47, }, ), ], orelse: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 58..61, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 58..61, }, ), }, ), ], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 63..152, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 69..76, op: And, values: [ Name( ExprName { node_index: NodeIndex(None), range: 69..70, id: Name("x"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 75..76, id: Name("y"), ctx: Load, }, ), ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 82..85, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 82..85, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 90..111, value: Call( ExprCall { node_index: NodeIndex(None), range: 90..111, func: Name( ExprName { node_index: NodeIndex(None), range: 90..95, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 95..111, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 96..110, value: StringLiteralValue { inner: Single( StringLiteral { range: 96..110, node_index: NodeIndex(None), value: "Hello World!", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), }, ), ], orelse: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 123..144, value: Call( ExprCall { node_index: NodeIndex(None), range: 123..144, func: Name( ExprName { node_index: NodeIndex(None), range: 123..128, id: Name("print"), ctx: Load, }, ), arguments: Arguments { range: 128..144, node_index: NodeIndex(None), args: [ StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), range: 129..143, value: StringLiteralValue { inner: Single( StringLiteral { range: 129..143, node_index: NodeIndex(None), value: "Olá, Mundo!", flags: StringLiteralFlags { quote_style: Single, prefix: Empty, triple_quoted: false, unclosed: false, }, }, ), }, }, ), ], keywords: [], }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 149..152, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 149..152, }, ), }, ), ], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 154..171, test: Named( ExprNamed { node_index: NodeIndex(None), range: 160..166, target: Name( ExprName { node_index: NodeIndex(None), range: 160..161, id: Name("a"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("b"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 168..171, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 168..171, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 172..197, test: BoolOp( ExprBoolOp { node_index: NodeIndex(None), range: 178..192, op: And, values: [ Named( ExprNamed { node_index: NodeIndex(None), range: 179..185, target: Name( ExprName { node_index: NodeIndex(None), range: 179..180, id: Name("a"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 184..185, id: Name("b"), ctx: Load, }, ), }, ), Name( ExprName { node_index: NodeIndex(None), range: 191..192, id: Name("c"), ctx: Load, }, ), ], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 194..197, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 194..197, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 198..220, test: Lambda( ExprLambda { node_index: NodeIndex(None), range: 204..215, parameters: Some( Parameters { range: 211..212, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 211..212, node_index: NodeIndex(None), parameter: Parameter { range: 211..212, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 211..212, node_index: NodeIndex(None), }, annotation: None, }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 214..215, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 217..220, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 217..220, }, ), }, ), ], orelse: [], }, ), While( StmtWhile { node_index: NodeIndex(None), range: 221..239, test: Await( ExprAwait { node_index: NodeIndex(None), range: 227..234, value: Name( ExprName { node_index: NodeIndex(None), range: 233..234, id: Name("x"), ctx: Load, }, ), }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 236..239, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 236..239, }, ), }, ), ], orelse: [], }, ), If( StmtIf { node_index: NodeIndex(None), range: 241..313, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 244..248, value: true, }, ), body: [ While( StmtWhile { node_index: NodeIndex(None), range: 254..298, test: Name( ExprName { node_index: NodeIndex(None), range: 260..261, id: Name("x"), ctx: Load, }, ), body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 271..275, }, ), ], orelse: [ Pass( StmtPass { node_index: NodeIndex(None), range: 294..298, }, ), ], }, ), ], elif_else_clauses: [ ElifElseClause { range: 299..313, node_index: NodeIndex(None), test: None, body: [ Pass( StmtPass { node_index: NodeIndex(None), range: 309..313, }, ), ], }, ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__with.py.snap000064400000000000000000000466451046102023000312050ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/valid/statement/with.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..361, body: [ With( StmtWith { node_index: NodeIndex(None), range: 137..151, is_async: false, items: [ WithItem { range: 142..146, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 142..146, id: Name("item"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 148..151, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 148..151, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 152..171, is_async: false, items: [ WithItem { range: 157..166, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 157..161, id: Name("item"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 165..166, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 168..171, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 168..171, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 172..194, is_async: false, items: [ WithItem { range: 177..182, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 177..182, id: Name("item1"), ctx: Load, }, ), optional_vars: None, }, WithItem { range: 184..189, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 184..189, id: Name("item2"), ctx: Load, }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 191..194, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 191..194, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 195..229, is_async: false, items: [ WithItem { range: 200..211, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 200..205, id: Name("item1"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 209..211, id: Name("f1"), ctx: Store, }, ), ), }, WithItem { range: 213..224, node_index: NodeIndex(None), context_expr: Name( ExprName { node_index: NodeIndex(None), range: 213..218, id: Name("item2"), ctx: Load, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 222..224, id: Name("f2"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 226..229, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 226..229, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 231..257, is_async: false, items: [ WithItem { range: 236..252, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 236..252, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 241..245, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 236..237, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 251..252, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: None, }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 254..257, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 254..257, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 258..289, is_async: false, items: [ WithItem { range: 263..284, node_index: NodeIndex(None), context_expr: If( ExprIf { node_index: NodeIndex(None), range: 263..279, test: BooleanLiteral( ExprBooleanLiteral { node_index: NodeIndex(None), range: 268..272, value: true, }, ), body: Name( ExprName { node_index: NodeIndex(None), range: 263..264, id: Name("x"), ctx: Load, }, ), orelse: Name( ExprName { node_index: NodeIndex(None), range: 278..279, id: Name("y"), ctx: Load, }, ), }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 283..284, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 286..289, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 286..289, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 313..334, is_async: false, items: [ WithItem { range: 318..329, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 318..324, func: Name( ExprName { node_index: NodeIndex(None), range: 318..322, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 322..324, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 328..329, id: Name("f"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 331..334, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 331..334, }, ), }, ), ], }, ), With( StmtWith { node_index: NodeIndex(None), range: 335..361, is_async: false, items: [ WithItem { range: 340..356, node_index: NodeIndex(None), context_expr: Call( ExprCall { node_index: NodeIndex(None), range: 340..346, func: Name( ExprName { node_index: NodeIndex(None), range: 340..344, id: Name("open"), ctx: Load, }, ), arguments: Arguments { range: 344..346, node_index: NodeIndex(None), args: [], keywords: [], }, }, ), optional_vars: Some( Attribute( ExprAttribute { node_index: NodeIndex(None), range: 350..356, value: Name( ExprName { node_index: NodeIndex(None), range: 350..351, id: Name("f"), ctx: Load, }, ), attr: Identifier { id: Name("attr"), range: 352..356, node_index: NodeIndex(None), }, ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 358..361, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 358..361, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@template_strings_py314.py.snap000064400000000000000000000150251046102023000322400ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/template_strings_py314.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..89, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 44..52, value: TString( ExprTString { node_index: NodeIndex(None), range: 44..52, value: TStringValue { inner: Single( TString { range: 44..52, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 46..51, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 47..50, id: Name("hey"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 53..63, value: TString( ExprTString { node_index: NodeIndex(None), range: 53..63, value: TStringValue { inner: Single( TString { range: 53..63, node_index: NodeIndex(None), elements: [ Interpolation( InterpolatedElement { range: 55..62, node_index: NodeIndex(None), expression: Name( ExprName { node_index: NodeIndex(None), range: 56..61, id: Name("there"), ctx: Load, }, ), debug_text: None, conversion: None, format_spec: None, }, ), ], flags: TStringFlags { quote_style: Single, prefix: Regular, triple_quoted: false, unclosed: false, }, }, ), }, }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 64..88, value: TString( ExprTString { node_index: NodeIndex(None), range: 64..88, value: TStringValue { inner: Single( TString { range: 64..88, node_index: NodeIndex(None), elements: [ Literal( InterpolatedStringLiteralElement { range: 68..85, node_index: NodeIndex(None), value: "what's\nhappening?", }, ), ], flags: TStringFlags { quote_style: Double, prefix: Regular, triple_quoted: true, unclosed: false, }, }, ), }, }, ), }, ), ], }, ) ``` valid_syntax@tuple_context_manager_py38.py.snap000064400000000000000000000070121046102023000331630ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/tuple_context_manager_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..85, body: [ With( StmtWith { node_index: NodeIndex(None), range: 43..84, is_async: false, items: [ WithItem { range: 48..79, node_index: NodeIndex(None), context_expr: Tuple( ExprTuple { node_index: NodeIndex(None), range: 48..72, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 52..55, id: Name("foo"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 59..62, id: Name("bar"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 66..69, id: Name("baz"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), optional_vars: Some( Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("tup"), ctx: Store, }, ), ), }, ], body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 81..84, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 81..84, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@type_param_default_py313.py.snap000064400000000000000000000202721046102023000325200ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/type_param_default_py313.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..112, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 44..65, name: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 50..59, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 51..58, name: Identifier { id: Name("T"), range: 51..52, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 55..58, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 62..65, id: Name("int"), ctx: Load, }, ), }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 66..87, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 70..71, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 71..80, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 72..79, name: Identifier { id: Name("T"), range: 72..73, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), parameters: Parameters { range: 80..82, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 84..87, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 84..87, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 88..111, decorator_list: [], name: Identifier { id: Name("C"), range: 94..95, node_index: NodeIndex(None), }, type_params: Some( TypeParams { range: 95..104, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 96..103, name: Identifier { id: Name("T"), range: 96..97, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 100..103, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), arguments: Some( Arguments { range: 104..106, node_index: NodeIndex(None), args: [], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 108..111, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 108..111, }, ), }, ), ], }, ), ], }, ) ``` valid_syntax@type_param_param_spec.py.snap000064400000000000000000000226061046102023000322520ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/type_param_param_spec.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..90, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..17, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..11, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 7..10, name: Identifier { id: Name("P"), range: 9..10, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 18..41, name: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 24..35, node_index: NodeIndex(None), type_params: [ ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 25..34, name: Identifier { id: Name("P"), range: 27..28, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 31..34, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 38..41, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 42..62, name: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 48..56, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 49..50, name: Identifier { id: Name("T"), range: 49..50, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 52..55, name: Identifier { id: Name("P"), range: 54..55, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 59..62, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 63..89, name: Name( ExprName { node_index: NodeIndex(None), range: 68..69, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 69..83, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 70..71, name: Identifier { id: Name("T"), range: 70..71, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ParamSpec( TypeParamParamSpec { node_index: NodeIndex(None), range: 73..82, name: Identifier { id: Name("P"), range: 75..76, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 79..82, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 86..89, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@type_param_type_var.py.snap000064400000000000000000000414401046102023000317660ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/type_param_type_var.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..147, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..15, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..9, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 7..8, name: Identifier { id: Name("T"), range: 7..8, node_index: NodeIndex(None), }, bound: None, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 12..15, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 16..37, name: Name( ExprName { node_index: NodeIndex(None), range: 21..22, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 22..31, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 23..30, name: Identifier { id: Name("T"), range: 23..24, node_index: NodeIndex(None), }, bound: None, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 27..30, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 34..37, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 38..64, name: Name( ExprName { node_index: NodeIndex(None), range: 43..44, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 44..58, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 45..57, name: Identifier { id: Name("T"), range: 45..46, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 48..51, id: Name("int"), ctx: Load, }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 54..57, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 61..64, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 65..98, name: Name( ExprName { node_index: NodeIndex(None), range: 70..71, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 71..92, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 72..91, name: Identifier { id: Name("T"), range: 72..73, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 75..85, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 76..79, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 81..84, id: Name("int"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 88..91, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 95..98, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 99..146, name: Name( ExprName { node_index: NodeIndex(None), range: 104..105, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 105..140, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 106..118, name: Identifier { id: Name("T"), range: 106..107, node_index: NodeIndex(None), }, bound: Some( Name( ExprName { node_index: NodeIndex(None), range: 109..112, id: Name("int"), ctx: Load, }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 115..118, id: Name("int"), ctx: Load, }, ), ), }, ), TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 120..139, name: Identifier { id: Name("U"), range: 120..121, node_index: NodeIndex(None), }, bound: Some( Tuple( ExprTuple { node_index: NodeIndex(None), range: 123..133, elts: [ Name( ExprName { node_index: NodeIndex(None), range: 124..127, id: Name("int"), ctx: Load, }, ), Name( ExprName { node_index: NodeIndex(None), range: 129..132, id: Name("int"), ctx: Load, }, ), ], ctx: Load, parenthesized: true, }, ), ), default: Some( Name( ExprName { node_index: NodeIndex(None), range: 136..139, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 143..146, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@type_param_type_var_tuple.py.snap000064400000000000000000000301601046102023000331740ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/type_param_type_var_tuple.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..115, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 0..17, name: Name( ExprName { node_index: NodeIndex(None), range: 5..6, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 6..11, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 7..10, name: Identifier { id: Name("Ts"), range: 8..10, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 14..17, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 18..41, name: Name( ExprName { node_index: NodeIndex(None), range: 23..24, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 24..35, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 25..34, name: Identifier { id: Name("Ts"), range: 26..28, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 31..34, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 38..41, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 42..66, name: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 48..60, node_index: NodeIndex(None), type_params: [ TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 49..59, name: Identifier { id: Name("Ts"), range: 50..52, node_index: NodeIndex(None), }, default: Some( Starred( ExprStarred { node_index: NodeIndex(None), range: 55..59, value: Name( ExprName { node_index: NodeIndex(None), range: 56..59, id: Name("int"), ctx: Load, }, ), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 63..66, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 67..87, name: Name( ExprName { node_index: NodeIndex(None), range: 72..73, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 73..81, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 74..75, name: Identifier { id: Name("T"), range: 74..75, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 77..80, name: Identifier { id: Name("Ts"), range: 78..80, node_index: NodeIndex(None), }, default: None, }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 84..87, id: Name("int"), ctx: Load, }, ), }, ), TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 88..114, name: Name( ExprName { node_index: NodeIndex(None), range: 93..94, id: Name("X"), ctx: Store, }, ), type_params: Some( TypeParams { range: 94..108, node_index: NodeIndex(None), type_params: [ TypeVar( TypeParamTypeVar { node_index: NodeIndex(None), range: 95..96, name: Identifier { id: Name("T"), range: 95..96, node_index: NodeIndex(None), }, bound: None, default: None, }, ), TypeVarTuple( TypeParamTypeVarTuple { node_index: NodeIndex(None), range: 98..107, name: Identifier { id: Name("Ts"), range: 99..101, node_index: NodeIndex(None), }, default: Some( Name( ExprName { node_index: NodeIndex(None), range: 104..107, id: Name("int"), ctx: Load, }, ), ), }, ), ], }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 111..114, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@type_stmt_py312.py.snap000064400000000000000000000020761046102023000307630ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..57, body: [ TypeAlias( StmtTypeAlias { node_index: NodeIndex(None), range: 44..56, name: Name( ExprName { node_index: NodeIndex(None), range: 49..50, id: Name("x"), ctx: Store, }, ), type_params: None, value: Name( ExprName { node_index: NodeIndex(None), range: 53..56, id: Name("int"), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@unparenthesized_named_expr_index_py39.py.snap000064400000000000000000000043421046102023000354010ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/unparenthesized_named_expr_index_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..53, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..52, value: Subscript( ExprSubscript { node_index: NodeIndex(None), range: 43..52, value: Name( ExprName { node_index: NodeIndex(None), range: 43..46, id: Name("lst"), ctx: Load, }, ), slice: Named( ExprNamed { node_index: NodeIndex(None), range: 47..51, target: Name( ExprName { node_index: NodeIndex(None), range: 47..48, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 50..51, value: Int( 1, ), }, ), }, ), ctx: Load, }, ), }, ), ], }, ) ``` valid_syntax@unparenthesized_named_expr_py39.py.snap000064400000000000000000000156211046102023000342140ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/unparenthesized_named_expr_py39.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..88, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 43..57, value: Set( ExprSet { node_index: NodeIndex(None), range: 43..57, elts: [ Named( ExprNamed { node_index: NodeIndex(None), range: 44..50, target: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 49..50, value: Int( 1, ), }, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 2, ), }, ), NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 55..56, value: Int( 3, ), }, ), ], }, ), }, ), Expr( StmtExpr { node_index: NodeIndex(None), range: 58..87, value: SetComp( ExprSetComp { node_index: NodeIndex(None), range: 58..87, elt: Named( ExprNamed { node_index: NodeIndex(None), range: 59..68, target: Name( ExprName { node_index: NodeIndex(None), range: 59..63, id: Name("last"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 67..68, id: Name("x"), ctx: Load, }, ), }, ), generators: [ Comprehension { range: 69..86, node_index: NodeIndex(None), target: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("x"), ctx: Store, }, ), iter: Call( ExprCall { node_index: NodeIndex(None), range: 78..86, func: Name( ExprName { node_index: NodeIndex(None), range: 78..83, id: Name("range"), ctx: Load, }, ), arguments: Arguments { range: 83..86, node_index: NodeIndex(None), args: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 84..85, value: Int( 3, ), }, ), ], keywords: [], }, }, ), ifs: [], is_async: false, }, ], }, ), }, ), ], }, ) ``` valid_syntax@valid_annotation_class.py.snap000064400000000000000000000317031046102023000324330ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..137, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 0..23, decorator_list: [], name: Identifier { id: Name("F"), range: 6..7, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 7..18, node_index: NodeIndex(None), args: [ Named( ExprNamed { node_index: NodeIndex(None), range: 8..17, target: Name( ExprName { node_index: NodeIndex(None), range: 8..9, id: Name("y"), ctx: Store, }, ), value: Name( ExprName { node_index: NodeIndex(None), range: 13..17, id: Name("list"), ctx: Load, }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 20..23, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 20..23, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 24..93, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 28..29, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 29..31, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 37..60, decorator_list: [], name: Identifier { id: Name("G"), range: 43..44, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 44..55, node_index: NodeIndex(None), args: [ Yield( ExprYield { node_index: NodeIndex(None), range: 46..53, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 52..53, value: Int( 1, ), }, ), ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 57..60, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 57..60, }, ), }, ), ], }, ), ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 65..93, decorator_list: [], name: Identifier { id: Name("H"), range: 71..72, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 72..88, node_index: NodeIndex(None), args: [ YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 74..86, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 85..86, value: Int( 1, ), }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 90..93, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 90..93, }, ), }, ), ], }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 94..136, is_async: true, decorator_list: [], name: Identifier { id: Name("f"), range: 104..105, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 105..107, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ ClassDef( StmtClassDef { node_index: NodeIndex(None), range: 113..136, decorator_list: [], name: Identifier { id: Name("G"), range: 119..120, node_index: NodeIndex(None), }, type_params: None, arguments: Some( Arguments { range: 120..131, node_index: NodeIndex(None), args: [ Await( ExprAwait { node_index: NodeIndex(None), range: 122..129, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 1, ), }, ), }, ), ], keywords: [], }, ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 133..136, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 133..136, }, ), }, ), ], }, ), ], }, ), ], }, ) ``` valid_syntax@valid_annotation_function_py313.py.snap000064400000000000000000000716321046102023000341170ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_function_py313.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..316, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 44..68, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 48..49, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 49..51, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 56..62, target: Name( ExprName { node_index: NodeIndex(None), range: 56..57, id: Name("y"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 61..62, value: Int( 3, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 65..68, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 65..68, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 69..94, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 73..74, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 74..89, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 75..88, node_index: NodeIndex(None), parameter: Parameter { range: 75..88, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 75..78, node_index: NodeIndex(None), }, annotation: Some( Named( ExprNamed { node_index: NodeIndex(None), range: 81..87, target: Name( ExprName { node_index: NodeIndex(None), range: 81..82, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 86..87, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 91..94, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 91..94, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 95..235, is_async: false, decorator_list: [], name: Identifier { id: Name("outer"), range: 99..104, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 104..106, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 112..136, is_async: false, decorator_list: [], name: Identifier { id: Name("i"), range: 116..117, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 117..131, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 118..130, node_index: NodeIndex(None), parameter: Parameter { range: 118..130, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 118..119, node_index: NodeIndex(None), }, annotation: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 122..129, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 128..129, value: Int( 1, ), }, ), ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 133..136, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 133..136, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 141..166, is_async: false, decorator_list: [], name: Identifier { id: Name("k"), range: 145..146, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 146..148, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Yield( ExprYield { node_index: NodeIndex(None), range: 153..160, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 159..160, value: Int( 1, ), }, ), ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 163..166, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 163..166, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 171..200, is_async: false, decorator_list: [], name: Identifier { id: Name("m"), range: 175..176, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 176..195, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 177..194, node_index: NodeIndex(None), parameter: Parameter { range: 177..194, node_index: NodeIndex(None), name: Identifier { id: Name("x"), range: 177..178, node_index: NodeIndex(None), }, annotation: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 181..193, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 192..193, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 197..200, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 197..200, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 205..235, is_async: false, decorator_list: [], name: Identifier { id: Name("o"), range: 209..210, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 210..212, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 217..229, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 228..229, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 232..235, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 232..235, }, ), }, ), ], }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 236..315, is_async: true, decorator_list: [], name: Identifier { id: Name("outer"), range: 246..251, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 251..253, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 259..284, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 263..264, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 264..266, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 271..278, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 277..278, value: Int( 1, ), }, ), }, ), ), body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 281..284, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 281..284, }, ), }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 289..315, is_async: false, decorator_list: [], name: Identifier { id: Name("g"), range: 293..294, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 294..310, node_index: NodeIndex(None), posonlyargs: [], args: [ ParameterWithDefault { range: 295..309, node_index: NodeIndex(None), parameter: Parameter { range: 295..309, node_index: NodeIndex(None), name: Identifier { id: Name("arg"), range: 295..298, node_index: NodeIndex(None), }, annotation: Some( Await( ExprAwait { node_index: NodeIndex(None), range: 301..308, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 307..308, value: Int( 1, ), }, ), }, ), ), }, default: None, }, ], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 312..315, value: EllipsisLiteral( ExprEllipsisLiteral { node_index: NodeIndex(None), range: 312..315, }, ), }, ), ], }, ), ], }, ), ], }, ) ``` valid_syntax@valid_annotation_py313.py.snap000064400000000000000000000204511046102023000322030ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_py313.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..144, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 44..55, target: Name( ExprName { node_index: NodeIndex(None), range: 44..45, id: Name("a"), ctx: Store, }, ), annotation: Named( ExprNamed { node_index: NodeIndex(None), range: 48..54, target: Name( ExprName { node_index: NodeIndex(None), range: 48..49, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 53..54, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 56..107, is_async: false, decorator_list: [], name: Identifier { id: Name("outer"), range: 60..65, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 65..67, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 73..85, target: Name( ExprName { node_index: NodeIndex(None), range: 73..74, id: Name("b"), ctx: Store, }, ), annotation: Yield( ExprYield { node_index: NodeIndex(None), range: 77..84, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 83..84, value: Int( 1, ), }, ), ), }, ), value: None, simple: true, }, ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 90..107, target: Name( ExprName { node_index: NodeIndex(None), range: 90..91, id: Name("c"), ctx: Store, }, ), annotation: YieldFrom( ExprYieldFrom { node_index: NodeIndex(None), range: 94..106, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 105..106, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), ], }, ), FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 108..143, is_async: true, decorator_list: [], name: Identifier { id: Name("outer"), range: 118..123, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 123..125, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), range: 131..143, target: Name( ExprName { node_index: NodeIndex(None), range: 131..132, id: Name("d"), ctx: Store, }, ), annotation: Await( ExprAwait { node_index: NodeIndex(None), range: 135..142, value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 141..142, value: Int( 1, ), }, ), }, ), value: None, simple: true, }, ), ], }, ), ], }, ) ``` valid_syntax@valid_future_feature.py.snap000064400000000000000000000024051046102023000321160ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/valid_future_feature.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..35, body: [ ImportFrom( StmtImportFrom { node_index: NodeIndex(None), range: 0..34, module: Some( Identifier { id: Name("__future__"), range: 5..15, node_index: NodeIndex(None), }, ), names: [ Alias { range: 23..34, node_index: NodeIndex(None), name: Identifier { id: Name("annotations"), range: 23..34, node_index: NodeIndex(None), }, asname: None, }, ], level: 0, is_lazy: false, }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots/valid_syntax@walrus_py38.py.snap000064400000000000000000000026271046102023000301770ustar00--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/walrus_py38.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..54, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 45..53, value: Named( ExprNamed { node_index: NodeIndex(None), range: 46..52, target: Name( ExprName { node_index: NodeIndex(None), range: 46..47, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 51..52, value: Int( 1, ), }, ), }, ), }, ), ], }, ) ``` valid_syntax@yield_after_comma_parenthesized.py.snap000064400000000000000000000070441046102023000343060ustar00ast_serialize-0.13.1/crates/ruff_python_parser/tests/snapshots--- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/ok/yield_after_comma_parenthesized.py --- ## AST ``` Module( ModModule { node_index: NodeIndex(None), range: 0..22, body: [ FunctionDef( StmtFunctionDef { node_index: NodeIndex(None), range: 0..21, is_async: false, decorator_list: [], name: Identifier { id: Name("f"), range: 4..5, node_index: NodeIndex(None), }, type_params: None, parameters: Parameters { range: 5..7, node_index: NodeIndex(None), posonlyargs: [], args: [], vararg: None, kwonlyargs: [], kwarg: None, }, returns: None, body: [ Expr( StmtExpr { node_index: NodeIndex(None), range: 9..21, value: Tuple( ExprTuple { node_index: NodeIndex(None), range: 9..21, elts: [ NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 9..10, value: Int( 1, ), }, ), Yield( ExprYield { node_index: NodeIndex(None), range: 13..20, value: Some( NumberLiteral( ExprNumberLiteral { node_index: NodeIndex(None), range: 19..20, value: Int( 1, ), }, ), ), }, ), ], ctx: Load, parenthesized: false, }, ), }, ), ], }, ), ], }, ) ``` ast_serialize-0.13.1/crates/ruff_python_trivia/Cargo.toml000064400000000000000000000011561046102023000205010ustar00[package] name = "ruff_python_trivia" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [lib] [dependencies] ruff_source_file = { workspace = true } ruff_text_size = { workspace = true } itertools = { workspace = true } rustc-hash = { workspace = true } unicode-ident = { workspace = true } [lints] workspace = true ast_serialize-0.13.1/crates/ruff_python_trivia/README.md000064400000000000000000000010421046102023000200220ustar00 # ruff_python_trivia This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_python_trivia). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_python_trivia/src/comment_ranges.rs000064400000000000000000000222601046102023000227060ustar00use std::fmt::{Debug, Formatter}; use std::ops::Deref; use itertools::Itertools; use rustc_hash::FxHashSet; use ruff_source_file::LineRanges; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::{has_leading_content, has_trailing_content, is_python_whitespace}; /// Token-derived range indexes shared by comment placement and formatting. #[derive(Clone, Default)] pub struct TriviaRanges { comments: CommentRanges, parenthesized_expressions: ParenthesizedExpressions, } impl TriviaRanges { /// Creates a combined set of token-derived range indexes. pub fn new( comments: CommentRanges, parenthesized_expressions: ParenthesizedExpressions, ) -> Self { Self { comments, parenthesized_expressions, } } /// Returns the indexed comment ranges. pub fn comments(&self) -> &CommentRanges { &self.comments } /// Returns the indexed parenthesized expression ranges. pub fn parenthesized(&self) -> &ParenthesizedExpressions { &self.parenthesized_expressions } } impl Debug for TriviaRanges { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.comments.fmt(f) } } /// Index of source ranges enclosed by matching parentheses. #[derive(Clone, Default)] pub struct ParenthesizedExpressions { ranges: FxHashSet, } impl ParenthesizedExpressions { /// Creates an index from parenthesized expression ranges. pub fn new(ranges: FxHashSet) -> Self { Self { ranges } } /// Returns `true` if the index contains `range`. pub fn contains(&self, range: TextRange) -> bool { self.ranges.contains(&range) } } /// Stores the ranges of comments sorted by [`TextRange::start`] in increasing order. No two ranges /// are overlapping. #[derive(Clone, Default)] pub struct CommentRanges { raw: Vec, } impl CommentRanges { pub fn new(ranges: Vec) -> Self { Self { raw: ranges } } /// Returns `true` if the given range intersects with any comment range. pub fn intersects(&self, target: TextRange) -> bool { self.raw .binary_search_by(|range| { if target.intersect(*range).is_some() { std::cmp::Ordering::Equal } else if range.end() < target.start() { std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater } }) .is_ok() } /// Returns the comments who are within the range pub fn comments_in_range(&self, range: TextRange) -> &[TextRange] { let start = self .raw .partition_point(|comment| comment.start() < range.start()); // We expect there are few comments, so switching to find should be faster match self.raw[start..] .iter() .find_position(|comment| comment.end() > range.end()) { Some((in_range, _element)) => &self.raw[start..start + in_range], None => &self.raw[start..], } } /// Returns `true` if a statement or expression includes at least one comment. pub fn has_comments(&self, node: &T, source: &str) -> bool where T: Ranged, { let start = if has_leading_content(node.start(), source) { node.start() } else { source.line_start(node.start()) }; let end = if has_trailing_content(node.end(), source) { node.end() } else { source.line_end(node.end()) }; self.intersects(TextRange::new(start, end)) } /// Given a [`CommentRanges`], determine which comments are grouped together /// in "comment blocks". A "comment block" is a sequence of consecutive /// own-line comments in which the comment hash (`#`) appears in the same /// column in each line, and at least one comment is non-empty. /// /// Returns a sorted vector containing the offset of the leading hash (`#`) /// for each comment in any block comment. /// /// ## Examples /// ```python /// # This is a block comment /// # because it spans multiple lines /// /// # This is also a block comment /// # even though it is indented /// /// # this is not a block comment /// /// x = 1 # this is not a block comment because /// y = 2 # the lines do not *only* contain comments /// /// # This is not a block comment because /// # not all consecutive lines have the /// # first `#` character in the same column /// /// """ /// # This is not a block comment because it is /// # contained within a multi-line string/comment /// """ /// ``` pub fn block_comments(&self, source: &str) -> Vec { let mut block_comments: Vec = Vec::new(); let mut current_block: Vec = Vec::new(); let mut current_block_column: Option = None; let mut current_block_non_empty = false; let mut prev_line_end = None; for comment_range in &self.raw { let offset = comment_range.start(); let line_start = source.line_start(offset); let line_end = source.full_line_end(offset); let column = offset - line_start; // If this is an end-of-line comment, reset the current block. if !Self::is_own_line(offset, source) { // Push the current block, and reset. if current_block.len() > 1 && current_block_non_empty { block_comments.extend(current_block); } current_block = vec![]; current_block_column = None; current_block_non_empty = false; prev_line_end = Some(line_end); continue; } // If there's a blank line between this comment and the previous // comment, reset the current block. if prev_line_end.is_some_and(|prev_line_end| { source.contains_line_break(TextRange::new(prev_line_end, line_start)) }) { // Push the current block. if current_block.len() > 1 && current_block_non_empty { block_comments.extend(current_block); } // Reset the block state. current_block = vec![offset]; current_block_column = Some(column); current_block_non_empty = !Self::is_empty(*comment_range, source); prev_line_end = Some(line_end); continue; } if let Some(current_column) = current_block_column { if column == current_column { // Add the comment to the current block. current_block.push(offset); current_block_non_empty |= !Self::is_empty(*comment_range, source); prev_line_end = Some(line_end); } else { // Push the current block. if current_block.len() > 1 && current_block_non_empty { block_comments.extend(current_block); } // Reset the block state. current_block = vec![offset]; current_block_column = Some(column); current_block_non_empty = !Self::is_empty(*comment_range, source); prev_line_end = Some(line_end); } } else { // Push the current block. if current_block.len() > 1 && current_block_non_empty { block_comments.extend(current_block); } // Reset the block state. current_block = vec![offset]; current_block_column = Some(column); current_block_non_empty = !Self::is_empty(*comment_range, source); prev_line_end = Some(line_end); } } // Push any lingering blocks. if current_block.len() > 1 && current_block_non_empty { block_comments.extend(current_block); } block_comments } /// Returns `true` if the given range is an empty comment. fn is_empty(range: TextRange, source: &str) -> bool { source[range].chars().skip(1).all(is_python_whitespace) } /// Returns `true` if a comment is an own-line comment (as opposed to an end-of-line comment). pub fn is_own_line(offset: TextSize, source: &str) -> bool { let range = TextRange::new(source.line_start(offset), offset); source[range].chars().all(is_python_whitespace) } } impl Deref for CommentRanges { type Target = [TextRange]; fn deref(&self) -> &Self::Target { self.raw.as_slice() } } impl Debug for CommentRanges { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_tuple("CommentRanges").field(&self.raw).finish() } } impl<'a> IntoIterator for &'a CommentRanges { type Item = TextRange; type IntoIter = std::iter::Copied>; fn into_iter(self) -> Self::IntoIter { self.raw.iter().copied() } } ast_serialize-0.13.1/crates/ruff_python_trivia/src/comments.rs000064400000000000000000000100561046102023000215320ustar00use ruff_text_size::TextRange; use crate::{PythonWhitespace, is_python_whitespace}; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub 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 { /// Attempts to identify the `kind` of a `comment`. /// The comment string should be the full line with the comment on it. pub fn from_comment(comment: &str) -> Option { // Match against `# fmt: on`, `# fmt: off`, `# yapf: disable`, and `# yapf: enable`, which // must be on their own lines. let trimmed = comment .strip_prefix('#') .unwrap_or(comment) .trim_whitespace(); if let Some(command) = trimmed.strip_prefix("fmt:") { match command.trim_whitespace_start() { "off" => return Some(Self::Off), "on" => return Some(Self::On), "skip" => return Some(Self::Skip), _ => {} } } else if let Some(command) = trimmed.strip_prefix("yapf:") { match command.trim_whitespace_start() { "disable" => return Some(Self::Off), "enable" => return Some(Self::On), _ => {} } } // Search for `# fmt: skip` comments, which can be interspersed with other comments (e.g., // `# fmt: skip # noqa: E501`). for segment in comment.split('#') { let trimmed = segment.trim_whitespace(); if let Some(command) = trimmed.strip_prefix("fmt:") { if command.trim_whitespace_start() == "skip" { return Some(SuppressionKind::Skip); } } } None } /// Returns true if this comment is a `fmt: off` or `yapf: disable` own line suppression comment. pub fn is_suppression_on(slice: &str, position: CommentLinePosition) -> bool { position.is_own_line() && matches!(Self::from_comment(slice), Some(Self::On)) } /// Returns true if this comment is a `fmt: on` or `yapf: enable` own line suppression comment. pub fn is_suppression_off(slice: &str, position: CommentLinePosition) -> bool { position.is_own_line() && matches!(Self::from_comment(slice), Some(Self::Off)) } } /// The position of a comment in the source text. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum CommentLinePosition { /// A comment that is on the same line as the preceding token and is separated by at least one line break from the following token. /// /// # Examples /// /// ## End of line /// /// ```python /// a; # comment /// b; /// ``` /// /// `# comment` is an end of line comments because it is separated by at least one line break from the following token `b`. /// Comments that not only end, but also start on a new line are [`OwnLine`](CommentLinePosition::OwnLine) comments. EndOfLine, /// A Comment that is separated by at least one line break from the preceding token. /// /// # Examples /// /// ```python /// a; /// # comment /// b; /// ``` /// /// `# comment` line comments because they are separated by one line break from the preceding token `a`. OwnLine, } impl CommentLinePosition { pub const fn is_own_line(self) -> bool { matches!(self, Self::OwnLine) } pub const fn is_end_of_line(self) -> bool { matches!(self, Self::EndOfLine) } /// Finds the line position of a comment given a range over a valid /// comment. pub fn for_range(comment_range: TextRange, source_code: &str) -> Self { let before = &source_code[TextRange::up_to(comment_range.start())]; for c in before.chars().rev() { match c { '\n' | '\r' => { break; } c if is_python_whitespace(c) => continue, _ => return Self::EndOfLine, } } Self::OwnLine } } ast_serialize-0.13.1/crates/ruff_python_trivia/src/cursor.rs000064400000000000000000000124231046102023000212220ustar00use std::str::Chars; use ruff_text_size::{TextLen, TextSize}; pub const EOF_CHAR: char = '\0'; /// A [`Cursor`] over a string. /// /// Based on [`rustc`'s `Cursor`](https://github.com/rust-lang/rust/blob/d1b7355d3d7b4ead564dbecb1d240fcc74fff21b/compiler/rustc_lexer/src/cursor.rs) #[derive(Debug, Clone)] pub struct Cursor<'a> { chars: Chars<'a>, source_length: TextSize, } impl<'a> Cursor<'a> { pub fn new(source: &'a str) -> Self { Self { source_length: source.text_len(), chars: source.chars(), } } /// Retrieves the current offset of the cursor within the source code. pub fn offset(&self) -> TextSize { self.source_length - self.text_len() } /// Return the remaining input as a string slice. pub fn chars(&self) -> Chars<'a> { self.chars.clone() } /// Returns the remaining input as byte slice. pub fn as_bytes(&self) -> &'a [u8] { self.as_str().as_bytes() } /// Returns the remaining input as string slice. pub fn as_str(&self) -> &'a str { self.chars.as_str() } /// 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 first(&self) -> char { 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. fn last(&self) -> char { self.chars.clone().next_back().unwrap_or(EOF_CHAR) } pub fn text_len(&self) -> TextSize { self.chars.as_str().text_len() } pub fn token_len(&self) -> TextSize { self.source_length - self.text_len() } pub fn start_token(&mut self) { self.source_length = self.text_len(); } /// Returns `true` if the file is at the end of the file. pub fn is_eof(&self) -> bool { self.chars.as_str().is_empty() } /// Consumes the next character pub fn bump(&mut self) -> Option { self.chars.next() } /// Consumes the next character from the back pub(crate) fn bump_back(&mut self) -> Option { self.chars.next_back() } pub fn eat_char(&mut self, c: char) -> bool { if self.first() == c { self.bump(); true } else { false } } /// Eats the next two characters if they are `c1` and `c2`. Does not /// consume any input otherwise, even if the first character matches. pub fn eat_char2(&mut self, c1: char, c2: char) -> bool { let mut chars = self.chars.clone(); if chars.next() == Some(c1) && chars.next() == Some(c2) { self.bump(); self.bump(); true } else { false } } /// Eats the next three characters if they are `c1`, `c2` and `c3` /// Does not consume any input otherwise, even if the first character matches. pub fn eat_char3(&mut self, c1: char, c2: char, c3: char) -> bool { let mut chars = self.chars.clone(); if chars.next() == Some(c1) && chars.next() == Some(c2) && chars.next() == Some(c3) { self.bump(); self.bump(); self.bump(); true } else { false } } pub(crate) fn eat_char_back(&mut self, c: char) -> bool { if self.last() == c { self.bump_back(); true } else { false } } /// Eats the next character if `predicate` returns `true`. pub fn eat_if(&mut self, mut predicate: impl FnMut(char) -> bool) -> bool { if predicate(self.first()) && !self.is_eof() { self.bump(); true } else { false } } /// Eats symbols while predicate returns true or until the end of file is reached. pub fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { // It was tried making optimized version of this for eg. line comments, but // LLVM can inline all of this and compile it down to fast iteration over bytes. while predicate(self.first()) && !self.is_eof() { self.bump(); } } /// Eats symbols from the back while predicate returns true or until the beginning of file is reached. pub(crate) fn eat_back_while(&mut self, mut predicate: impl FnMut(char) -> bool) { // It was tried making optimized version of this for eg. line comments, but // LLVM can inline all of this and compile it down to fast iteration over bytes. while predicate(self.last()) && !self.is_eof() { self.bump_back(); } } /// Skips the next `count` bytes. /// /// ## Panics /// - If `count` is larger than the remaining bytes in the input stream. /// - If `count` indexes into a multi-byte character. pub fn skip_bytes(&mut self, count: usize) { self.chars = self.chars.as_str()[count..].chars(); } } ast_serialize-0.13.1/crates/ruff_python_trivia/src/lib.rs000064400000000000000000000004471046102023000204560ustar00mod comment_ranges; mod comments; mod cursor; mod pragmas; pub mod textwrap; mod tokenizer; mod whitespace; pub use comment_ranges::{CommentRanges, ParenthesizedExpressions, TriviaRanges}; pub use comments::*; pub use cursor::*; pub use pragmas::*; pub use tokenizer::*; pub use whitespace::*; ast_serialize-0.13.1/crates/ruff_python_trivia/src/pragmas.rs000064400000000000000000000052311046102023000213360ustar00/// Returns `true` if a comment appears to be a pragma comment. /// /// ``` /// assert!(ruff_python_trivia::is_pragma_comment("# type: ignore")); /// assert!(ruff_python_trivia::is_pragma_comment("# noqa: F401")); /// assert!(ruff_python_trivia::is_pragma_comment("# noqa")); /// assert!(ruff_python_trivia::is_pragma_comment("# NoQA")); /// assert!(ruff_python_trivia::is_pragma_comment("# nosec")); /// assert!(ruff_python_trivia::is_pragma_comment("# nosec B602, B607")); /// assert!(ruff_python_trivia::is_pragma_comment("# isort: off")); /// assert!(ruff_python_trivia::is_pragma_comment("# isort: skip")); /// assert!(ruff_python_trivia::is_pragma_comment("# pyrefly: ignore[missing-attribute]")); /// ``` pub fn is_pragma_comment(comment: &str) -> bool { let Some(content) = comment.strip_prefix('#') else { return false; }; let trimmed = content.trim_start(); // Case-insensitive match against `noqa` (which doesn't require a trailing colon). if matches!( trimmed.as_bytes(), [b'n' | b'N', b'o' | b'O', b'q' | b'Q', b'a' | b'A', ..] ) { return true; } // Case-insensitive match against pragmas that don't require a trailing colon. if trimmed.starts_with("nosec") { return true; } // Case-sensitive match against a variety of pragmas that _do_ require a trailing colon. trimmed.split_once(':').is_some_and(|(maybe_pragma, _)| { matches!( maybe_pragma, "isort" | "type" | "pyright" | "pyrefly" | "pylint" | "flake8" | "ruff" | "ty" ) }) } /// Returns the byte offset within `comment` where a trailing pragma comment starts, /// or `None` if no pragma is found. /// /// For a plain pragma like `# noqa: F401`, returns `Some(0)`. /// For a nested pragma like `# some text # noqa: F401`, returns the offset of the /// trailing `#` that begins the pragma (i.e., the start of `# noqa: F401`). /// /// ``` /// assert_eq!(ruff_python_trivia::find_trailing_pragma_offset("# noqa: F401"), Some(0)); /// assert_eq!(ruff_python_trivia::find_trailing_pragma_offset("# type: ignore"), Some(0)); /// assert_eq!(ruff_python_trivia::find_trailing_pragma_offset("# some comment # noqa: F401"), Some(15)); /// assert_eq!(ruff_python_trivia::find_trailing_pragma_offset("## noqa: F401"), Some(1)); /// assert_eq!(ruff_python_trivia::find_trailing_pragma_offset("# just a comment"), None); /// ``` pub fn find_trailing_pragma_offset(comment: &str) -> Option { comment.match_indices('#').find_map(|(offset, _)| { let sub_comment = &comment[offset..]; if is_pragma_comment(sub_comment) { Some(offset) } else { None } }) } ast_serialize-0.13.1/crates/ruff_python_trivia/src/textwrap.rs000064400000000000000000000463411046102023000215710ustar00//! Functions related to adding and removing indentation from lines of //! text. use std::borrow::Cow; use std::cmp; use ruff_source_file::UniversalNewlines; use crate::PythonWhitespace; /// Indent each line by the given prefix. /// /// # Examples /// /// ``` /// # use ruff_python_trivia::textwrap::indent; /// /// assert_eq!(indent("First line.\nSecond line.\n", " "), /// " First line.\n Second line.\n"); /// ``` /// /// When indenting, trailing whitespace is stripped from the prefix. /// This means that empty lines remain empty afterwards: /// /// ``` /// # use ruff_python_trivia::textwrap::indent; /// /// assert_eq!(indent("First line.\n\n\nSecond line.\n", " "), /// " First line.\n\n\n Second line.\n"); /// ``` /// /// Notice how `"\n\n\n"` remained as `"\n\n\n"`. /// /// This feature is useful when you want to indent text and have a /// space between your prefix and the text. In this case, you _don't_ /// want a trailing space on empty lines: /// /// ``` /// # use ruff_python_trivia::textwrap::indent; /// /// assert_eq!(indent("foo = 123\n\nprint(foo)\n", "# "), /// "# foo = 123\n#\n# print(foo)\n"); /// ``` /// /// Notice how `"\n\n"` became `"\n#\n"` instead of `"\n# \n"` which /// would have trailing whitespace. /// /// Leading and trailing whitespace coming from the text itself is /// kept unchanged: /// /// ``` /// # use ruff_python_trivia::textwrap::indent; /// /// assert_eq!(indent(" \t Foo ", "->"), "-> \t Foo "); /// ``` pub fn indent<'a>(text: &'a str, prefix: &str) -> Cow<'a, str> { if prefix.is_empty() { return Cow::Borrowed(text); } let mut result = String::with_capacity(text.len() + prefix.len()); let trimmed_prefix = prefix.trim_whitespace_end(); for line in text.universal_newlines() { if line.trim_whitespace().is_empty() { result.push_str(trimmed_prefix); } else { result.push_str(prefix); } result.push_str(line.as_full_str()); } Cow::Owned(result) } /// Indent only the first line by the given prefix. /// /// This function is useful when you want to indent the first line of a multi-line /// expression while preserving the relative indentation of subsequent lines. /// /// # Examples /// /// ``` /// # use ruff_python_trivia::textwrap::indent_first_line; /// /// assert_eq!(indent_first_line("First line.\nSecond line.\n", " "), /// " First line.\nSecond line.\n"); /// ``` /// /// When indenting, trailing whitespace is stripped from the prefix. /// This means that empty lines remain empty afterwards: /// /// ``` /// # use ruff_python_trivia::textwrap::indent_first_line; /// /// assert_eq!(indent_first_line("\n\n\nSecond line.\n", " "), /// "\n\n\nSecond line.\n"); /// ``` /// /// Leading and trailing whitespace coming from the text itself is /// kept unchanged: /// /// ``` /// # use ruff_python_trivia::textwrap::indent_first_line; /// /// assert_eq!(indent_first_line(" \t Foo ", "->"), "-> \t Foo "); /// ``` pub fn indent_first_line<'a>(text: &'a str, prefix: &str) -> Cow<'a, str> { if prefix.is_empty() { return Cow::Borrowed(text); } let mut lines = text.universal_newlines(); let Some(first_line) = lines.next() else { return Cow::Borrowed(text); }; let mut result = String::with_capacity(text.len() + prefix.len()); // Indent only the first line if first_line.trim_whitespace().is_empty() { result.push_str(prefix.trim_whitespace_end()); } else { result.push_str(prefix); } result.push_str(first_line.as_full_str()); // Add remaining lines without indentation for line in lines { result.push_str(line.as_full_str()); } Cow::Owned(result) } /// Removes common leading whitespace from each line. /// /// This function will look at each non-empty line and determine the /// maximum amount of whitespace that can be removed from all lines. /// /// Lines that consist solely of whitespace are trimmed to a blank line. /// /// ``` /// # use ruff_python_trivia::textwrap::dedent; /// /// assert_eq!(dedent(" /// 1st line /// 2nd line /// 3rd line /// "), " /// 1st line /// 2nd line /// 3rd line /// "); /// ``` pub fn dedent(text: &str) -> Cow<'_, str> { // Find the minimum amount of leading whitespace on each line. let prefix_len = text .universal_newlines() .fold(usize::MAX, |prefix_len, line| { let leading_whitespace_len = line.len() - line.trim_whitespace_start().len(); if leading_whitespace_len == line.len() { // Skip empty lines. prefix_len } else { cmp::min(prefix_len, leading_whitespace_len) } }); // If there is no common prefix, no need to dedent. if prefix_len == usize::MAX { return Cow::Borrowed(text); } // Remove the common prefix from each line. let mut result = String::with_capacity(text.len()); for line in text.universal_newlines() { if line.trim_whitespace().is_empty() { if let Some(line_ending) = line.line_ending() { result.push_str(&line_ending); } } else { result.push_str(&line.as_full_str()[prefix_len..]); } } Cow::Owned(result) } /// Reduce a block's indentation to match the provided indentation. /// /// This function looks at the first line in the block to determine the /// current indentation, then removes whitespace from each line to /// match the provided indentation. /// /// Leading comments are ignored unless the block is only composed of comments. /// /// Lines that are indented by _less_ than the indent of the first line /// are left unchanged. /// /// Lines that consist solely of whitespace are trimmed to a blank line. /// /// Lines that start with formfeeds have the indentation after the formfeeds /// removed and the formfeeds reinstated /// /// # Panics /// If the first line is indented by less than the provided indent. pub fn dedent_to(text: &str, indent: &str) -> Option { // The caller may provide an `indent` from source code by taking // a range of text beginning with the start of a line. In Python, // while a line may begin with form feeds, these do not contribute // to the indentation. So we strip those here. let indent = indent.trim_start_matches('\x0C'); // Look at the indentation of the first non-empty line, to determine the "baseline" indentation. let mut first_comment_indent = None; let existing_indent_len = text .universal_newlines() .find_map(|line| { // Following Python's lexer, treat form feed character's at the start of a line // the same as a line break (reset the indentation) let trimmed_start_of_line_formfeed = line.trim_start_matches('\x0C'); let trimmed = trimmed_start_of_line_formfeed.trim_whitespace_start(); // A whitespace only line if trimmed.is_empty() { return None; } let indent_len = trimmed_start_of_line_formfeed.len() - trimmed.len(); if trimmed.starts_with('#') && first_comment_indent.is_none() { first_comment_indent = Some(indent_len); None } else { Some(indent_len) } }) .unwrap_or(first_comment_indent.unwrap_or_default()); if existing_indent_len < indent.len() { return None; } // Determine the amount of indentation to remove. let dedent_len = existing_indent_len - indent.len(); let mut result = String::with_capacity(text.len() + indent.len()); for line in text.universal_newlines() { let line_content = line.trim_start_matches('\x0C'); let formfeed_count = line.len() - line_content.len(); let line_ending = if let Some(line_ending) = line.line_ending() { line_ending.as_str() } else { "" }; let line_without_indent = line.trim_whitespace_start(); if line_without_indent.is_empty() { result.push_str(line_ending); continue; } // Determine the current indentation level. let current_indent_len = line_content.len() - line_without_indent.len(); if current_indent_len < existing_indent_len { // If the current indentation level is less than the baseline, keep it as is. result.push_str(line.as_full_str()); continue; } let dedented_content = &line_content[dedent_len..]; let formfeeds = &line[..formfeed_count]; result.push_str(formfeeds); result.push_str(dedented_content); result.push_str(line_ending); } Some(result) } #[cfg(test)] mod tests { use super::*; #[test] fn indent_empty() { assert_eq!(indent("\n", " "), "\n"); } #[test] #[rustfmt::skip] fn indent_nonempty() { let text = [ " foo\n", "bar\n", " baz\n", ].join(""); let expected = [ "// foo\n", "// bar\n", "// baz\n", ].join(""); assert_eq!(indent(&text, "// "), expected); } #[test] #[rustfmt::skip] fn indent_empty_line() { let text = [ " foo", "bar", "", " baz", ].join("\n"); let expected = [ "// foo", "// bar", "//", "// baz", ].join("\n"); assert_eq!(indent(&text, "// "), expected); } #[test] #[rustfmt::skip] fn indent_mixed_newlines() { let text = [ " foo\r\n", "bar\n", " baz\r", ].join(""); let expected = [ "// foo\r\n", "// bar\n", "// baz\r", ].join(""); assert_eq!(indent(&text, "// "), expected); } #[test] fn dedent_empty() { assert_eq!(dedent(""), ""); } #[test] #[rustfmt::skip] fn dedent_multi_line() { let x = [ " foo", " bar", " baz", ].join("\n"); let y = [ " foo", "bar", " baz" ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_empty_line() { let x = [ " foo", " bar", " ", " baz" ].join("\n"); let y = [ " foo", "bar", "", " baz" ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_blank_line() { let x = [ " foo", "", " bar", " foo", " bar", " baz", ].join("\n"); let y = [ "foo", "", " bar", " foo", " bar", " baz", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_whitespace_line() { let x = [ " foo", " ", " bar", " foo", " bar", " baz", ].join("\n"); let y = [ "foo", "", " bar", " foo", " bar", " baz", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_mixed_whitespace() { let x = [ "\tfoo", " bar", ].join("\n"); let y = [ "foo", " bar", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_tabbed_whitespace() { let x = [ "\t\tfoo", "\t\t\tbar", ].join("\n"); let y = [ "foo", "\tbar", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_mixed_tabbed_whitespace() { let x = [ "\t \tfoo", "\t \t\tbar", ].join("\n"); let y = [ "foo", "\tbar", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_preserve_no_terminating_newline() { let x = [ " foo", " bar", ].join("\n"); let y = [ "foo", " bar", ].join("\n"); assert_eq!(dedent(&x), y); } #[test] #[rustfmt::skip] fn dedent_mixed_newlines() { let x = [ " foo\r\n", " bar\n", " baz\r", ].join(""); let y = [ " foo\r\n", "bar\n", " baz\r" ].join(""); assert_eq!(dedent(&x), y); } #[test] fn dedent_non_python_whitespace() { let text = r"        C = int(f.rea1,0],[-1,0,1]], [[-1,-1,1],[1,1,-1],[0,-1,0]], [[-1,-1,-1],[1,1,0],[1,0,1]] ]"; assert_eq!(dedent(text), text); } #[test] fn indent_first_line_empty() { assert_eq!(indent_first_line("\n", " "), "\n"); } #[test] #[rustfmt::skip] fn indent_first_line_nonempty() { let text = [ " foo\n", "bar\n", " baz\n", ].join(""); let expected = [ "// foo\n", "bar\n", " baz\n", ].join(""); assert_eq!(indent_first_line(&text, "// "), expected); } #[test] #[rustfmt::skip] fn indent_first_line_empty_line() { let text = [ " foo", "bar", "", " baz", ].join("\n"); let expected = [ "// foo", "bar", "", " baz", ].join("\n"); assert_eq!(indent_first_line(&text, "// "), expected); } #[test] #[rustfmt::skip] fn indent_first_line_mixed_newlines() { let text = [ " foo\r\n", "bar\n", " baz\r", ].join(""); let expected = [ "// foo\r\n", "bar\n", " baz\r", ].join(""); assert_eq!(indent_first_line(&text, "// "), expected); } #[test] #[rustfmt::skip] fn adjust_indent() { let x = [ " foo", " bar", " ", " baz" ].join("\n"); let y = [ " foo", " bar", "", " baz" ].join("\n"); assert_eq!(dedent_to(&x, " "), Some(y)); let x = [ " foo", " bar", " baz", ].join("\n"); let y = [ "foo", " bar", "baz" ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); let x = [ " # foo", " # bar", "# baz" ].join("\n"); let y = [ " # foo", " # bar", "# baz" ].join("\n"); assert_eq!(dedent_to(&x, " "), Some(y)); let x = [ " # foo", " bar", " baz" ].join("\n"); let y = [ " # foo", " bar", " baz" ].join("\n"); assert_eq!(dedent_to(&x, " "), Some(y)); let x = [ "\x0C 1", " 2" ].join("\n"); let y = [ "\x0C1", "2" ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_returns_none_if_indent_too_large() { let x = [ " foo", " bar" ].join("\n"); assert_eq!(dedent_to(&x, " "), None); } #[test] #[rustfmt::skip] fn dedent_to_only_whitespace_lines() { let x = [ " ", "\t", " " ].join("\n"); let y = "\n\n".to_string(); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_preserves_crlf_for_lines_starting_with_form_feed() { let x = [ "\x0C 1\r\n", " 2\r\n", ].join(""); let y = [ "\x0C1\r\n", "2\r\n", ].join(""); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_preserves_multiple_leading_form_feeds_on_first_line() { let x = [ "\x0C\x0C 1", " 2", ].join("\n"); let y = [ "\x0C\x0C1", "2", ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_preserves_multiple_leading_form_feeds_on_second_line() { let x = [ " 1", "\x0C\x0C 2", ].join("\n"); let y = [ "1", "\x0C\x0C2", ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_handles_when_multiple_leading_form_feeds_greater_than_dedent_len() { let x = [ "\x0C\x0C\x0C\x0C 1", " 2", ].join("\n"); let y = [ "\x0C\x0C\x0C\x0C1", "2", ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_ignores_leading_form_feeds_when_checking_indentation() { let x = [ " 1", "\x0C\x0C 2", ].join("\n"); let y = [ "1", "\x0C\x0C 2", ].join("\n"); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_is_idempotent() { let x = [ " foo", " bar", " ", " baz" ].join("\n"); let y = [ " foo", " bar", "", " baz" ].join("\n"); let first_result = dedent_to(&x, " ").unwrap(); assert_eq!(dedent_to(&first_result, " "), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_preserves_less_indented_later_line() { let x = [ " foo\n", " bar\n", ].join(""); let y = [ "foo\n", " bar\n", ].join(""); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_preserves_less_indented_later_line_with_crlf() { let x = [ " foo\r\n", " bar\r\n", ].join(""); let y = [ "foo\r\n", " bar\r\n", ].join(""); assert_eq!(dedent_to(&x, ""), Some(y)); } #[test] #[rustfmt::skip] fn dedent_to_ignores_leading_form_feeds_in_provided_indentation() { let x = [ " 1", " 2", ].join("\n"); let y = [ "1", "2", ].join("\n"); assert_eq!(dedent_to(&x, "\x0C\x0C"), Some(y)); } } ast_serialize-0.13.1/crates/ruff_python_trivia/src/tokenizer.rs000064400000000000000000000714541046102023000217300ustar00use unicode_ident::{is_xid_continue, is_xid_start}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use crate::{Cursor, is_python_whitespace}; /// Searches for the first non-trivia character after `offset`. /// /// The search skips over any whitespace and comments. /// /// Returns `Some` if the source code after `offset` contains any non-trivia character./// /// Returns `None` if the text after `offset` is empty or only contains trivia (whitespace or comments). pub fn first_non_trivia_token(offset: TextSize, code: &str) -> Option { SimpleTokenizer::starts_at(offset, code) .skip_trivia() .next() } /// Returns the only non-trivia, non-closing parenthesis token in `range`. /// /// Includes debug assertions that the range only contains that single token. pub fn find_only_token_in_range( range: TextRange, token_kind: SimpleTokenKind, code: &str, ) -> 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); #[expect(clippy::debug_assert_with_mut_call)] { 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)]); let mut newlines = 0u32; while let Some(c) = cursor.bump_back() { match c { '\n' => { cursor.eat_char_back('\r'); newlines += 1; } '\r' => { newlines += 1; } c if is_python_whitespace(c) => { continue; } _ => { break; } } } newlines } /// Counts the empty lines between `offset` and the first non-whitespace character. pub fn lines_after(offset: TextSize, code: &str) -> u32 { let mut cursor = Cursor::new(&code[offset.to_usize()..]); let mut newlines = 0u32; while let Some(c) = cursor.bump() { match c { '\n' => { newlines += 1; } '\r' => { cursor.eat_char('\n'); newlines += 1; } c if is_python_whitespace(c) => { continue; } _ => { break; } } } newlines } /// Counts the empty lines after `offset`, ignoring any trailing trivia: end-of-line comments, /// own-line comments, and any intermediary newlines. pub fn lines_after_ignoring_trivia(offset: TextSize, code: &str) -> u32 { let mut newlines = 0u32; for token in SimpleTokenizer::starts_at(offset, code) { match token.kind() { SimpleTokenKind::Newline => { newlines += 1; } SimpleTokenKind::Whitespace => {} // If we see a comment, reset the newlines counter. SimpleTokenKind::Comment => { newlines = 0; } // As soon as we see a non-trivia token, we're done. _ => { break; } } } newlines } /// Counts the empty lines after `offset`, ignoring any trailing trivia on the same line as /// `offset`. #[expect(clippy::cast_possible_truncation)] pub fn lines_after_ignoring_end_of_line_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 { 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 // in https://docs.python.org/3/reference/lexical_analysis.html#identifiers fn is_identifier_continuation(c: char) -> bool { // Arrange things such that ASCII codepoints never // result in the slower `is_xid_continue` getting called. if c.is_ascii() { matches!(c, 'a'..='z' | 'A'..='Z' | '_' | '0'..='9') } else { is_xid_continue(c) } } fn to_keyword_or_other(source: &str) -> SimpleTokenKind { match source { "and" => SimpleTokenKind::And, "as" => SimpleTokenKind::As, "assert" => SimpleTokenKind::Assert, "async" => SimpleTokenKind::Async, "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, "lazy" => SimpleTokenKind::Lazy, // Lazy 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. "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::Name, // Potentially an identifier, but only if it isn't a string prefix. The caller (SimpleTokenizer) is responsible for enforcing that constraint. } } #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct SimpleToken { pub kind: SimpleTokenKind, pub range: TextRange, } impl SimpleToken { pub const fn kind(&self) -> SimpleTokenKind { self.kind } } impl Ranged for SimpleToken { fn range(&self) -> TextRange { self.range } } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum SimpleTokenKind { /// A comment, not including the trailing new line. Comment, /// Sequence of ' ' or '\t' Whitespace, /// Start or end of the file EndOfFile, /// `\\` Continuation, /// `\n` or `\r` or `\r\n` Newline, /// `(` LParen, /// `)` RParen, /// `{` LBrace, /// `}` RBrace, /// `[` LBracket, /// `]` RBracket, /// `,` Comma, /// `:` Colon, /// `;` Semi, /// `/` Slash, /// `*` Star, /// `.` 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, /// `import` Import, /// `in` In, /// `is` Is, /// `lambda` Lambda, /// `nonlocal` Nonlocal, /// `not` Not, /// `or` Or, /// `pass` Pass, /// `raise` Raise, /// `return` Return, /// `try` Try, /// `while` While, /// `lazy` Lazy, /// `match` Match, /// `type` Type, /// `case` Case, /// `with` With, /// `yield` Yield, /// An identifier or keyword. Name, /// Any other non trivia token. Other, /// Returned for each character after [`SimpleTokenKind::Other`] has been returned once. Bogus, } impl SimpleTokenKind { pub const fn is_trivia(self) -> bool { matches!( self, SimpleTokenKind::Whitespace | SimpleTokenKind::Newline | SimpleTokenKind::Comment | SimpleTokenKind::Continuation ) } pub const fn is_comment(self) -> bool { matches!(self, SimpleTokenKind::Comment) } } /// Simple zero allocation tokenizer handling most tokens. /// /// The tokenizer must start at an offset that is trivia (e.g. not inside of a multiline string). /// /// In case it finds something it can't parse, the tokenizer will return a /// [`SimpleTokenKind::Other`] and then only a final [`SimpleTokenKind::Bogus`] afterwards. pub struct SimpleTokenizer<'a> { offset: TextSize, /// `true` when it is known that the current `back` line has no comment for sure. bogus: bool, source: &'a str, cursor: Cursor<'a>, } impl<'a> SimpleTokenizer<'a> { pub fn new(source: &'a str, range: TextRange) -> Self { Self { offset: range.start(), bogus: false, source, cursor: Cursor::new(&source[range]), } } pub fn starts_at(offset: TextSize, source: &'a str) -> Self { let range = TextRange::new(offset, source.text_len()); Self::new(source, range) } fn next_token(&mut self) -> SimpleToken { self.cursor.start_token(); let Some(first) = self.cursor.bump() else { return SimpleToken { kind: SimpleTokenKind::EndOfFile, range: TextRange::empty(self.offset), }; }; if self.bogus { // Emit a single final bogus token let token = SimpleToken { kind: SimpleTokenKind::Bogus, range: TextRange::new(self.offset, self.source.text_len()), }; // Set the cursor to EOF self.cursor = Cursor::new(""); self.offset = self.source.text_len(); return token; } let kind = self.next_token_inner(first); let token_len = self.cursor.token_len(); let token = SimpleToken { kind, range: TextRange::at(self.offset, token_len), }; self.offset += token_len; token } fn next_token_inner(&mut self, first: char) -> SimpleTokenKind { 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 = to_keyword_or_other(&self.source[range]); // If the next character is a quote, we may be in a string prefix. For example: // `f"foo`. if kind == SimpleTokenKind::Name && matches!(self.cursor.first(), '"' | '\'') && matches!( &self.source[range], "B" | "BR" | "Br" | "F" | "FR" | "Fr" | "R" | "RB" | "RF" | "Rb" | "Rf" | "U" | "b" | "bR" | "br" | "f" | "fR" | "fr" | "r" | "rB" | "rF" | "rb" | "rf" | "u" | "T" | "TR" | "Tr" | "RT" | "Rt" | "t" | "tR" | "tr" | "rT" | "rt" ) { self.bogus = true; SimpleTokenKind::Other } else { kind } } // Space, tab, or form feed. We ignore the true semantics of form feed, and treat it as // whitespace. ' ' | '\t' | '\x0C' => { self.cursor.eat_while(|c| matches!(c, ' ' | '\t' | '\x0C')); SimpleTokenKind::Whitespace } '\n' => SimpleTokenKind::Newline, '\r' => { self.cursor.eat_char('\n'); SimpleTokenKind::Newline } '#' => { self.cursor.eat_while(|c| !matches!(c, '\n' | '\r')); SimpleTokenKind::Comment } '\\' => SimpleTokenKind::Continuation, // 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, '~' => 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 } } } pub fn skip_trivia(self) -> impl Iterator + 'a { self.filter(|t| !t.kind().is_trivia()) } } impl Iterator for SimpleTokenizer<'_> { type Item = SimpleToken; fn next(&mut self) -> Option { let token = self.next_token(); if token.kind == SimpleTokenKind::EndOfFile { None } else { Some(token) } } } /// Simple zero allocation backwards tokenizer for finding preceding tokens. /// /// The tokenizer must start at an offset that is trivia (e.g. not inside of a multiline string). /// It will fail when reaching a string. /// /// In case it finds something it can't parse, the tokenizer will return a /// [`SimpleTokenKind::Other`] and then only a final [`SimpleTokenKind::Bogus`] afterwards. pub struct BackwardsTokenizer<'a> { offset: TextSize, back_offset: TextSize, /// Not `&CommentRanges` to avoid a circular dependency. comment_ranges: &'a [TextRange], bogus: bool, source: &'a str, cursor: Cursor<'a>, } impl<'a> BackwardsTokenizer<'a> { pub fn new(source: &'a str, range: TextRange, comment_range: &'a [TextRange]) -> Self { Self { offset: range.start(), back_offset: range.end(), // Throw out any comments that follow the range. comment_ranges: &comment_range [..comment_range.partition_point(|comment| comment.start() <= range.end())], bogus: false, source, cursor: Cursor::new(&source[range]), } } pub fn up_to(offset: TextSize, source: &'a str, comment_range: &'a [TextRange]) -> Self { Self::new(source, TextRange::up_to(offset), comment_range) } pub fn skip_trivia(self) -> impl Iterator + 'a { self.filter(|t| !t.kind().is_trivia()) } fn next_token(&mut self) -> SimpleToken { self.cursor.start_token(); self.back_offset = self.cursor.text_len() + self.offset; let Some(last) = self.cursor.bump_back() else { return SimpleToken { kind: SimpleTokenKind::EndOfFile, range: TextRange::empty(self.back_offset), }; }; if self.bogus { let token = SimpleToken { kind: SimpleTokenKind::Bogus, range: TextRange::up_to(self.back_offset), }; // Set the cursor to EOF self.cursor = Cursor::new(""); self.back_offset = TextSize::new(0); return token; } if let Some(comment) = self .comment_ranges .last() .filter(|comment| comment.contains_inclusive(self.back_offset)) { self.comment_ranges = &self.comment_ranges[..self.comment_ranges.len() - 1]; // Skip the comment without iterating over the chars manually. self.cursor = Cursor::new(&self.source[TextRange::new(self.offset, comment.start())]); debug_assert_eq!(self.cursor.text_len() + self.offset, comment.start()); return SimpleToken { kind: SimpleTokenKind::Comment, range: comment.range(), }; } let kind = match last { // Space, tab, or form feed. We ignore the true semantics of form feed, and treat it as // whitespace. Note that this will lex-out trailing whitespace from a comment as // whitespace rather than as part of the comment token, but this shouldn't matter for // our use case. ' ' | '\t' | '\x0C' => { self.cursor .eat_back_while(|c| matches!(c, ' ' | '\t' | '\x0C')); SimpleTokenKind::Whitespace } '\r' => SimpleTokenKind::Newline, '\n' => { self.cursor.eat_char_back('\r'); SimpleTokenKind::Newline } _ => self.next_token_inner(last), }; let token_len = self.cursor.token_len(); let start = self.back_offset - token_len; SimpleToken { kind, range: TextRange::at(start, token_len), } } /// Helper to parser the previous token once we skipped all whitespace fn next_token_inner(&mut self, last: char) -> SimpleTokenKind { match last { // 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) { to_keyword_or_other(&self.source[range]) } else { self.cursor = savepoint; self.bogus = true; SimpleTokenKind::Other } } // 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 = SimpleTokenizer::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`.y for _ in self.source[token.range].chars().rev().skip(1) { self.cursor.bump_back().unwrap(); } token.kind() } else { self.bogus = true; SimpleTokenKind::Other } } _ => { self.bogus = true; SimpleTokenKind::Other } } } } impl Iterator for BackwardsTokenizer<'_> { type Item = SimpleToken; fn next(&mut self) -> Option { let token = self.next_token(); if token.kind == SimpleTokenKind::EndOfFile { None } else { Some(token) } } } ast_serialize-0.13.1/crates/ruff_python_trivia/src/whitespace.rs000064400000000000000000000114611046102023000220420ustar00use std::borrow::Cow; use ruff_source_file::LineRanges; use ruff_text_size::{TextRange, TextSize}; /// Expands tabs to the next eight-column tab stop, matching Python's `str.expandtabs`. pub fn expand_tabs(source: &str) -> Cow<'_, str> { const TAB_SIZE: usize = 8; if !source.contains('\t') { return Cow::Borrowed(source); } let mut expanded = String::with_capacity(source.len()); let mut column = 0; for character in source.chars() { match character { '\t' => { let spaces = tab_offset(column, TAB_SIZE); expanded.extend(std::iter::repeat_n(' ', spaces)); column += spaces; } '\r' | '\n' => { expanded.push(character); column = 0; } _ => { expanded.push(character); column += 1; } } } Cow::Owned(expanded) } /// Returns the number of columns from `column` to the next tab stop. pub const fn tab_offset(column: usize, tab_size: usize) -> usize { tab_size - column % tab_size } /// Returns the number of columns from `column` to the next tab stop using `u32` values. pub const fn tab_offset_u32(column: u32, tab_size: u32) -> u32 { tab_size - column % tab_size } /// Extract the leading indentation from a line. pub fn indentation_at_offset(offset: TextSize, source: &str) -> Option<&str> { let line_start = source.line_start(offset); let indentation = &source[TextRange::new(line_start, offset)]; indentation .chars() .all(is_python_whitespace) .then_some(indentation) } /// Return `true` if the node starting the given [`TextSize`] has leading content. pub fn has_leading_content(offset: TextSize, source: &str) -> bool { let line_start = source.line_start(offset); let leading = &source[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, source: &str) -> bool { let line_end = source.line_end(offset); let trailing = &source[TextRange::new(offset, line_end)]; for char in trailing.chars() { if char == '#' { return false; } if !is_python_whitespace(char) { return true; } } false } /// Returns `true` for [whitespace](https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens) /// characters. pub const fn is_python_whitespace(c: char) -> bool { matches!( c, // Space, tab, or form-feed ' ' | '\t' | '\x0C' ) } /// Extract the leading indentation from a line. pub fn leading_indentation(line: &str) -> &str { line.find(|char: char| !is_python_whitespace(char)) .map_or(line, |index| &line[..index]) } pub trait PythonWhitespace { /// Like `str::trim()`, but only removes whitespace characters that Python considers /// to be [whitespace](https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens). fn trim_whitespace(&self) -> &Self; /// Like `str::trim_start()`, but only removes whitespace characters that Python considers /// to be [whitespace](https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens). fn trim_whitespace_start(&self) -> &Self; /// Like `str::trim_end()`, but only removes whitespace characters that Python considers /// to be [whitespace](https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens). fn trim_whitespace_end(&self) -> &Self; } impl PythonWhitespace for str { fn trim_whitespace(&self) -> &Self { self.trim_matches(is_python_whitespace) } fn trim_whitespace_start(&self) -> &Self { self.trim_start_matches(is_python_whitespace) } fn trim_whitespace_end(&self) -> &Self { self.trim_end_matches(is_python_whitespace) } } #[cfg(test)] mod tests { use std::borrow::Cow; use super::{expand_tabs, tab_offset, tab_offset_u32}; #[test] fn tab_expansion_borrows_unchanged_text() { assert!(matches!(expand_tabs("unchanged"), Cow::Borrowed(_))); } #[test] fn tab_expansion_allocates_changed_text() { let expanded = expand_tabs(" \tvalue"); assert!(matches!(&expanded, Cow::Owned(_))); assert_eq!(expanded, " value"); } #[test] fn tab_offset_advances_to_next_stop() { assert_eq!(tab_offset(0, 8), 8); assert_eq!(tab_offset(2, 8), 6); assert_eq!(tab_offset(8, 8), 8); } #[test] fn u32_tab_offset_advances_to_next_stop() { assert_eq!(tab_offset_u32(0, 8), 8); assert_eq!(tab_offset_u32(2, 8), 6); assert_eq!(tab_offset_u32(8, 8), 8); } } ast_serialize-0.13.1/crates/ruff_source_file/Cargo.toml000064400000000000000000000013401046102023000200740ustar00[package] name = "ruff_source_file" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [lib] [dependencies] ruff_text_size = { workspace = true } get-size2 = { workspace = true, optional = true } memchr = { workspace = true } serde = { workspace = true, optional = true } [dev-dependencies] [features] get-size = ["dep:get-size2", "ruff_text_size/get-size"] serde = ["dep:serde", "ruff_text_size/serde"] [lints] workspace = true ast_serialize-0.13.1/crates/ruff_source_file/README.md000064400000000000000000000010361046102023000174250ustar00 # ruff_source_file This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_source_file). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_source_file/src/lib.rs000064400000000000000000000177601046102023000200640ustar00use std::cmp::Ordering; use std::fmt::{Debug, Display, Formatter}; use std::hash::Hash; use std::sync::{Arc, OnceLock}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use ruff_text_size::{Ranged, TextSize}; pub use crate::line_index::{LineIndex, OneIndexed, PositionEncoding}; pub use crate::line_ranges::LineRanges; pub use crate::newlines::{ Line, LineEnding, NewlineWithTrailingNewline, UniversalNewlineIterator, UniversalNewlines, find_newline, }; mod line_index; mod line_ranges; mod newlines; /// Gives access to the source code of a file and allows mapping between [`TextSize`] and [`LineColumn`]. #[derive(Debug)] pub struct SourceCode<'src, 'index> { text: &'src str, index: &'index LineIndex, } impl<'src, 'index> SourceCode<'src, 'index> { pub fn new(content: &'src str, index: &'index LineIndex) -> Self { Self { text: content, index, } } /// Computes the one indexed line and column numbers for `offset`, skipping any potential BOM. #[inline] pub fn line_column(&self, offset: TextSize) -> LineColumn { self.index.line_column(offset, self.text) } #[inline] pub fn source_location( &self, offset: TextSize, position_encoding: PositionEncoding, ) -> SourceLocation { self.index .source_location(offset, self.text, position_encoding) } #[inline] pub fn line_index(&self, offset: TextSize) -> OneIndexed { self.index.line_index(offset) } /// Take the source code between the given [`ruff_text_size::TextRange`]. pub fn slice(&self, ranged: T) -> &'src str { &self.text[ranged.range()] } pub fn line_start(&self, line: OneIndexed) -> TextSize { self.index.line_start(line, self.text) } pub fn line_end(&self, line: OneIndexed) -> TextSize { self.index.line_end(line, self.text) } pub fn line_end_exclusive(&self, line: OneIndexed) -> TextSize { self.index.line_end_exclusive(line, self.text) } /// Returns the source text of the line with the given index #[inline] pub fn line_text(&self, index: OneIndexed) -> &'src str { let range = self.index.line_range(index, self.text); &self.text[range] } /// Returns the source text pub fn text(&self) -> &'src str { self.text } /// Returns the number of lines #[inline] pub fn line_count(&self) -> usize { self.index.line_count() } } impl PartialEq for SourceCode<'_, '_> { fn eq(&self, other: &Self) -> bool { self.text == other.text } } impl Eq for SourceCode<'_, '_> {} /// A Builder for constructing a [`SourceFile`] pub struct SourceFileBuilder { name: Box, code: Box, index: Option, } impl SourceFileBuilder { /// Creates a new builder for a file named `name`. pub fn new>, Code: Into>>(name: Name, code: Code) -> Self { Self { name: name.into(), code: code.into(), index: None, } } /// Consumes `self` and returns the [`SourceFile`]. pub fn finish(self) -> SourceFile { let index = if let Some(index) = self.index { OnceLock::from(index) } else { OnceLock::new() }; SourceFile { inner: Arc::new(SourceFileInner { name: self.name, code: self.code, line_index: index, }), } } } /// A source file that is identified by its name. Optionally stores the source code and [`LineIndex`]. /// /// Cloning a [`SourceFile`] is cheap, because it only requires bumping a reference count. #[derive(Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct SourceFile { inner: Arc, } impl Debug for SourceFile { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("SourceFile") .field("name", &self.name()) .field("code", &self.source_text()) .finish() } } impl SourceFile { /// Returns the name of the source file (filename). #[inline] pub fn name(&self) -> &str { &self.inner.name } pub fn to_source_code(&self) -> SourceCode<'_, '_> { SourceCode { text: self.source_text(), index: self.index(), } } pub fn index(&self) -> &LineIndex { self.inner .line_index .get_or_init(|| LineIndex::from_source_text(self.source_text())) } /// Returns the source code. #[inline] pub fn source_text(&self) -> &str { &self.inner.code } } impl PartialOrd for SourceFile { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for SourceFile { fn cmp(&self, other: &Self) -> Ordering { // Short circuit if these are the same source files if Arc::ptr_eq(&self.inner, &other.inner) { Ordering::Equal } else { self.inner.name.cmp(&other.inner.name) } } } #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] struct SourceFileInner { name: Box, code: Box, line_index: OnceLock, } impl PartialEq for SourceFileInner { fn eq(&self, other: &Self) -> bool { self.name == other.name && self.code == other.code } } impl Eq for SourceFileInner {} impl Hash for SourceFileInner { fn hash(&self, state: &mut H) { self.name.hash(state); self.code.hash(state); } } /// The line and column of an offset in a source file. /// /// See [`LineIndex::line_column`] for more information. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LineColumn { /// The line in the source text. pub line: OneIndexed, /// The column (UTF scalar values) relative to the start of the line except any /// potential BOM on the first line. pub column: OneIndexed, } impl Default for LineColumn { fn default() -> Self { Self { line: OneIndexed::MIN, column: OneIndexed::MIN, } } } impl Debug for LineColumn { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("LineColumn") .field("line", &self.line.get()) .field("column", &self.column.get()) .finish() } } impl std::fmt::Display for LineColumn { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{line}:{column}", line = self.line, column = self.column) } } /// A position into a source file represented by the line number and the offset to that character relative to the start of that line. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SourceLocation { /// The line in the source text. pub line: OneIndexed, /// The offset from the start of the line to the character. /// /// This can be a byte offset, the number of UTF16 code points, or the UTF8 code units, depending on the /// [`PositionEncoding`] used. pub character_offset: OneIndexed, } impl Default for SourceLocation { fn default() -> Self { Self { line: OneIndexed::MIN, character_offset: OneIndexed::MIN, } } } #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum SourceRow { /// A row within a cell in a Jupyter Notebook. Notebook { cell: OneIndexed, line: OneIndexed }, /// A row within a source file. SourceFile { line: OneIndexed }, } impl Display for SourceRow { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { SourceRow::Notebook { cell, line } => write!(f, "cell {cell}, line {line}"), SourceRow::SourceFile { line } => write!(f, "line {line}"), } } } ast_serialize-0.13.1/crates/ruff_source_file/src/line_index.rs000064400000000000000000001016131046102023000214230ustar00use std::fmt; use std::fmt::{Debug, Formatter}; use std::num::{NonZeroUsize, ParseIntError}; use std::ops::Deref; use std::str::FromStr; use std::sync::Arc; use crate::{LineColumn, SourceLocation}; use ruff_text_size::{TextLen, TextRange, TextSize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// Index for fast [byte offset](TextSize) to [`LineColumn`] conversions. /// /// Cloning a [`LineIndex`] is cheap because it only requires bumping a reference count. #[derive(Clone, Eq, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct LineIndex { inner: Arc, } #[derive(Eq, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] struct LineIndexInner { line_starts: Vec, kind: IndexKind, } impl LineIndex { /// Builds the [`LineIndex`] from the source text of a file. pub fn from_source_text(text: &str) -> Self { let mut line_starts: Vec = Vec::with_capacity(text.len() / 88); line_starts.push(TextSize::default()); let bytes = text.as_bytes(); assert!(u32::try_from(bytes.len()).is_ok()); for i in memchr::memchr2_iter(b'\n', b'\r', bytes) { // Skip `\r` in `\r\n` sequences (only count the `\n`). if bytes[i] == b'\r' && bytes.get(i + 1) == Some(&b'\n') { continue; } // SAFETY: Assertion above guarantees `i <= u32::MAX` #[expect(clippy::cast_possible_truncation)] line_starts.push(TextSize::from(i as u32) + TextSize::from(1)); } // Determine whether the source text is ASCII. // // Empirically, this simple loop is auto-vectorized by LLVM and benchmarks faster than both // `str::is_ascii()` and hand-written SIMD. let mut has_non_ascii = false; for byte in bytes { has_non_ascii |= !byte.is_ascii(); } let kind = if has_non_ascii { IndexKind::Utf8 } else { IndexKind::Ascii }; Self { inner: Arc::new(LineIndexInner { line_starts, kind }), } } fn kind(&self) -> IndexKind { self.inner.kind } /// Returns the line and column number for an UTF-8 byte offset. /// /// The `column` number is the nth-character of the line, except for the first line /// where it doesn't include the UTF-8 BOM marker at the start of the file. /// /// ### BOM handling /// /// For files starting with a UTF-8 BOM marker, the byte offsets /// in the range `0...3` are all mapped to line 0 and column 0. /// Because of this, the conversion isn't lossless. /// /// ## Examples /// /// ``` /// # use ruff_text_size::TextSize; /// # use ruff_source_file::{LineIndex, OneIndexed, LineColumn}; /// let source = format!("\u{FEFF}{}", "def a():\n pass"); /// let index = LineIndex::from_source_text(&source); /// /// // Before BOM, maps to after BOM /// assert_eq!( /// index.line_column(TextSize::from(0), &source), /// LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(0) } /// ); /// /// // After BOM, maps to after BOM /// assert_eq!( /// index.line_column(TextSize::from(3), &source), /// LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(0) } /// ); /// /// assert_eq!( /// index.line_column(TextSize::from(7), &source), /// LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(4) } /// ); /// assert_eq!( /// index.line_column(TextSize::from(16), &source), /// LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(4) } /// ); /// ``` /// /// ## Panics /// /// If the byte offset isn't within the bounds of `content`. pub fn line_column(&self, offset: TextSize, content: &str) -> LineColumn { let location = self.source_location(offset, content, PositionEncoding::Utf32); // Don't count the BOM character as a column, but only on the first line. let column = if location.line.to_zero_indexed() == 0 && content.starts_with('\u{feff}') { location.character_offset.saturating_sub(1) } else { location.character_offset }; LineColumn { line: location.line, column, } } /// Given a UTF-8 byte offset, returns the line and character offset according to the given encoding. /// /// ### BOM handling /// /// Unlike [`Self::line_column`], this method does not skip the BOM character at the start of the file. /// This allows for bidirectional mapping between [`SourceLocation`] and [`TextSize`] (see [`Self::offset`]). /// /// ## Examples /// /// ``` /// # use ruff_text_size::TextSize; /// # use ruff_source_file::{LineIndex, OneIndexed, LineColumn, SourceLocation, PositionEncoding, Line}; /// let source = format!("\u{FEFF}{}", "def a():\n pass"); /// let index = LineIndex::from_source_text(&source); /// /// // Before BOM, maps to character 0 /// assert_eq!( /// index.source_location(TextSize::from(0), &source, PositionEncoding::Utf32), /// SourceLocation { line: OneIndexed::from_zero_indexed(0), character_offset: OneIndexed::from_zero_indexed(0) } /// ); /// /// // After BOM, maps to after BOM /// assert_eq!( /// index.source_location(TextSize::from(3), &source, PositionEncoding::Utf32), /// SourceLocation { line: OneIndexed::from_zero_indexed(0), character_offset: OneIndexed::from_zero_indexed(1) } /// ); /// /// assert_eq!( /// index.source_location(TextSize::from(7), &source, PositionEncoding::Utf32), /// SourceLocation { line: OneIndexed::from_zero_indexed(0), character_offset: OneIndexed::from_zero_indexed(5) } /// ); /// assert_eq!( /// index.source_location(TextSize::from(16), &source, PositionEncoding::Utf32), /// SourceLocation { line: OneIndexed::from_zero_indexed(1), character_offset: OneIndexed::from_zero_indexed(4) } /// ); /// ``` /// /// ## Panics /// /// If the UTF-8 byte offset is out of bounds of `text`. pub fn source_location( &self, offset: TextSize, text: &str, encoding: PositionEncoding, ) -> SourceLocation { let line = self.line_index(offset); let line_start = self.line_start(line, text); let character_offset = self.characters_between(TextRange::new(line_start, offset), text, encoding); SourceLocation { line, character_offset: OneIndexed::from_zero_indexed(character_offset), } } fn characters_between( &self, range: TextRange, text: &str, encoding: PositionEncoding, ) -> usize { if self.is_ascii() { return (range.end() - range.start()).to_usize(); } match encoding { PositionEncoding::Utf8 => (range.end() - range.start()).to_usize(), PositionEncoding::Utf16 => { let up_to_character = &text[range]; up_to_character.encode_utf16().count() } PositionEncoding::Utf32 => { let up_to_character = &text[range]; up_to_character.chars().count() } } } /// Returns the length of the line in characters, respecting the given encoding pub fn line_len(&self, line: OneIndexed, text: &str, encoding: PositionEncoding) -> usize { let line_range = self.line_range(line, text); self.characters_between(line_range, text, encoding) } /// Return the number of lines in the source code. pub fn line_count(&self) -> usize { self.line_starts().len() } /// Returns `true` if the text only consists of ASCII characters fn is_ascii(&self) -> bool { self.kind().is_ascii() } /// Returns the row number for a given offset. /// /// ## Examples /// /// ``` /// # use ruff_text_size::TextSize; /// # use ruff_source_file::{LineIndex, OneIndexed, LineColumn}; /// let source = "def a():\n pass"; /// let index = LineIndex::from_source_text(source); /// /// assert_eq!(index.line_index(TextSize::from(0)), OneIndexed::from_zero_indexed(0)); /// assert_eq!(index.line_index(TextSize::from(4)), OneIndexed::from_zero_indexed(0)); /// assert_eq!(index.line_index(TextSize::from(13)), OneIndexed::from_zero_indexed(1)); /// ``` /// /// ## Panics /// /// If the offset is out of bounds. pub fn line_index(&self, offset: TextSize) -> OneIndexed { match self.line_starts().binary_search(&offset) { // Offset is at the start of a line Ok(row) => OneIndexed::from_zero_indexed(row), Err(row) => { // SAFETY: Safe because the index always contains an entry for the offset 0 OneIndexed::from_zero_indexed(row - 1) } } } /// Returns the [byte offset](TextSize) for the `line` with the given index. pub fn line_start(&self, line: OneIndexed, contents: &str) -> TextSize { let row_index = line.to_zero_indexed(); let starts = self.line_starts(); // If start-of-line position after last line if row_index == starts.len() { contents.text_len() } else { starts[row_index] } } /// Returns the [byte offset](TextSize) of the `line`'s end. /// The offset is the end of the line, up to and including the newline character ending the line (if any). pub fn line_end(&self, line: OneIndexed, contents: &str) -> TextSize { let row_index = line.to_zero_indexed(); let starts = self.line_starts(); // If start-of-line position after last line if row_index.saturating_add(1) >= starts.len() { contents.text_len() } else { starts[row_index + 1] } } /// Returns the [byte offset](TextSize) of the `line`'s end. /// The offset is the end of the line, excluding the newline character ending the line (if any). pub(crate) fn line_end_exclusive(&self, line: OneIndexed, contents: &str) -> TextSize { let row_index = line.to_zero_indexed(); let starts = self.line_starts(); // If start-of-line position after last line if row_index.saturating_add(1) >= starts.len() { contents.text_len() } else { let next_line_start = starts[row_index + 1].to_usize(); let bytes = contents.as_bytes(); let line_ending_len = if bytes[..next_line_start].ends_with(b"\r\n") { 2 } else { 1 }; starts[row_index + 1] - TextSize::new(line_ending_len) } } /// Returns the [`TextRange`] of the `line` with the given index. /// The start points to the first character's [byte offset](TextSize), the end up to, and including /// the newline character ending the line (if any). pub fn line_range(&self, line: OneIndexed, contents: &str) -> TextRange { let starts = self.line_starts(); if starts.len() == line.to_zero_indexed() { TextRange::empty(contents.text_len()) } else { TextRange::new( self.line_start(line, contents), self.line_start(line.saturating_add(1), contents), ) } } /// Returns the [UTF-8 byte offset](TextSize) at `line` and `character` where character is counted using the given encoding. /// /// ## Examples /// /// ### ASCII only source text /// /// ``` /// # use ruff_source_file::{SourceLocation, LineIndex, OneIndexed, PositionEncoding}; /// # use ruff_text_size::TextSize; /// let source = r#"a = 4 /// c = "some string" /// x = b"#; /// /// let index = LineIndex::from_source_text(source); /// /// // First line, first character /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(0), /// character_offset: OneIndexed::from_zero_indexed(0) /// }, /// source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(0) /// ); /// /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(1), /// character_offset: OneIndexed::from_zero_indexed(4) /// }, /// source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(10) /// ); /// /// // Offset past the end of the first line /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(0), /// character_offset: OneIndexed::from_zero_indexed(10) /// }, /// source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(6) /// ); /// /// // Offset past the end of the file /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(3), /// character_offset: OneIndexed::from_zero_indexed(0) /// }, /// source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(29) /// ); /// ``` /// /// ### Non-ASCII source text /// /// ``` /// use ruff_source_file::{LineIndex, OneIndexed, SourceLocation, PositionEncoding}; /// use ruff_text_size::TextSize; /// let source = format!("\u{FEFF}{}", r#"a = 4 /// c = "❤️" /// x = b"#); /// /// let index = LineIndex::from_source_text(&source); /// /// // First line, first character, points at the BOM /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(0), /// character_offset: OneIndexed::from_zero_indexed(0) /// }, /// &source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(0) /// ); /// /// // First line, after the BOM /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(0), /// character_offset: OneIndexed::from_zero_indexed(1) /// }, /// &source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(3) /// ); /// /// // second line, 7th character, after emoji, UTF32 /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(1), /// character_offset: OneIndexed::from_zero_indexed(7) /// }, /// &source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(20) /// ); /// /// // Second line, 7th character, after emoji, UTF 16 /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(1), /// character_offset: OneIndexed::from_zero_indexed(7) /// }, /// &source, /// PositionEncoding::Utf16, /// ), /// TextSize::new(20) /// ); /// /// /// // Offset past the end of the second line /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(1), /// character_offset: OneIndexed::from_zero_indexed(10) /// }, /// &source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(22) /// ); /// /// // Offset past the end of the file /// assert_eq!( /// index.offset( /// SourceLocation { /// line: OneIndexed::from_zero_indexed(3), /// character_offset: OneIndexed::from_zero_indexed(0) /// }, /// &source, /// PositionEncoding::Utf32, /// ), /// TextSize::new(27) /// ); /// ``` pub fn offset( &self, position: SourceLocation, text: &str, position_encoding: PositionEncoding, ) -> TextSize { // If start-of-line position after last line if position.line.to_zero_indexed() > self.line_starts().len() { return text.text_len(); } let line_range = self.line_range(position.line, text); let character_offset = position.character_offset.to_zero_indexed(); let character_byte_offset = if self.is_ascii() { TextSize::try_from(character_offset).unwrap() } else { let line = &text[line_range]; match position_encoding { PositionEncoding::Utf8 => { TextSize::try_from(position.character_offset.to_zero_indexed()).unwrap() } PositionEncoding::Utf16 => { let mut byte_offset = TextSize::new(0); let mut utf16_code_unit_offset = 0; for c in line.chars() { if utf16_code_unit_offset >= character_offset { break; } // Count characters encoded as two 16 bit words as 2 characters. byte_offset += c.text_len(); utf16_code_unit_offset += c.len_utf16(); } byte_offset } PositionEncoding::Utf32 => line .chars() .take(position.character_offset.to_zero_indexed()) .map(ruff_text_size::TextLen::text_len) .sum(), } }; line_range.start() + character_byte_offset.clamp(TextSize::new(0), line_range.len()) } /// Returns the [byte offsets](TextSize) for every line pub fn line_starts(&self) -> &[TextSize] { &self.inner.line_starts } } impl Deref for LineIndex { type Target = [TextSize]; fn deref(&self) -> &Self::Target { self.line_starts() } } impl Debug for LineIndex { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.line_starts()).finish() } } #[derive(Debug, Clone, Copy, Eq, PartialEq)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] enum IndexKind { /// Optimized index for an ASCII only document Ascii, /// Index for UTF8 documents Utf8, } impl IndexKind { const fn is_ascii(self) -> bool { matches!(self, IndexKind::Ascii) } } /// Type-safe wrapper for a value whose logical range starts at `1`, for /// instance the line or column numbers in a file /// /// Internally this is represented as a [`NonZeroUsize`], this enables some /// memory optimizations #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct OneIndexed(NonZeroUsize); impl OneIndexed { /// The largest value that can be represented by this integer type pub const MAX: Self = Self::new(usize::MAX).unwrap(); // SAFETY: These constants are being initialized with non-zero values /// The smallest value that can be represented by this integer type. pub const MIN: Self = Self::new(1).unwrap(); const ONE: NonZeroUsize = NonZeroUsize::new(1).unwrap(); /// Creates a non-zero if the given value is not zero. pub const fn new(value: usize) -> Option { match NonZeroUsize::new(value) { Some(value) => Some(Self(value)), None => None, } } /// Construct a new [`OneIndexed`] from a zero-indexed value pub const fn from_zero_indexed(value: usize) -> Self { Self(Self::ONE.saturating_add(value)) } /// Returns the value as a primitive type. pub const fn get(self) -> usize { self.0.get() } /// Return the zero-indexed primitive value for this [`OneIndexed`] pub const fn to_zero_indexed(self) -> usize { self.0.get() - 1 } /// Saturating integer addition. Computes `self + rhs`, saturating at /// the numeric bounds instead of overflowing. #[must_use] pub const fn saturating_add(self, rhs: usize) -> Self { match NonZeroUsize::new(self.0.get().saturating_add(rhs)) { Some(value) => Self(value), None => Self::MAX, } } /// Saturating integer subtraction. Computes `self - rhs`, saturating /// at the numeric bounds instead of overflowing. #[must_use] pub const fn saturating_sub(self, rhs: usize) -> Self { match NonZeroUsize::new(self.0.get().saturating_sub(rhs)) { Some(value) => Self(value), None => Self::MIN, } } /// Checked addition. Returns `None` if overflow occurred. #[must_use] pub fn checked_add(self, rhs: Self) -> Option { self.0.checked_add(rhs.0.get()).map(Self) } /// Checked subtraction. Returns `None` if overflow occurred. #[must_use] pub fn checked_sub(self, rhs: Self) -> Option { self.0.get().checked_sub(rhs.get()).and_then(Self::new) } /// Calculate the number of digits in `self`. /// /// This is primarily intended for computing the length of the string representation for /// formatted printing. /// /// # Examples /// /// ``` /// use ruff_source_file::OneIndexed; /// /// let one = OneIndexed::new(1).unwrap(); /// assert_eq!(one.digits().get(), 1); /// /// let hundred = OneIndexed::new(100).unwrap(); /// assert_eq!(hundred.digits().get(), 3); /// /// let thousand = OneIndexed::new(1000).unwrap(); /// assert_eq!(thousand.digits().get(), 4); /// ``` pub const fn digits(self) -> NonZeroUsize { // Safety: the 1+ ensures this is always non-zero, and // `usize::MAX.ilog10()` << `usize::MAX`, so the result is always safe // to cast to a usize, even though it's returned as a u32 // (u64::MAX.ilog10() is 19). NonZeroUsize::new(1 + self.0.get().ilog10() as usize).unwrap() } } impl Default for OneIndexed { fn default() -> Self { Self::MIN } } impl fmt::Display for OneIndexed { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { std::fmt::Debug::fmt(&self.0.get(), f) } } impl FromStr for OneIndexed { type Err = ParseIntError; fn from_str(s: &str) -> Result { Ok(OneIndexed(NonZeroUsize::from_str(s)?)) } } #[derive(Copy, Clone, Debug)] pub enum PositionEncoding { /// Character offsets count the number of bytes from the start of the line. Utf8, /// Character offsets count the number of UTF-16 code units from the start of the line. Utf16, /// Character offsets count the number of UTF-32 code points units (the same as number of characters in Rust) /// from the start of the line. Utf32, } #[cfg(test)] mod tests { use ruff_text_size::TextSize; use crate::line_index::LineIndex; use crate::{LineColumn, OneIndexed}; #[test] fn ascii_index() { let index = LineIndex::from_source_text(""); assert_eq!(index.line_starts(), &[TextSize::from(0)]); let index = LineIndex::from_source_text("x = 1"); assert_eq!(index.line_starts(), &[TextSize::from(0)]); let index = LineIndex::from_source_text("x = 1\n"); assert_eq!(index.line_starts(), &[TextSize::from(0), TextSize::from(6)]); let index = LineIndex::from_source_text("x = 1\ny = 2\nz = x + y\n"); assert_eq!( index.line_starts(), &[ TextSize::from(0), TextSize::from(6), TextSize::from(12), TextSize::from(22) ] ); } #[test] fn ascii_source_location() { let contents = "x = 1\ny = 2"; let index = LineIndex::from_source_text(contents); // First row. let loc = index.line_column(TextSize::from(2), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(2) } ); // Second row. let loc = index.line_column(TextSize::from(6), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); let loc = index.line_column(TextSize::from(11), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(5) } ); } #[test] fn ascii_carriage_return() { let contents = "x = 4\ry = 3"; let index = LineIndex::from_source_text(contents); assert_eq!(index.line_starts(), &[TextSize::from(0), TextSize::from(6)]); assert_eq!( index.line_column(TextSize::from(4), contents), LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(4) } ); assert_eq!( index.line_column(TextSize::from(6), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); assert_eq!( index.line_column(TextSize::from(7), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(1) } ); } #[test] fn ascii_carriage_return_newline() { let contents = "x = 4\r\ny = 3"; let index = LineIndex::from_source_text(contents); assert_eq!(index.line_starts(), &[TextSize::from(0), TextSize::from(7)]); assert_eq!( index.line_column(TextSize::from(4), contents), LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(4) } ); assert_eq!( index.line_column(TextSize::from(7), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); assert_eq!( index.line_column(TextSize::from(8), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(1) } ); } #[test] fn line_end_exclusive_handles_different_line_endings() { let lf_contents = "a\nb"; let lf_index = LineIndex::from_source_text(lf_contents); assert_eq!( lf_index.line_end_exclusive(OneIndexed::from_zero_indexed(0), lf_contents), TextSize::from(1) ); assert_eq!( lf_index.line_end_exclusive(OneIndexed::from_zero_indexed(1), lf_contents), TextSize::from(3) ); let crlf_contents = "a\r\nb"; let crlf_index = LineIndex::from_source_text(crlf_contents); assert_eq!( crlf_index.line_end_exclusive(OneIndexed::from_zero_indexed(0), crlf_contents), TextSize::from(1) ); assert_eq!( crlf_index.line_end_exclusive(OneIndexed::from_zero_indexed(1), crlf_contents), TextSize::from(4) ); let cr_contents = "a\rb"; let cr_index = LineIndex::from_source_text(cr_contents); assert_eq!( cr_index.line_end_exclusive(OneIndexed::from_zero_indexed(0), cr_contents), TextSize::from(1) ); assert_eq!( cr_index.line_end_exclusive(OneIndexed::from_zero_indexed(1), cr_contents), TextSize::from(3) ); } #[test] fn utf8_index() { let index = LineIndex::from_source_text("x = '🫣'"); assert_eq!(index.line_count(), 1); assert_eq!(index.line_starts(), &[TextSize::from(0)]); let index = LineIndex::from_source_text("x = '🫣'\n"); assert_eq!(index.line_count(), 2); assert_eq!( index.line_starts(), &[TextSize::from(0), TextSize::from(11)] ); let index = LineIndex::from_source_text("x = '🫣'\ny = 2\nz = x + y\n"); assert_eq!(index.line_count(), 4); assert_eq!( index.line_starts(), &[ TextSize::from(0), TextSize::from(11), TextSize::from(17), TextSize::from(27) ] ); let index = LineIndex::from_source_text("# 🫣\nclass Foo:\n \"\"\".\"\"\""); assert_eq!(index.line_count(), 3); assert_eq!( index.line_starts(), &[TextSize::from(0), TextSize::from(7), TextSize::from(18)] ); } #[test] fn utf8_carriage_return() { let contents = "x = '🫣'\ry = 3"; let index = LineIndex::from_source_text(contents); assert_eq!(index.line_count(), 2); assert_eq!( index.line_starts(), &[TextSize::from(0), TextSize::from(11)] ); // Second ' assert_eq!( index.line_column(TextSize::from(9), contents), LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(6) } ); assert_eq!( index.line_column(TextSize::from(11), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); assert_eq!( index.line_column(TextSize::from(12), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(1) } ); } #[test] fn utf8_carriage_return_newline() { let contents = "x = '🫣'\r\ny = 3"; let index = LineIndex::from_source_text(contents); assert_eq!(index.line_count(), 2); assert_eq!( index.line_starts(), &[TextSize::from(0), TextSize::from(12)] ); // Second ' assert_eq!( index.line_column(TextSize::from(9), contents), LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(6) } ); assert_eq!( index.line_column(TextSize::from(12), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); assert_eq!( index.line_column(TextSize::from(13), contents), LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(1) } ); } #[test] fn utf8_byte_offset() { let contents = "x = '☃'\ny = 2"; let index = LineIndex::from_source_text(contents); assert_eq!( index.line_starts(), &[TextSize::from(0), TextSize::from(10)] ); // First row. let loc = index.line_column(TextSize::from(0), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(0) } ); let loc = index.line_column(TextSize::from(5), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(5) } ); let loc = index.line_column(TextSize::from(8), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(0), column: OneIndexed::from_zero_indexed(6) } ); // Second row. let loc = index.line_column(TextSize::from(10), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(0) } ); // One-past-the-end. let loc = index.line_column(TextSize::from(15), contents); assert_eq!( loc, LineColumn { line: OneIndexed::from_zero_indexed(1), column: OneIndexed::from_zero_indexed(5) } ); } } ast_serialize-0.13.1/crates/ruff_source_file/src/line_ranges.rs000064400000000000000000000325551046102023000216030ustar00use crate::find_newline; use memchr::{memchr2, memrchr2}; use ruff_text_size::{TextLen, TextRange, TextSize}; use std::ops::Add; /// Extension trait for [`str`] that provides methods for working with ranges of lines. pub trait LineRanges { /// Computes the start position of the line of `offset`. /// /// ## Examples /// /// ``` /// # use ruff_text_size::TextSize; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\rthird line"; /// /// assert_eq!(text.line_start(TextSize::from(0)), TextSize::from(0)); /// assert_eq!(text.line_start(TextSize::from(4)), TextSize::from(0)); /// /// assert_eq!(text.line_start(TextSize::from(14)), TextSize::from(11)); /// assert_eq!(text.line_start(TextSize::from(28)), TextSize::from(23)); /// ``` /// /// ## Panics /// If `offset` is out of bounds. fn line_start(&self, offset: TextSize) -> TextSize; /// Computes the start position of the file contents: either the first byte, or the byte after /// the BOM. fn bom_start_offset(&self) -> TextSize; /// Returns `true` if `offset` is at the start of a line. fn is_at_start_of_line(&self, offset: TextSize) -> bool { self.line_start(offset) == offset } /// Computes the offset that is right after the newline character that ends `offset`'s line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.full_line_end(TextSize::from(3)), TextSize::from(11)); /// assert_eq!(text.full_line_end(TextSize::from(14)), TextSize::from(24)); /// assert_eq!(text.full_line_end(TextSize::from(28)), TextSize::from(34)); /// ``` /// /// ## Panics /// /// If `offset` is passed the end of the content. fn full_line_end(&self, offset: TextSize) -> TextSize; /// Computes the offset that is right before the newline character that ends `offset`'s line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.line_end(TextSize::from(3)), TextSize::from(10)); /// assert_eq!(text.line_end(TextSize::from(14)), TextSize::from(22)); /// assert_eq!(text.line_end(TextSize::from(28)), TextSize::from(34)); /// ``` /// /// ## Panics /// /// If `offset` is passed the end of the content. fn line_end(&self, offset: TextSize) -> TextSize; /// Computes the range of this `offset`s line. /// /// The range starts at the beginning of the line and goes up to, and including, the new line character /// at the end of the line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.full_line_range(TextSize::from(3)), TextRange::new(TextSize::from(0), TextSize::from(11))); /// assert_eq!(text.full_line_range(TextSize::from(14)), TextRange::new(TextSize::from(11), TextSize::from(24))); /// assert_eq!(text.full_line_range(TextSize::from(28)), TextRange::new(TextSize::from(24), TextSize::from(34))); /// ``` /// /// ## Panics /// If `offset` is out of bounds. fn full_line_range(&self, offset: TextSize) -> TextRange { TextRange::new(self.line_start(offset), self.full_line_end(offset)) } /// Computes the range of this `offset`s line ending before the newline character. /// /// The range starts at the beginning of the line and goes up to, but excluding, the new line character /// at the end of the line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.line_range(TextSize::from(3)), TextRange::new(TextSize::from(0), TextSize::from(10))); /// assert_eq!(text.line_range(TextSize::from(14)), TextRange::new(TextSize::from(11), TextSize::from(22))); /// assert_eq!(text.line_range(TextSize::from(28)), TextRange::new(TextSize::from(24), TextSize::from(34))); /// ``` /// /// ## Panics /// If `offset` is out of bounds. fn line_range(&self, offset: TextSize) -> TextRange { TextRange::new(self.line_start(offset), self.line_end(offset)) } /// Returns the text of the `offset`'s line. /// /// The line includes the newline characters at the end of the line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.full_line_str(TextSize::from(3)), "First line\n"); /// assert_eq!(text.full_line_str(TextSize::from(14)), "second line\r\n"); /// assert_eq!(text.full_line_str(TextSize::from(28)), "third line"); /// ``` /// /// ## Panics /// If `offset` is out of bounds. fn full_line_str(&self, offset: TextSize) -> &str; /// Returns the text of the `offset`'s line. /// /// Excludes the newline characters at the end of the line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!(text.line_str(TextSize::from(3)), "First line"); /// assert_eq!(text.line_str(TextSize::from(14)), "second line"); /// assert_eq!(text.line_str(TextSize::from(28)), "third line"); /// ``` /// /// ## Panics /// If `offset` is out of bounds. fn line_str(&self, offset: TextSize) -> &str; /// Computes the range of all lines that this `range` covers. /// /// The range starts at the beginning of the line at `range.start()` and goes up to, and including, the new line character /// at the end of `range.ends()`'s line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!( /// text.full_lines_range(TextRange::new(TextSize::from(3), TextSize::from(5))), /// TextRange::new(TextSize::from(0), TextSize::from(11)) /// ); /// assert_eq!( /// text.full_lines_range(TextRange::new(TextSize::from(3), TextSize::from(14))), /// TextRange::new(TextSize::from(0), TextSize::from(24)) /// ); /// ``` /// /// ## Panics /// If the start or end of `range` is out of bounds. fn full_lines_range(&self, range: TextRange) -> TextRange { TextRange::new( self.line_start(range.start()), self.full_line_end(range.end()), ) } /// Computes the range of all lines that this `range` covers. /// /// The range starts at the beginning of the line at `range.start()` and goes up to, but excluding, the new line character /// at the end of `range.end()`'s line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!( /// text.lines_range(TextRange::new(TextSize::from(3), TextSize::from(5))), /// TextRange::new(TextSize::from(0), TextSize::from(10)) /// ); /// assert_eq!( /// text.lines_range(TextRange::new(TextSize::from(3), TextSize::from(14))), /// TextRange::new(TextSize::from(0), TextSize::from(22)) /// ); /// ``` /// /// ## Panics /// If the start or end of `range` is out of bounds. fn lines_range(&self, range: TextRange) -> TextRange { TextRange::new(self.line_start(range.start()), self.line_end(range.end())) } /// Returns true if the text of `range` contains any line break. /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert!( /// !text.contains_line_break(TextRange::new(TextSize::from(3), TextSize::from(5))), /// ); /// assert!( /// text.contains_line_break(TextRange::new(TextSize::from(3), TextSize::from(14))), /// ); /// ``` /// /// ## Panics /// If the `range` is out of bounds. fn contains_line_break(&self, range: TextRange) -> bool; /// Returns the text of all lines that include `range`. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!( /// text.lines_str(TextRange::new(TextSize::from(3), TextSize::from(5))), /// "First line" /// ); /// assert_eq!( /// text.lines_str(TextRange::new(TextSize::from(3), TextSize::from(14))), /// "First line\nsecond line" /// ); /// ``` /// /// ## Panics /// If the start or end of `range` is out of bounds. fn lines_str(&self, range: TextRange) -> &str; /// Returns the text of all lines that include `range`. /// /// Includes the newline characters of the last line. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange, TextSize}; /// # use ruff_source_file::LineRanges; /// /// let text = "First line\nsecond line\r\nthird line"; /// /// assert_eq!( /// text.full_lines_str(TextRange::new(TextSize::from(3), TextSize::from(5))), /// "First line\n" /// ); /// assert_eq!( /// text.full_lines_str(TextRange::new(TextSize::from(3), TextSize::from(14))), /// "First line\nsecond line\r\n" /// ); /// ``` /// /// ## Panics /// If the start or end of `range` is out of bounds. fn full_lines_str(&self, range: TextRange) -> &str; /// The number of lines `range` spans. /// /// ## Examples /// /// ``` /// # use ruff_text_size::{Ranged, TextRange}; /// # use ruff_source_file::LineRanges; /// /// assert_eq!("a\nb".count_lines(TextRange::up_to(1.into())), 0); /// assert_eq!("a\nb\r\nc".count_lines(TextRange::up_to(3.into())), 1, "Up to the end of the second line"); /// assert_eq!("a\nb\r\nc".count_lines(TextRange::up_to(4.into())), 2, "In between the line break characters"); /// assert_eq!("a\nb\r\nc".count_lines(TextRange::up_to(5.into())), 2); /// assert_eq!("Single line".count_lines(TextRange::up_to(13.into())), 0); /// assert_eq!("out\nof\nbounds end".count_lines(TextRange::up_to(55.into())), 2); /// ``` fn count_lines(&self, range: TextRange) -> u32 { let mut count = 0; let mut line_end = self.line_end(range.start()); loop { let next_line_start = self.full_line_end(line_end); // Reached the end of the string if next_line_start == line_end { break count; } // Range ends at the line boundary if line_end >= range.end() { break count; } count += 1; line_end = self.line_end(next_line_start); } } } impl LineRanges for str { fn line_start(&self, offset: TextSize) -> TextSize { let bytes = self[TextRange::up_to(offset)].as_bytes(); if let Some(index) = memrchr2(b'\n', b'\r', bytes) { // SAFETY: Safe because `index < offset` TextSize::try_from(index).unwrap().add(TextSize::from(1)) } else { self.bom_start_offset() } } fn bom_start_offset(&self) -> TextSize { if self.starts_with('\u{feff}') { // Skip the BOM. '\u{feff}'.text_len() } else { // Start of file. TextSize::default() } } fn full_line_end(&self, offset: TextSize) -> TextSize { let slice = &self[usize::from(offset)..]; if let Some((index, line_ending)) = find_newline(slice) { offset + TextSize::try_from(index).unwrap() + line_ending.text_len() } else { self.text_len() } } fn line_end(&self, offset: TextSize) -> TextSize { let slice = &self[offset.to_usize()..]; if let Some(index) = memchr2(b'\n', b'\r', slice.as_bytes()) { offset + TextSize::try_from(index).unwrap() } else { self.text_len() } } fn full_line_str(&self, offset: TextSize) -> &str { &self[self.full_line_range(offset)] } fn line_str(&self, offset: TextSize) -> &str { &self[self.line_range(offset)] } fn contains_line_break(&self, range: TextRange) -> bool { memchr2(b'\n', b'\r', self[range].as_bytes()).is_some() } fn lines_str(&self, range: TextRange) -> &str { &self[self.lines_range(range)] } fn full_lines_str(&self, range: TextRange) -> &str { &self[self.full_lines_range(range)] } } ast_serialize-0.13.1/crates/ruff_source_file/src/newlines.rs000064400000000000000000000317431046102023000211370ustar00use std::iter::FusedIterator; use std::ops::Deref; use memchr::{memchr2, memrchr2}; use ruff_text_size::{TextLen, TextRange, TextSize}; /// Extension trait for [`str`] that provides a [`UniversalNewlineIterator`]. pub trait UniversalNewlines { fn universal_newlines(&self) -> UniversalNewlineIterator<'_>; } impl UniversalNewlines for str { fn universal_newlines(&self) -> UniversalNewlineIterator<'_> { UniversalNewlineIterator::from(self) } } /// Like [`str::lines`], but accommodates LF, CRLF, and CR line endings, /// the latter of which are not supported by [`str::lines`]. /// /// ## Examples /// /// ```rust /// # use ruff_text_size::TextSize; /// # use ruff_source_file::{Line, UniversalNewlineIterator}; /// let mut lines = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop"); /// /// assert_eq!(lines.next_back(), Some(Line::new("bop", TextSize::from(14)))); /// assert_eq!(lines.next(), Some(Line::new("foo\n", TextSize::from(0)))); /// assert_eq!(lines.next_back(), Some(Line::new("baz\r", TextSize::from(10)))); /// assert_eq!(lines.next(), Some(Line::new("bar\n", TextSize::from(4)))); /// assert_eq!(lines.next_back(), Some(Line::new("\r\n", TextSize::from(8)))); /// assert_eq!(lines.next(), None); /// ``` #[derive(Clone)] pub struct UniversalNewlineIterator<'a> { text: &'a str, offset: TextSize, offset_back: TextSize, } impl<'a> UniversalNewlineIterator<'a> { pub fn with_offset(text: &'a str, offset: TextSize) -> UniversalNewlineIterator<'a> { UniversalNewlineIterator { text, offset, offset_back: offset + text.text_len(), } } pub fn from(text: &'a str) -> UniversalNewlineIterator<'a> { Self::with_offset(text, TextSize::default()) } } /// Finds the next newline character. Returns its position and the [`LineEnding`]. #[inline] pub fn find_newline(text: &str) -> Option<(usize, LineEnding)> { let bytes = text.as_bytes(); if let Some(position) = memchr2(b'\n', b'\r', bytes) { let line_ending = match bytes[position] { // Explicit branch for `\n` as this is the most likely path b'\n' => LineEnding::Lf, // '\r\n' b'\r' if bytes.get(position.saturating_add(1)) == Some(&b'\n') => LineEnding::CrLf, // '\r' _ => LineEnding::Cr, }; Some((position, line_ending)) } else { None } } impl<'a> Iterator for UniversalNewlineIterator<'a> { type Item = Line<'a>; #[inline] fn next(&mut self) -> Option> { if self.text.is_empty() { return None; } let line = if let Some((newline_position, line_ending)) = find_newline(self.text) { let (text, remainder) = self.text.split_at(newline_position + line_ending.len()); let line = Line { offset: self.offset, text, }; self.text = remainder; self.offset += text.text_len(); line } // Last line else { Line { offset: self.offset, text: std::mem::take(&mut self.text), } }; Some(line) } fn last(mut self) -> Option { self.next_back() } } impl DoubleEndedIterator for UniversalNewlineIterator<'_> { #[inline] fn next_back(&mut self) -> Option { if self.text.is_empty() { return None; } let len = self.text.len(); // Trim any trailing newlines. let haystack = match self.text.as_bytes()[len - 1] { b'\n' if len > 1 && self.text.as_bytes()[len - 2] == b'\r' => &self.text[..len - 2], b'\n' | b'\r' => &self.text[..len - 1], _ => self.text, }; // Find the end of the previous line. The previous line is the text up to, but not including // the newline character. let line = if let Some(line_end) = memrchr2(b'\n', b'\r', haystack.as_bytes()) { // '\n' or '\r' or '\r\n' let (remainder, line) = self.text.split_at(line_end + 1); self.text = remainder; self.offset_back -= line.text_len(); Line { text: line, offset: self.offset_back, } } else { // Last line let offset = self.offset_back - self.text.text_len(); Line { text: std::mem::take(&mut self.text), offset, } }; Some(line) } } impl FusedIterator for UniversalNewlineIterator<'_> {} /// Like [`UniversalNewlineIterator`], but includes a trailing newline as an empty line. pub struct NewlineWithTrailingNewline<'a> { trailing: Option>, underlying: UniversalNewlineIterator<'a>, } impl<'a> NewlineWithTrailingNewline<'a> { pub fn from(input: &'a str) -> NewlineWithTrailingNewline<'a> { Self::with_offset(input, TextSize::default()) } pub fn with_offset(input: &'a str, offset: TextSize) -> Self { NewlineWithTrailingNewline { underlying: UniversalNewlineIterator::with_offset(input, offset), trailing: if input.ends_with(['\r', '\n']) { Some(Line { text: "", offset: offset + input.text_len(), }) } else { None }, } } } impl<'a> Iterator for NewlineWithTrailingNewline<'a> { type Item = Line<'a>; #[inline] fn next(&mut self) -> Option { self.underlying.next().or_else(|| self.trailing.take()) } } impl DoubleEndedIterator for NewlineWithTrailingNewline<'_> { #[inline] fn next_back(&mut self) -> Option { self.trailing.take().or_else(|| self.underlying.next_back()) } } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Line<'a> { text: &'a str, offset: TextSize, } impl<'a> Line<'a> { pub fn new(text: &'a str, offset: TextSize) -> Self { Self { text, offset } } #[inline] pub const fn start(&self) -> TextSize { self.offset } /// Returns the byte offset where the line ends, including its terminating new line character. #[inline] pub fn full_end(&self) -> TextSize { self.offset + self.full_text_len() } /// Returns the byte offset where the line ends, excluding its new line character #[inline] pub fn end(&self) -> TextSize { self.offset + self.as_str().text_len() } /// Returns the range of the line, including its terminating new line character. #[inline] pub fn full_range(&self) -> TextRange { TextRange::at(self.offset, self.text.text_len()) } /// Returns the range of the line, excluding its terminating new line character #[inline] pub fn range(&self) -> TextRange { TextRange::new(self.start(), self.end()) } /// Returns the line's new line character, if any. #[inline] pub fn line_ending(&self) -> Option { let mut bytes = self.text.bytes().rev(); match bytes.next() { Some(b'\n') => { if bytes.next() == Some(b'\r') { Some(LineEnding::CrLf) } else { Some(LineEnding::Lf) } } Some(b'\r') => Some(LineEnding::Cr), _ => None, } } /// Returns the text of the line, excluding the terminating new line character. #[inline] pub fn as_str(&self) -> &'a str { let newline_len = self .line_ending() .map_or(0, |line_ending| line_ending.len()); &self.text[..self.text.len() - newline_len] } /// Returns the line's text, including the terminating new line character. #[inline] pub fn as_full_str(&self) -> &'a str { self.text } #[inline] fn full_text_len(&self) -> TextSize { self.text.text_len() } } impl Deref for Line<'_> { type Target = str; fn deref(&self) -> &Self::Target { self.as_str() } } impl PartialEq<&str> for Line<'_> { fn eq(&self, other: &&str) -> bool { self.as_str() == *other } } impl PartialEq> for &str { fn eq(&self, other: &Line<'_>) -> bool { *self == other.as_str() } } /// The line ending style used in Python source code. /// See #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum LineEnding { Lf, Cr, CrLf, } impl Default for LineEnding { fn default() -> Self { if cfg!(windows) { LineEnding::CrLf } else { LineEnding::Lf } } } impl LineEnding { pub const fn as_str(&self) -> &'static str { match self { LineEnding::Lf => "\n", LineEnding::CrLf => "\r\n", LineEnding::Cr => "\r", } } #[expect(clippy::len_without_is_empty)] pub const fn len(&self) -> usize { match self { LineEnding::Lf | LineEnding::Cr => 1, LineEnding::CrLf => 2, } } pub const fn text_len(&self) -> TextSize { match self { LineEnding::Lf | LineEnding::Cr => TextSize::new(1), LineEnding::CrLf => TextSize::new(2), } } } impl Deref for LineEnding { type Target = str; fn deref(&self) -> &Self::Target { self.as_str() } } #[cfg(test)] mod tests { use ruff_text_size::TextSize; use super::{Line, UniversalNewlineIterator}; #[test] fn universal_newlines_empty_str() { let lines: Vec<_> = UniversalNewlineIterator::from("").collect(); assert_eq!(lines, Vec::::new()); let lines: Vec<_> = UniversalNewlineIterator::from("").rev().collect(); assert_eq!(lines, Vec::::new()); } #[test] fn universal_newlines_forward() { let lines: Vec<_> = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop").collect(); assert_eq!( lines, vec![ Line::new("foo\n", TextSize::from(0)), Line::new("bar\n", TextSize::from(4)), Line::new("\r\n", TextSize::from(8)), Line::new("baz\r", TextSize::from(10)), Line::new("bop", TextSize::from(14)), ] ); let lines: Vec<_> = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop\n").collect(); assert_eq!( lines, vec![ Line::new("foo\n", TextSize::from(0)), Line::new("bar\n", TextSize::from(4)), Line::new("\r\n", TextSize::from(8)), Line::new("baz\r", TextSize::from(10)), Line::new("bop\n", TextSize::from(14)), ] ); let lines: Vec<_> = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop\n\n").collect(); assert_eq!( lines, vec![ Line::new("foo\n", TextSize::from(0)), Line::new("bar\n", TextSize::from(4)), Line::new("\r\n", TextSize::from(8)), Line::new("baz\r", TextSize::from(10)), Line::new("bop\n", TextSize::from(14)), Line::new("\n", TextSize::from(18)), ] ); } #[test] fn universal_newlines_backwards() { let lines: Vec<_> = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop") .rev() .collect(); assert_eq!( lines, vec![ Line::new("bop", TextSize::from(14)), Line::new("baz\r", TextSize::from(10)), Line::new("\r\n", TextSize::from(8)), Line::new("bar\n", TextSize::from(4)), Line::new("foo\n", TextSize::from(0)), ] ); let lines: Vec<_> = UniversalNewlineIterator::from("foo\nbar\n\nbaz\rbop\n") .rev() .map(|line| line.as_str()) .collect(); assert_eq!( lines, vec![ Line::new("bop\n", TextSize::from(13)), Line::new("baz\r", TextSize::from(9)), Line::new("\n", TextSize::from(8)), Line::new("bar\n", TextSize::from(4)), Line::new("foo\n", TextSize::from(0)), ] ); } #[test] fn universal_newlines_mixed() { let mut lines = UniversalNewlineIterator::from("foo\nbar\n\r\nbaz\rbop"); assert_eq!( lines.next_back(), Some(Line::new("bop", TextSize::from(14))) ); assert_eq!(lines.next(), Some(Line::new("foo\n", TextSize::from(0)))); assert_eq!( lines.next_back(), Some(Line::new("baz\r", TextSize::from(10))) ); assert_eq!(lines.next(), Some(Line::new("bar\n", TextSize::from(4)))); assert_eq!( lines.next_back(), Some(Line::new("\r\n", TextSize::from(8))) ); assert_eq!(lines.next(), None); } } ast_serialize-0.13.1/crates/ruff_text_size/Cargo.toml000064400000000000000000000014761046102023000176250ustar00[package] name = "ruff_text_size" version = "0.0.9-ast-serialize.0.13.1" description = "This is an internal component crate of Ruff" authors = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } readme = "README.md" [dependencies] get-size2 = { workspace = true, optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true, optional = true } [dev-dependencies] serde_test = { workspace = true } static_assertions = { workspace = true } [features] serde = ["dep:serde"] get-size = ["dep:get-size2"] [lints] workspace = true [[test]] name = "serde" path = "tests/serde.rs" required-features = ["serde"] [lib] test = false ast_serialize-0.13.1/crates/ruff_text_size/README.md000064400000000000000000000010321046102023000171400ustar00 # ruff_text_size This crate is an internal component of [Ruff](https://crates.io/crates/ruff). The Rust API exposed here is unstable and will have frequent breaking changes. This version (0.0.9) is a component of [Ruff 0.16.3](https://crates.io/crates/ruff/0.16.3). The source can be found [here](https://github.com/astral-sh/ruff/blob/0.16.3/crates/ruff_text_size). See Ruff's [crate versioning policy](https://docs.astral.sh/ruff/versioning/#crate-versioning) for details on versioning. ast_serialize-0.13.1/crates/ruff_text_size/src/lib.rs000064400000000000000000000024311046102023000175700ustar00//! Newtypes for working with text sizes/ranges in a more type-safe manner. //! //! This library can help with two things: //! * Reducing storage requirements for offsets and ranges, under the //! assumption that 32 bits is enough. //! * Providing standard vocabulary types for applications where text ranges //! are pervasive. //! //! However, you should not use this library simply because you work with //! strings. In the overwhelming majority of cases, using `usize` and //! `std::ops::Range` is better. In particular, if you are publishing a //! library, using only std types in the interface would make it more //! interoperable. Similarly, if you are writing something like a lexer, which //! produces, but does not *store* text ranges, then sticking to `usize` would //! be better. //! //! Minimal Supported Rust Version: latest stable. #![forbid(unsafe_code)] #![warn(missing_debug_implementations, missing_docs)] mod range; mod size; mod traits; #[cfg(feature = "schemars")] mod schemars_impls; #[cfg(feature = "serde")] mod serde_impls; pub use crate::{ range::TextRange, size::TextSize, traits::Ranged, traits::TextLen, traits::TextSlice, }; #[cfg(target_pointer_width = "16")] compile_error!("text-size assumes usize >= u32 and does not work on 16-bit targets"); ast_serialize-0.13.1/crates/ruff_text_size/src/range.rs000064400000000000000000000412511046102023000201210ustar00use cmp::Ordering; use { crate::TextSize, std::{ cmp, fmt, ops::{Add, AddAssign, Bound, Index, IndexMut, Range, RangeBounds, Sub, SubAssign}, }, }; /// A range in text, represented as a pair of [`TextSize`][struct@TextSize]. /// /// It is a logic error for `start` to be greater than `end`. #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TextRange { // Invariant: start <= end start: TextSize, end: TextSize, } impl fmt::Debug for TextRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}..{}", self.start().raw, self.end().raw) } } impl TextRange { /// Creates a new `TextRange` with the given `start` and `end` (`start..end`). /// /// # Panics /// /// Panics if `end < start`. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let start = TextSize::from(5); /// let end = TextSize::from(10); /// let range = TextRange::new(start, end); /// /// assert_eq!(range.start(), start); /// assert_eq!(range.end(), end); /// assert_eq!(range.len(), end - start); /// ``` #[inline] #[track_caller] pub const fn new(start: TextSize, end: TextSize) -> TextRange { assert!(start.raw <= end.raw); TextRange { start, end } } /// Create a new `TextRange` with the given `offset` and `len` (`offset..offset + len`). /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let text = "0123456789"; /// /// let offset = TextSize::from(2); /// let length = TextSize::from(5); /// let range = TextRange::at(offset, length); /// /// assert_eq!(range, TextRange::new(offset, offset + length)); /// assert_eq!(&text[range], "23456") /// ``` #[inline] pub fn at(offset: TextSize, len: TextSize) -> TextRange { TextRange::new(offset, offset + len) } /// Create a zero-length range at the specified offset (`offset..offset`). /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let point: TextSize; /// # point = TextSize::from(3); /// let range = TextRange::empty(point); /// assert!(range.is_empty()); /// assert_eq!(range, TextRange::new(point, point)); /// ``` #[inline] pub fn empty(offset: TextSize) -> TextRange { TextRange { start: offset, end: offset, } } /// Create a range up to the given end (`..end`). /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let point: TextSize; /// # point = TextSize::from(12); /// let range = TextRange::up_to(point); /// /// assert_eq!(range.len(), point); /// assert_eq!(range, TextRange::new(0.into(), point)); /// assert_eq!(range, TextRange::at(0.into(), point)); /// ``` #[inline] pub fn up_to(end: TextSize) -> TextRange { TextRange { start: 0.into(), end, } } } /// Identity methods. impl TextRange { /// The start point of this range. #[inline] pub const fn start(self) -> TextSize { self.start } /// The end point of this range. #[inline] pub const fn end(self) -> TextSize { self.end } /// The size of this range. #[inline] pub const fn len(self) -> TextSize { // HACK for const fn: math on primitives only TextSize { raw: self.end().raw - self.start().raw, } } /// Check if this range is empty. #[inline] pub const fn is_empty(self) -> bool { // HACK for const fn: math on primitives only self.start().raw == self.end().raw } } /// Manipulation methods. impl TextRange { /// Check if this range contains an offset. /// /// The end index is considered excluded. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let (start, end): (TextSize, TextSize); /// # start = 10.into(); end = 20.into(); /// let range = TextRange::new(start, end); /// assert!(range.contains(start)); /// assert!(!range.contains(end)); /// ``` #[inline] pub fn contains(self, offset: TextSize) -> bool { self.start() <= offset && offset < self.end() } /// Check if this range contains an offset. /// /// The end index is considered included. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let (start, end): (TextSize, TextSize); /// # start = 10.into(); end = 20.into(); /// let range = TextRange::new(start, end); /// assert!(range.contains_inclusive(start)); /// assert!(range.contains_inclusive(end)); /// ``` #[inline] pub fn contains_inclusive(self, offset: TextSize) -> bool { self.start() <= offset && offset <= self.end() } /// Check if this range completely contains another range. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let larger = TextRange::new(0.into(), 20.into()); /// let smaller = TextRange::new(5.into(), 15.into()); /// assert!(larger.contains_range(smaller)); /// assert!(!smaller.contains_range(larger)); /// /// // a range always contains itself /// assert!(larger.contains_range(larger)); /// assert!(smaller.contains_range(smaller)); /// ``` #[inline] pub fn contains_range(self, other: TextRange) -> bool { self.start() <= other.start() && other.end() <= self.end() } /// The range covered by both ranges, if it exists. /// If the ranges touch but do not overlap, the output range is empty. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!( /// TextRange::intersect( /// TextRange::new(0.into(), 10.into()), /// TextRange::new(5.into(), 15.into()), /// ), /// Some(TextRange::new(5.into(), 10.into())), /// ); /// ``` #[inline] pub fn intersect(self, other: TextRange) -> Option { let start = cmp::max(self.start(), other.start()); let end = cmp::min(self.end(), other.end()); if end < start { return None; } Some(TextRange::new(start, end)) } /// Extends the range to cover `other` as well. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!( /// TextRange::cover( /// TextRange::new(0.into(), 5.into()), /// TextRange::new(15.into(), 20.into()), /// ), /// TextRange::new(0.into(), 20.into()), /// ); /// ``` #[inline] #[must_use] pub fn cover(self, other: TextRange) -> TextRange { let start = cmp::min(self.start(), other.start()); let end = cmp::max(self.end(), other.end()); TextRange::new(start, end) } /// Extends the range to cover `other` offsets as well. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!( /// TextRange::empty(0.into()).cover_offset(20.into()), /// TextRange::new(0.into(), 20.into()), /// ) /// ``` #[inline] #[must_use] pub fn cover_offset(self, offset: TextSize) -> TextRange { self.cover(TextRange::empty(offset)) } /// Add an offset to this range. /// /// Note that this is not appropriate for changing where a `TextRange` is /// within some string; rather, it is for changing the reference anchor /// that the `TextRange` is measured against. /// /// The unchecked version (`Add::add`) will _always_ panic on overflow, /// in contrast to primitive integers, which check in debug mode only. #[inline] pub fn checked_add(self, offset: TextSize) -> Option { Some(TextRange { start: self.start.checked_add(offset)?, end: self.end.checked_add(offset)?, }) } /// Subtract an offset from this range. /// /// Note that this is not appropriate for changing where a `TextRange` is /// within some string; rather, it is for changing the reference anchor /// that the `TextRange` is measured against. /// /// The unchecked version (`Sub::sub`) will _always_ panic on overflow, /// in contrast to primitive integers, which check in debug mode only. #[inline] pub fn checked_sub(self, offset: TextSize) -> Option { Some(TextRange { start: self.start.checked_sub(offset)?, end: self.end.checked_sub(offset)?, }) } /// Relative order of the two ranges (overlapping ranges are considered /// equal). /// /// /// This is useful when, for example, binary searching an array of disjoint /// ranges. /// /// # Examples /// /// ``` /// # use ruff_text_size::*; /// # use std::cmp::Ordering; /// /// let a = TextRange::new(0.into(), 3.into()); /// let b = TextRange::new(4.into(), 5.into()); /// assert_eq!(a.ordering(b), Ordering::Less); /// /// let a = TextRange::new(0.into(), 3.into()); /// let b = TextRange::new(3.into(), 5.into()); /// assert_eq!(a.ordering(b), Ordering::Less); /// /// let a = TextRange::new(0.into(), 3.into()); /// let b = TextRange::new(2.into(), 5.into()); /// assert_eq!(a.ordering(b), Ordering::Equal); /// /// let a = TextRange::new(0.into(), 3.into()); /// let b = TextRange::new(2.into(), 2.into()); /// assert_eq!(a.ordering(b), Ordering::Equal); /// /// let a = TextRange::new(2.into(), 3.into()); /// let b = TextRange::new(2.into(), 2.into()); /// assert_eq!(a.ordering(b), Ordering::Greater); /// ``` #[inline] pub fn ordering(self, other: TextRange) -> Ordering { if self.end() <= other.start() { Ordering::Less } else if other.end() <= self.start() { Ordering::Greater } else { Ordering::Equal } } /// Returns a new range with the start offset set to the /// value given and the end offset unchanged from this /// range. /// /// ## Panics /// /// When `offset > self.end()`. /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// let new = range.with_start(TextSize::from(8)); /// assert_eq!(new, TextRange::new(TextSize::from(8), TextSize::from(10))); /// ``` #[inline] #[must_use] pub fn with_start(&self, offset: TextSize) -> TextRange { TextRange::new(offset, self.end()) } /// Returns a new range with the end offset set to the /// value given and the start offset unchanged from this /// range. /// /// ## Panics /// /// When `offset < self.start()`. /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// let new = range.with_end(TextSize::from(8)); /// assert_eq!(new, TextRange::new(TextSize::from(5), TextSize::from(8))); /// ``` #[inline] #[must_use] pub fn with_end(&self, offset: TextSize) -> TextRange { TextRange::new(self.start(), offset) } /// Subtracts an offset from the start position. /// /// /// ## Panics /// If `start - amount` is less than zero. /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// assert_eq!(range.sub_start(TextSize::from(2)), TextRange::new(TextSize::from(3), TextSize::from(10))); /// ``` #[inline] #[must_use] pub fn sub_start(&self, amount: TextSize) -> TextRange { TextRange::new(self.start() - amount, self.end()) } /// Adds an offset to the start position. /// /// ## Panics /// If `start + amount > end` /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// assert_eq!(range.add_start(TextSize::from(3)), TextRange::new(TextSize::from(8), TextSize::from(10))); /// ``` #[inline] #[must_use] pub fn add_start(&self, amount: TextSize) -> TextRange { TextRange::new(self.start() + amount, self.end()) } /// Subtracts an offset from the end position. /// /// /// ## Panics /// If `end - amount < 0` or `end - amount < start` /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// assert_eq!(range.sub_end(TextSize::from(2)), TextRange::new(TextSize::from(5), TextSize::from(8))); /// ``` #[inline] #[must_use] pub fn sub_end(&self, amount: TextSize) -> TextRange { TextRange::new(self.start(), self.end() - amount) } /// Adds an offset to the end position. /// /// /// ## Panics /// If `end + amount > u32::MAX` /// /// ## Examples /// /// ``` /// use ruff_text_size::{Ranged, TextRange, TextSize}; /// /// let range = TextRange::new(TextSize::from(5), TextSize::from(10)); /// assert_eq!(range.add_end(TextSize::from(2)), TextRange::new(TextSize::from(5), TextSize::from(12))); /// ``` #[inline] #[must_use] pub fn add_end(&self, amount: TextSize) -> TextRange { TextRange::new(self.start(), self.end() + amount) } } /// Conversion methods. impl TextRange { /// A convenience routine for converting this range to a /// standard library range that satisfies the `RangeBounds` /// trait. /// /// This is also available as a `From` trait implementation, /// but this method avoids the need to specify types to help /// inference. #[inline] #[must_use] pub fn to_std_range(&self) -> Range { (*self).into() } } impl Index for str { type Output = str; #[inline] fn index(&self, index: TextRange) -> &str { &self[Range::::from(index)] } } impl Index for String { type Output = str; #[inline] fn index(&self, index: TextRange) -> &str { &self[Range::::from(index)] } } impl IndexMut for str { #[inline] fn index_mut(&mut self, index: TextRange) -> &mut str { &mut self[Range::::from(index)] } } impl IndexMut for String { #[inline] fn index_mut(&mut self, index: TextRange) -> &mut str { &mut self[Range::::from(index)] } } impl RangeBounds for TextRange { fn start_bound(&self) -> Bound<&TextSize> { Bound::Included(&self.start) } fn end_bound(&self) -> Bound<&TextSize> { Bound::Excluded(&self.end) } } impl From> for TextRange { #[inline] fn from(r: Range) -> Self { TextRange::new(r.start, r.end) } } impl From for Range where T: From, { #[inline] fn from(r: TextRange) -> Self { r.start().into()..r.end().into() } } macro_rules! ops { (impl $Op:ident for TextRange by fn $f:ident = $op:tt) => { impl $Op<&TextSize> for TextRange { type Output = TextRange; #[inline] fn $f(self, other: &TextSize) -> TextRange { self $op *other } } impl $Op for &TextRange where TextRange: $Op, { type Output = TextRange; #[inline] fn $f(self, other: T) -> TextRange { *self $op other } } }; } impl Add for TextRange { type Output = TextRange; #[inline] fn add(self, offset: TextSize) -> TextRange { self.checked_add(offset) .expect("TextRange +offset overflowed") } } impl Sub for TextRange { type Output = TextRange; #[inline] fn sub(self, offset: TextSize) -> TextRange { self.checked_sub(offset) .expect("TextRange -offset overflowed") } } ops!(impl Add for TextRange by fn add = +); ops!(impl Sub for TextRange by fn sub = -); impl AddAssign for TextRange where TextRange: Add, { #[inline] fn add_assign(&mut self, rhs: A) { *self = *self + rhs; } } impl SubAssign for TextRange where TextRange: Sub, { #[inline] fn sub_assign(&mut self, rhs: S) { *self = *self - rhs; } } ast_serialize-0.13.1/crates/ruff_text_size/src/schemars_impls.rs000064400000000000000000000023221046102023000220320ustar00//! This module implements the [`JsonSchema`] trait from the `schemars` crate for //! [`TextSize`] and [`TextRange`] if the `schemars` feature is enabled. This trait //! exposes meta-information on how a given type is serialized and deserialized //! using `serde`, and is currently used to generate autocomplete information //! for the `rome.json` configuration file and TypeScript types for the node.js //! bindings to the Workspace API use crate::{TextRange, TextSize}; use schemars::{JsonSchema, Schema, SchemaGenerator}; use std::borrow::Cow; impl JsonSchema for TextSize { fn schema_name() -> Cow<'static, str> { Cow::Borrowed("TextSize") } fn json_schema(r#gen: &mut SchemaGenerator) -> Schema { // TextSize is represented as a raw u32, see serde_impls.rs for the // actual implementation ::json_schema(r#gen) } } impl JsonSchema for TextRange { fn schema_name() -> Cow<'static, str> { Cow::Borrowed("TextRange") } fn json_schema(r#gen: &mut SchemaGenerator) -> Schema { // TextSize is represented as (TextSize, TextSize), see serde_impls.rs // for the actual implementation <(TextSize, TextSize)>::json_schema(r#gen) } } ast_serialize-0.13.1/crates/ruff_text_size/src/serde_impls.rs000064400000000000000000000022451046102023000213330ustar00use { crate::{TextRange, TextSize}, serde::{Deserialize, Deserializer, Serialize, Serializer, de}, }; impl Serialize for TextSize { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.raw.serialize(serializer) } } impl<'de> Deserialize<'de> for TextSize { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { u32::deserialize(deserializer).map(TextSize::from) } } impl Serialize for TextRange { fn serialize(&self, serializer: S) -> Result where S: Serializer, { (self.start(), self.end()).serialize(serializer) } } impl<'de> Deserialize<'de> for TextRange { #[expect(clippy::nonminimal_bool)] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let (start, end) = Deserialize::deserialize(deserializer)?; if !(start <= end) { return Err(de::Error::custom(format!( "invalid range: {start:?}..{end:?}" ))); } Ok(TextRange::new(start, end)) } } ast_serialize-0.13.1/crates/ruff_text_size/src/size.rs000064400000000000000000000130271046102023000177770ustar00use { crate::TextLen, std::{ convert::TryFrom, fmt, iter, num::TryFromIntError, ops::{Add, AddAssign, Sub, SubAssign}, }, }; /// A measure of text length. Also, equivalently, an index into text. /// /// This is a UTF-8 bytes offset stored as `u32`, but /// most clients should treat it as an opaque measure. /// /// For cases that need to escape `TextSize` and return to working directly /// with primitive integers, `TextSize` can be converted losslessly to/from /// `u32` via [`From`] conversions as well as losslessly be converted [`Into`] /// `usize`. The `usize -> TextSize` direction can be done via [`TryFrom`]. /// /// These escape hatches are primarily required for unit testing and when /// converting from UTF-8 size to another coordinate space, such as UTF-16. #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "get-size", derive(get_size2::GetSize))] pub struct TextSize { pub(crate) raw: u32, } impl fmt::Debug for TextSize { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.raw) } } impl TextSize { /// A `TextSize` of zero. pub const ZERO: TextSize = TextSize::new(0); /// Creates a new `TextSize` at the given `offset`. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!(TextSize::from(4), TextSize::new(4)); /// ``` pub const fn new(offset: u32) -> Self { Self { raw: offset } } /// The text size of some primitive text-like object. /// /// Accepts `char`, `&str`, and `&String`. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// let char_size = TextSize::of('🦀'); /// assert_eq!(char_size, TextSize::from(4)); /// /// let str_size = TextSize::of("rust-analyzer"); /// assert_eq!(str_size, TextSize::from(13)); /// ``` #[inline] pub fn of(text: T) -> TextSize { text.text_len() } /// Returns current raw `offset` as u32. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!(TextSize::from(4).to_u32(), 4); /// ``` pub const fn to_u32(&self) -> u32 { self.raw } /// Returns current raw `offset` as usize. /// /// # Examples /// /// ```rust /// # use ruff_text_size::*; /// assert_eq!(TextSize::from(4).to_usize(), 4); /// ``` pub const fn to_usize(&self) -> usize { self.raw as usize } } /// Methods to act like a primitive integer type, where reasonably applicable. // Last updated for parity with Rust 1.42.0. impl TextSize { /// Checked addition. Returns `None` if overflow occurred. #[inline] pub fn checked_add(self, rhs: TextSize) -> Option { self.raw.checked_add(rhs.raw).map(|raw| TextSize { raw }) } /// Checked subtraction. Returns `None` if overflow occurred. #[inline] pub fn checked_sub(self, rhs: TextSize) -> Option { self.raw.checked_sub(rhs.raw).map(|raw| TextSize { raw }) } /// Saturating addition. Returns maximum `TextSize` if overflow occurred. #[inline] #[must_use] pub fn saturating_add(self, rhs: TextSize) -> TextSize { TextSize { raw: self.raw.saturating_add(rhs.raw), } } /// Saturating subtraction. Returns minimum `TextSize` if overflow /// occurred. #[inline] #[must_use] pub fn saturating_sub(self, rhs: TextSize) -> TextSize { TextSize { raw: self.raw.saturating_sub(rhs.raw), } } } impl From for TextSize { #[inline] fn from(raw: u32) -> Self { TextSize::new(raw) } } impl From for u32 { #[inline] fn from(value: TextSize) -> Self { value.to_u32() } } impl TryFrom for TextSize { type Error = TryFromIntError; #[inline] fn try_from(value: usize) -> Result { Ok(u32::try_from(value)?.into()) } } impl From for usize { #[inline] fn from(value: TextSize) -> Self { value.to_usize() } } macro_rules! ops { (impl $Op:ident for TextSize by fn $f:ident = $op:tt) => { impl $Op for TextSize { type Output = TextSize; #[inline] fn $f(self, other: TextSize) -> TextSize { TextSize { raw: self.raw $op other.raw } } } impl $Op<&TextSize> for TextSize { type Output = TextSize; #[inline] fn $f(self, other: &TextSize) -> TextSize { self $op *other } } impl $Op for &TextSize where TextSize: $Op, { type Output = TextSize; #[inline] fn $f(self, other: T) -> TextSize { *self $op other } } }; } ops!(impl Add for TextSize by fn add = +); ops!(impl Sub for TextSize by fn sub = -); impl AddAssign for TextSize where TextSize: Add, { #[inline] fn add_assign(&mut self, rhs: A) { *self = *self + rhs; } } impl SubAssign for TextSize where TextSize: Sub, { #[inline] fn sub_assign(&mut self, rhs: S) { *self = *self - rhs; } } impl iter::Sum for TextSize where TextSize: Add, { #[inline] fn sum>(iter: I) -> TextSize { iter.fold(0.into(), Add::add) } } ast_serialize-0.13.1/crates/ruff_text_size/src/traits.rs000064400000000000000000000040171046102023000203320ustar00use std::sync::Arc; use {crate::TextRange, crate::TextSize, std::convert::TryInto}; use priv_in_pub::Sealed; mod priv_in_pub { pub trait Sealed {} } /// Primitives with a textual length that can be passed to [`TextSize::of`]. pub trait TextLen: Copy + Sealed { /// The textual length of this primitive. fn text_len(self) -> TextSize; } impl Sealed for &'_ str {} impl TextLen for &'_ str { #[inline] fn text_len(self) -> TextSize { self.len().try_into().unwrap() } } impl Sealed for &'_ String {} impl TextLen for &'_ String { #[inline] fn text_len(self) -> TextSize { self.as_str().text_len() } } impl Sealed for char {} impl TextLen for char { #[inline] #[expect(clippy::cast_possible_truncation)] fn text_len(self) -> TextSize { (self.len_utf8() as u32).into() } } /// A ranged item in the source text. pub trait Ranged { /// The range of this item in the source text. fn range(&self) -> TextRange; /// The start offset of this item in the source text. fn start(&self) -> TextSize { self.range().start() } /// The end offset of this item in the source text. fn end(&self) -> TextSize { self.range().end() } } impl Ranged for TextRange { fn range(&self) -> TextRange { *self } } impl Ranged for &T where T: Ranged, { fn range(&self) -> TextRange { T::range(self) } } impl Ranged for Arc where T: Ranged, { fn range(&self) -> TextRange { T::range(self) } } /// A slice of the source text. pub trait TextSlice: Sealed { /// Returns the slice of the text within the given `range`. /// /// ## Note /// /// This is the same as `&self[range]` if `self` is a `str` and `range` a `TextRange`. /// /// ## Panics /// If the range is out of bounds. fn slice(&self, range: impl Ranged) -> &str; } impl Sealed for str {} impl TextSlice for str { fn slice(&self, ranged: impl Ranged) -> &str { &self[ranged.range()] } } ast_serialize-0.13.1/crates/ruff_text_size/tests/auto_traits.rs000064400000000000000000000010211046102023000217250ustar00use { ruff_text_size::{TextRange, TextSize}, static_assertions::assert_impl_all, std::{ fmt::Debug, hash::Hash, marker::{Send, Sync}, panic::{RefUnwindSafe, UnwindSafe}, }, }; // auto traits assert_impl_all!(TextSize: Send, Sync, Unpin, UnwindSafe, RefUnwindSafe); assert_impl_all!(TextRange: Send, Sync, Unpin, UnwindSafe, RefUnwindSafe); // common traits assert_impl_all!(TextSize: Copy, Debug, Default, Hash, Ord); assert_impl_all!(TextRange: Copy, Debug, Default, Hash, Eq); ast_serialize-0.13.1/crates/ruff_text_size/tests/constructors.rs000064400000000000000000000007001046102023000221420ustar00use ruff_text_size::TextSize; #[derive(Copy, Clone)] struct BadRope<'a>(&'a [&'a str]); impl BadRope<'_> { fn text_len(self) -> TextSize { self.0.iter().copied().map(TextSize::of).sum() } } #[test] fn main() { let x: char = 'c'; let _ = TextSize::of(x); let x: &str = "hello"; let _ = TextSize::of(x); let x: &String = &"hello".into(); let _ = TextSize::of(x); let _ = BadRope(&[""]).text_len(); } ast_serialize-0.13.1/crates/ruff_text_size/tests/indexing.rs000064400000000000000000000002271046102023000212030ustar00use ruff_text_size::TextRange; #[test] fn main() { let range = TextRange::default(); let _ = &""[range]; let _ = &String::new()[range]; } ast_serialize-0.13.1/crates/ruff_text_size/tests/main.rs000064400000000000000000000043741046102023000203310ustar00use { ruff_text_size::{TextRange, TextSize}, std::ops, }; fn size(x: u32) -> TextSize { TextSize::from(x) } fn range(x: ops::Range) -> TextRange { TextRange::new(x.start.into(), x.end.into()) } #[test] fn sum() { let xs: Vec = vec![size(0), size(1), size(2)]; assert_eq!(xs.iter().sum::(), size(3)); assert_eq!(xs.into_iter().sum::(), size(3)); } #[test] fn math() { assert_eq!(size(10) + size(5), size(15)); assert_eq!(size(10) - size(5), size(5)); } #[test] fn checked_math() { assert_eq!(size(1).checked_add(size(1)), Some(size(2))); assert_eq!(size(1).checked_sub(size(1)), Some(size(0))); assert_eq!(size(1).checked_sub(size(2)), None); assert_eq!(size(!0).checked_add(size(1)), None); } #[test] #[rustfmt::skip] fn contains() { assert!( range(2..4).contains_range(range(2..3))); assert!( ! range(2..4).contains_range(range(1..3))); } #[test] fn intersect() { assert_eq!(range(1..2).intersect(range(2..3)), Some(range(2..2))); assert_eq!(range(1..5).intersect(range(2..3)), Some(range(2..3))); assert_eq!(range(1..2).intersect(range(3..4)), None); } #[test] fn cover() { assert_eq!(range(1..2).cover(range(2..3)), range(1..3)); assert_eq!(range(1..5).cover(range(2..3)), range(1..5)); assert_eq!(range(1..2).cover(range(4..5)), range(1..5)); } #[test] fn cover_offset() { assert_eq!(range(1..3).cover_offset(size(0)), range(0..3)); assert_eq!(range(1..3).cover_offset(size(1)), range(1..3)); assert_eq!(range(1..3).cover_offset(size(2)), range(1..3)); assert_eq!(range(1..3).cover_offset(size(3)), range(1..3)); assert_eq!(range(1..3).cover_offset(size(4)), range(1..4)); } #[test] #[rustfmt::skip] fn contains_point() { assert!( ! range(1..3).contains(size(0))); assert!( range(1..3).contains(size(1))); assert!( range(1..3).contains(size(2))); assert!( ! range(1..3).contains(size(3))); assert!( ! range(1..3).contains(size(4))); assert!( ! range(1..3).contains_inclusive(size(0))); assert!( range(1..3).contains_inclusive(size(1))); assert!( range(1..3).contains_inclusive(size(2))); assert!( range(1..3).contains_inclusive(size(3))); assert!( ! range(1..3).contains_inclusive(size(4))); } ast_serialize-0.13.1/crates/ruff_text_size/tests/serde.rs000064400000000000000000000034201046102023000204760ustar00use { ruff_text_size::{TextRange, TextSize}, serde_test::{Token, assert_de_tokens_error, assert_tokens}, std::ops, }; fn size(x: u32) -> TextSize { TextSize::from(x) } fn range(x: ops::Range) -> TextRange { TextRange::new(x.start.into(), x.end.into()) } #[test] fn size_serialization() { assert_tokens(&size(00), &[Token::U32(00)]); assert_tokens(&size(10), &[Token::U32(10)]); assert_tokens(&size(20), &[Token::U32(20)]); assert_tokens(&size(30), &[Token::U32(30)]); } #[test] fn range_serialization() { assert_tokens( &range(00..10), &[ Token::Tuple { len: 2 }, Token::U32(00), Token::U32(10), Token::TupleEnd, ], ); assert_tokens( &range(10..20), &[ Token::Tuple { len: 2 }, Token::U32(10), Token::U32(20), Token::TupleEnd, ], ); assert_tokens( &range(20..30), &[ Token::Tuple { len: 2 }, Token::U32(20), Token::U32(30), Token::TupleEnd, ], ); assert_tokens( &range(30..40), &[ Token::Tuple { len: 2 }, Token::U32(30), Token::U32(40), Token::TupleEnd, ], ); } #[test] fn invalid_range_deserialization() { assert_tokens::( &range(62..92), &[ Token::Tuple { len: 2 }, Token::U32(62), Token::U32(92), Token::TupleEnd, ], ); assert_de_tokens_error::( &[ Token::Tuple { len: 2 }, Token::U32(92), Token::U32(62), Token::TupleEnd, ], "invalid range: 92..62", ); } ast_serialize-0.13.1/pyproject.toml000064400000000000000000000027521046102023000142660ustar00[build-system] requires = ["maturin>=1.9,<2.0"] build-backend = "maturin" [project] name = "ast_serialize" version = "0.13.1" description = "Python bindings for mypy AST serialization" readme = {text = """ ast_serialize - Python Parser and AST Serializer ================================================ This is a fast Python extension for parsing Python files and serializing the AST using the native binary format used by mypy. This will eventually replace the current mypy parser, which uses the Python stdlib ``ast`` module for parsing. """, content-type = "text/x-rst"} authors = [{name = "Jukka Lehtosalo", email = "jukka.lehtosalo@iki.fi"}] classifiers = [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.15", "Programming Language :: Rust", "Topic :: Software Development", "Typing :: Typed", ] requires-python = ">=3.7" license = "MIT" license-files = ["LICENSE", "crates/LICENSE"] [project.urls] Homepage = "https://github.com/mypyc/ast_serialize" Issues = "https://github.com/mypyc/ast_serialize/issues" [tool.maturin] bindings = "pyo3" manifest-path = "Cargo.toml" module-name = "ast_serialize" ast_serialize-0.13.1/rustfmt.toml000064400000000000000000000000501046102023000137400ustar00edition = "2024" style_edition = "2024" ast_serialize-0.13.1/src/func_effect_visitor.rs000064400000000000000000000537471046102023000165470ustar00//! Visitor to detect if a function body has externally visible effects. //! //! This is used to determine if a function body can be safely omitted during serialization //! when errors are ignored in a file. A function body must be preserved if it has effects //! that are externally visible, such as: //! - Defining attributes on its first parameter (e.g., `self.x = 1`) //! - Containing yield expressions that affect the return type use ruff_python_ast::{self as ast, visitor::Visitor}; /// Check if a function body is "trivial" (e.g., pass, ..., raise, or just docstring). /// /// Trivial bodies may be needed for type checking as they have externally visible impact. /// This matches the behavior of mypy's trivial body detection. /// /// A body is considered trivial if it contains: /// - Just a docstring (string literal as a standalone statement) /// - A docstring followed by pass /// - A docstring followed by raise /// - A docstring followed by `...` (ellipsis literal) /// /// # Examples /// /// ```python /// # Trivial: /// def foo(): /// pass /// /// def bar(): /// """Docstring""" /// /// def baz(): /// """Docstring""" /// pass /// /// def qux(): /// raise NotImplementedError /// /// # Not trivial: /// def compute(): /// return 42 /// ``` pub(crate) fn is_trivial_body(body: &[ast::Stmt]) -> bool { if body.is_empty() { return false; } let mut i = 0; // Skip docstring if present (first statement is a string literal expression) if let Some(ast::Stmt::Expr(expr_stmt)) = body.first() { if matches!(&*expr_stmt.value, ast::Expr::StringLiteral(_)) { i += 1; } } // If only a docstring, it's trivial if i == body.len() { return true; } // If more than one non-docstring statement, it's not trivial if body.len() > i + 1 { return false; } // Check if the single non-docstring statement is pass, raise, or ellipsis let stmt = &body[i]; match stmt { ast::Stmt::Pass(_) | ast::Stmt::Raise(_) => true, ast::Stmt::Expr(expr_stmt) => { // Check if it's an ellipsis literal expression matches!(&*expr_stmt.value, ast::Expr::EllipsisLiteral(_)) } _ => false, } } /// Check if a function body has externally visible effects. /// /// Returns `true` if the function body contains: /// - Any assignments to attributes of the first parameter (if `check_attributes` is true): /// - Direct assignments: `self.x = 1` /// - Augmented assignments: `self.x += 1` /// - Annotated assignments: `self.x: int = 1` /// - Tuple/list unpacking: `self.x, self.y = f()` /// - Starred expressions: `*self.x = range(10)` /// - Nested tuple/list unpacking: `(self.x, (self.y, self.z)) = f()` /// - Yield expressions: `yield x` or `yield from iterable` /// (these affect the inferred return type, making the function a generator) /// /// Returns `false` if no externally visible effects are found. /// /// # Arguments /// /// * `body` - The function body statements to analyze /// * `parameters` - The function parameters /// * `check_attributes` - Whether to check for attribute assignments (true for methods, false for top-level functions) /// /// # Examples /// /// ```python /// # Returns true for (when check_attributes=true): /// def foo(self): /// self.x = 1 /// /// # Returns true for (regardless of check_attributes): /// def bar(): /// yield 1 /// /// # Returns false for: /// def baz(self): /// local_var = 1 /// ``` pub(crate) fn has_externally_visible_effect( body: &[ast::Stmt], parameters: &ast::Parameters, check_attributes: bool, ) -> bool { // Trivial bodies always have externally visible effects (needed for type checking) if is_trivial_body(body) { return true; } // Get the name of the first parameter (if any) let first_param_name = if check_attributes { parameters .posonlyargs .first() .or(parameters.args.first()) .map(|p| p.parameter.name.as_str()) .unwrap_or("") } else { "" // Don't check attributes if not requested }; let mut visitor = EffectDetector { first_param_name, defines_attributes: false, contains_yield: false, }; visitor.visit_body(body); visitor.defines_attributes || visitor.contains_yield } /// Visitor that detects externally visible effects in function bodies. struct EffectDetector<'a> { /// Name of the first parameter to check (e.g., "self") first_param_name: &'a str, /// Whether we've found an attribute assignment defines_attributes: bool, /// Whether we've found a yield expression contains_yield: bool, } impl<'a> Visitor<'a> for EffectDetector<'a> { fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { // Early exit if we already found both an attribute definition and yield if self.defines_attributes && self.contains_yield { return; } match stmt { // Don't recurse into nested functions/classes - they have their own scope ast::Stmt::FunctionDef(_) | ast::Stmt::ClassDef(_) => { // Simply skip nested definitions entirely return; } // Check various assignment forms ast::Stmt::Assign(assign) => { // Check all targets (can have multiple in `a = b = 1`) for target in &assign.targets { if self.contains_param_attribute(target) { self.defines_attributes = true; return; } } } ast::Stmt::AugAssign(aug_assign) => { if self.contains_param_attribute(&aug_assign.target) { self.defines_attributes = true; return; } } ast::Stmt::AnnAssign(ann_assign) => { if self.contains_param_attribute(&ann_assign.target) { self.defines_attributes = true; return; } } ast::Stmt::With(with_stmt) => { // Check `with expr as target:` - target can be self.x for item in &with_stmt.items { if let Some(optional_vars) = &item.optional_vars { if self.contains_param_attribute(optional_vars) { self.defines_attributes = true; return; } } } } ast::Stmt::For(for_stmt) => { // Check `for target in iter:` - target can be self.x if self.contains_param_attribute(&for_stmt.target) { self.defines_attributes = true; return; } } _ => {} } // Continue walking the AST ast::visitor::walk_stmt(self, stmt); } fn visit_expr(&mut self, expr: &'a ast::Expr) { // Early exit if we already found both an attribute definition and yield if self.defines_attributes && self.contains_yield { return; } // Check for yield expressions match expr { ast::Expr::Yield(_) | ast::Expr::YieldFrom(_) => { self.contains_yield = true; // Don't need to walk further into yield expression return; } // Don't recurse into nested functions/lambdas - they have their own scope ast::Expr::Lambda(_) => { // Skip lambda bodies - yield in a lambda would be a syntax error anyway, // but we skip for consistency with nested function handling return; } _ => {} } // Continue walking the AST ast::visitor::walk_expr(self, expr); } } impl<'a> EffectDetector<'a> { /// Check if an expression contains an attribute access on the first parameter. /// /// This handles: /// - Direct attribute: `self.x` /// - Tuple unpacking: `(self.x, y)`, `self.x, y` /// - List unpacking: `[self.x, y]` /// - Starred expressions: `*self.x` /// - Nested structures: `(self.x, (self.y, z))` fn contains_param_attribute(&self, expr: &ast::Expr) -> bool { match expr { ast::Expr::Attribute(attr) => { // Check if this is `param_name.something` matches!(&*attr.value, ast::Expr::Name(name) if name.id.as_str() == self.first_param_name) } ast::Expr::Tuple(tuple) => { // Check all elements in tuple: `self.x, self.y = f()` tuple .elts .iter() .any(|elt| self.contains_param_attribute(elt)) } ast::Expr::List(list) => { // Check all elements in list: `[self.x, self.y] = f()` list.elts .iter() .any(|elt| self.contains_param_attribute(elt)) } ast::Expr::Starred(starred) => { // Check starred expression: `*self.x = range(10)` self.contains_param_attribute(&starred.value) } _ => false, } } } #[cfg(test)] mod tests { use super::*; use ruff_python_ast::PySourceType; use ruff_python_parser::{ParseOptions, parse_unchecked}; /// Helper to parse a function and check if it has externally visible effects /// Assumes we're checking a method (check_attributes = true) fn check_function(code: &str) -> bool { let parsed = parse_unchecked(code, ParseOptions::from(PySourceType::Python)); let ast::Mod::Module(module) = parsed.into_syntax() else { panic!("Expected module"); }; // Get the first function definition for stmt in &module.body { if let ast::Stmt::FunctionDef(func) = stmt { return has_externally_visible_effect(&func.body, &func.parameters, true); } } panic!("No function found in code"); } /// Helper to check top-level function (check_attributes = false) fn check_toplevel_function(code: &str) -> bool { let parsed = parse_unchecked(code, ParseOptions::from(PySourceType::Python)); let ast::Mod::Module(module) = parsed.into_syntax() else { panic!("Expected module"); }; // Get the first function definition for stmt in &module.body { if let ast::Stmt::FunctionDef(func) = stmt { return has_externally_visible_effect(&func.body, &func.parameters, false); } } panic!("No function found in code"); } #[test] fn test_simple_attribute_assignment() { let code = r#" def foo(self): self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_no_attribute_assignment() { let code = r#" def foo(self): local_var = 1 "#; assert!(!check_function(code)); } #[test] fn test_no_parameters() { let code = r#" def foo(): x = 1 "#; assert!(!check_function(code)); } #[test] fn test_augmented_assignment() { let code = r#" def foo(self): self.x += 1 "#; assert!(check_function(code)); } #[test] fn test_annotated_assignment() { let code = r#" def foo(self): self.x: int = 1 "#; assert!(check_function(code)); } #[test] fn test_tuple_unpacking() { let code = r#" def foo(self): self.x, y = (1, 2) "#; assert!(check_function(code)); } #[test] fn test_tuple_unpacking_second_element() { let code = r#" def foo(self): x, self.y = (1, 2) "#; assert!(check_function(code)); } #[test] fn test_tuple_unpacking_no_self() { let code = r#" def foo(self): x, y = (1, 2) "#; assert!(!check_function(code)); } #[test] fn test_list_unpacking() { let code = r#" def foo(self): [self.x, y] = [1, 2] "#; assert!(check_function(code)); } #[test] fn test_nested_tuple_unpacking() { let code = r#" def foo(self): (self.x, (y, z)) = (1, (2, 3)) "#; assert!(check_function(code)); } #[test] fn test_nested_list_unpacking() { let code = r#" def foo(self): [a, [self.y, z]] = [1, [2, 3]] "#; assert!(check_function(code)); } #[test] fn test_deeply_nested_unpacking() { let code = r#" def foo(self): (a, (b, (self.x, c))) = (1, (2, (3, 4))) "#; assert!(check_function(code)); } #[test] fn test_starred_expression() { let code = r#" def foo(self): *self.x, = range(10) "#; assert!(check_function(code)); } #[test] fn test_starred_in_tuple() { let code = r#" def foo(self): a, *self.rest = [1, 2, 3, 4] "#; assert!(check_function(code)); } #[test] fn test_nested_function_no_leak() { // Attribute assignment in nested function should not count let code = r#" def foo(self): def inner(self): self.x = 1 return inner "#; assert!(!check_function(code)); } #[test] fn test_nested_class_no_leak() { // Attribute assignment in nested class should not count let code = r#" def foo(self): class Inner: def method(self): self.x = 1 "#; assert!(!check_function(code)); } #[test] fn test_attribute_in_if_statement() { let code = r#" def foo(self): if True: self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_attribute_in_while_loop() { let code = r#" def foo(self): while True: self.x = 1 break "#; assert!(check_function(code)); } #[test] fn test_attribute_in_for_loop() { let code = r#" def foo(self): for i in range(10): self.x = i "#; assert!(check_function(code)); } #[test] fn test_attribute_in_try_except() { let code = r#" def foo(self): try: self.x = 1 except: pass "#; assert!(check_function(code)); } #[test] fn test_attribute_in_except_handler() { let code = r#" def foo(self): try: pass except Exception: self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_attribute_in_finally() { let code = r#" def foo(self): try: pass finally: self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_attribute_in_with_statement() { let code = r#" def foo(self): with open("file") as f: self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_attribute_assignment_after_nested_function() { let code = r#" def foo(self): def inner(): pass self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_multiple_assignment_targets() { let code = r#" def foo(self): self.x = y = 1 "#; assert!(check_function(code)); } #[test] fn test_different_param_name() { let code = r#" def foo(obj): obj.x = 1 "#; assert!(check_function(code)); } #[test] fn test_attribute_of_different_object() { let code = r#" def foo(self): other.x = 1 "#; assert!(!check_function(code)); } #[test] fn test_posonly_param() { let code = r#" def foo(self, /): self.x = 1 "#; assert!(check_function(code)); } #[test] fn test_posonly_param_no_assignment() { let code = r#" def foo(self, /): y = 1 "#; assert!(!check_function(code)); } #[test] fn test_empty_body() { // A body with just `pass` is now considered trivial (externally visible) let code = r#" def foo(self): pass "#; assert!(check_function(code)); } #[test] fn test_only_docstring() { // A body with just docstring and pass is now considered trivial (externally visible) let code = r#" def foo(self): """Docstring""" pass "#; assert!(check_function(code)); } #[test] fn test_mixed_tuple_and_list() { let code = r#" def foo(self): (a, [self.x, b]) = (1, [2, 3]) "#; assert!(check_function(code)); } // Yield expression tests #[test] fn test_simple_yield() { let code = r#" def foo(self): yield 1 "#; assert!(check_function(code)); } #[test] fn test_yield_from() { let code = r#" def foo(self): yield from range(10) "#; assert!(check_function(code)); } #[test] fn test_yield_in_loop() { let code = r#" def foo(self): for i in range(10): yield i "#; assert!(check_function(code)); } #[test] fn test_yield_in_if() { let code = r#" def foo(self): if True: yield 1 "#; assert!(check_function(code)); } #[test] fn test_yield_in_expression() { let code = r#" def foo(self): x = (yield 1) "#; assert!(check_function(code)); } #[test] fn test_yield_with_no_value() { let code = r#" def foo(self): yield "#; assert!(check_function(code)); } #[test] fn test_yield_in_comprehension() { // Yield in generator expression let code = r#" def foo(self): return [(yield i) for i in range(10)] "#; assert!(check_function(code)); } #[test] fn test_yield_with_attribute_assignment() { // Both yield and attribute assignment let code = r#" def foo(self): self.x = 1 yield 2 "#; assert!(check_function(code)); } #[test] fn test_yield_in_nested_function_no_leak() { // Yield in nested function should not count let code = r#" def foo(self): def inner(): yield 1 return inner "#; assert!(!check_function(code)); } #[test] fn test_no_yield_no_attributes() { let code = r#" def foo(self): x = 1 return x "#; assert!(!check_function(code)); } #[test] fn test_yield_in_try_except() { let code = r#" def foo(self): try: yield 1 except: pass "#; assert!(check_function(code)); } #[test] fn test_yield_in_with() { let code = r#" def foo(self): with open("file") as f: yield f.read() "#; assert!(check_function(code)); } #[test] fn test_yield_no_params() { // Function with no parameters but with yield should still preserve body let code = r#" def foo(): yield 1 "#; assert!(check_function(code)); } // Tests for top-level functions (check_attributes = false) #[test] fn test_toplevel_with_yield() { let code = r#" def foo(): yield 1 "#; assert!(check_toplevel_function(code)); } #[test] fn test_toplevel_with_attribute_assignment() { // Top-level function with attribute assignment should NOT count // (since check_attributes = false) let code = r#" def foo(self): self.x = 1 "#; assert!(!check_toplevel_function(code)); } #[test] fn test_toplevel_plain_function() { let code = r#" def foo(x): return x + 1 "#; assert!(!check_toplevel_function(code)); } #[test] fn test_toplevel_with_yield_in_loop() { let code = r#" def foo(items): for item in items: yield item "#; assert!(check_toplevel_function(code)); } #[test] fn test_with_statement_target() { let code = r#" def foo(self): with y as self.x: pass "#; assert!(check_function(code)); } #[test] fn test_for_statement_target() { let code = r#" def foo(self): for self.x in items: pass "#; assert!(check_function(code)); } // Tests for trivial body detection #[test] fn test_trivial_pass() { let code = r#" def foo(): pass "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_ellipsis() { let code = r#" def foo(): ... "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_raise() { let code = r#" def foo(): raise NotImplementedError "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_docstring_only() { let code = r#" def foo(): """Docstring""" "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_docstring_and_pass() { let code = r#" def foo(): """Docstring""" pass "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_docstring_and_ellipsis() { let code = r#" def foo(): """Docstring""" ... "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_trivial_docstring_and_raise() { let code = r#" def foo(): """Docstring""" raise NotImplementedError "#; assert!(check_function(code)); assert!(check_toplevel_function(code)); } #[test] fn test_not_trivial_return() { let code = r#" def foo(): return 42 "#; assert!(!check_toplevel_function(code)); } #[test] fn test_not_trivial_assignment() { let code = r#" def foo(): x = 1 "#; assert!(!check_toplevel_function(code)); } #[test] fn test_not_trivial_multiple_statements() { let code = r#" def foo(): """Docstring""" pass pass "#; assert!(!check_toplevel_function(code)); } #[test] fn test_not_trivial_docstring_and_return() { let code = r#" def foo(): """Docstring""" return 42 "#; assert!(!check_toplevel_function(code)); } } ast_serialize-0.13.1/src/lib.rs000064400000000000000000000174251046102023000132600ustar00use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; use std::path::Path; mod func_effect_visitor; mod mypy_inline_config; mod options; pub mod reachability; mod serialize_ast; pub mod type_comment; /// Parse a Python file and serialize its AST to mypy's binary format. /// /// # Arguments /// /// * `fnam` - Path to the Python file to parse /// * `skip_function_bodies` - Optional boolean to skip function bodies without externally visible effects (default: false) /// * `python_version` - Optional tuple (major, minor) for reachability analysis (default: use sys.version_info) /// * `platform` - Optional platform string for reachability analysis (default: use sys.platform) /// * `always_true` - Optional list of names that are always considered true (default: empty) /// * `always_false` - Optional list of names that are always considered false (default: empty) /// /// # Returns /// /// A tuple containing: /// - bytes: The serialized AST in mypy's format (may be partial if there are syntax errors) /// - list: A list of syntax errors, where each error is a dict with 'line', 'column', and 'message' /// - list[tuple[int, list[str]]]: A list of tuples (line_number, error_codes) for `type: ignore` comments /// - bytes: The serialized imports metadata /// /// # Errors /// /// Raises ValueError if the file cannot be read (but not for syntax errors) #[pyfunction] #[pyo3(signature = ( fnam, source=None, skip_function_bodies=false, python_version=None, platform=None, always_true=None, always_false=None, cache_version=0 ))] fn parse( py: Python, fnam: String, source: Option, skip_function_bodies: bool, python_version: Option<(u32, u32)>, platform: Option, always_true: Option>, always_false: Option>, cache_version: u32, ) -> PyResult<(Vec, Vec>, Vec>, Vec, Py)> { // Get defaults from Python if not provided let python_version = match python_version { Some(v) => v, None => get_default_python_version(py)?, }; let platform = match platform { Some(p) => p, None => get_default_platform(py)?, }; let always_true = always_true.unwrap_or_default(); let always_false = always_false.unwrap_or_default(); let src = source .as_ref() .map(|src| match src { serialize_ast::Source::Text(src) => Ok(src.as_ref()), serialize_ast::Source::Bytes(src) => std::str::from_utf8(src).map_err(|e| { match pyo3::exceptions::PyUnicodeDecodeError::new_utf8(py, src, e) { Ok(err) => PyErr::from_value(err.into_any()), Err(err) => err, } }), }) .transpose()?; let path = Path::new(&fnam); let ( ast_bytes, syntax_errors, type_ignore_lines, mypy_ignore_lines, import_bytes, is_partial_package, uses_template_strings, source_hash, mypy_comments, ) = py .detach(|| { serialize_ast::serialize_python_file( path, src, skip_function_bodies, options::Options::new( python_version, platform, always_true, always_false, cache_version, ), ) }) .map_err(|e| PyErr::new::(e.to_string()))?; // Convert syntax errors to Python dicts let py_errors: PyResult>> = syntax_errors .iter() .map(|error| { let dict = PyDict::new(py); dict.set_item("line", error.line)?; dict.set_item("column", error.column)?; dict.set_item("message", error.message.clone())?; dict.set_item("blocker", error.blocker)?; Ok(dict.into()) }) .collect(); let py_errors = py_errors?; // Convert type ignore lines to Python tuples (line, error_codes) let py_type_ignores = to_py_tuples(py, type_ignore_lines)?; // Same for mypy: ignore comments. let py_mypy_ignores = to_py_tuples(py, mypy_ignore_lines)?; // Add various mypy-specific extra information about AST. let ast_data = PyDict::new(py); ast_data.set_item("is_partial_package", is_partial_package)?; ast_data.set_item("mypy_ignores", py_mypy_ignores)?; ast_data.set_item("uses_template_strings", uses_template_strings)?; ast_data.set_item("source_hash", source_hash)?; let py_mypy_comments: PyResult>> = mypy_comments .iter() .map(|(line, text)| { let tuple = PyTuple::new( py, [ line.into_pyobject(py)?.into_any(), text.into_pyobject(py)?.into_any(), ], )?; Ok(tuple.into()) }) .collect(); ast_data.set_item("mypy_comments", py_mypy_comments?)?; let ast_data = ast_data.into(); Ok(( ast_bytes, py_errors, py_type_ignores, import_bytes, ast_data, )) } fn to_py_tuples(py: Python, ignore_lines: Vec<(usize, Vec)>) -> PyResult>> { ignore_lines .iter() .map(|(line, error_codes)| { let tuple = PyTuple::new( py, [ line.into_pyobject(py)?.into_any(), error_codes.into_pyobject(py)?.into_any(), ], )?; Ok(tuple.into()) }) .collect() } /// Get the default Python version from sys.version_info fn get_default_python_version(py: Python) -> PyResult<(u32, u32)> { let sys = py.import("sys")?; let version_info = sys.getattr("version_info")?; let major: u32 = version_info.get_item(0)?.extract()?; let minor: u32 = version_info.get_item(1)?.extract()?; Ok((major, minor)) } /// Get the default platform from sys.platform fn get_default_platform(py: Python) -> PyResult { let sys = py.import("sys")?; sys.getattr("platform")?.extract() } /// Parse and serialize a single type (escaped as a string, e.g. a forward reference) /// /// # Arguments /// /// * `source` - The type string source /// * `range` - The location of the type string on original source file as /// `(line, column, end_line, end_column)` /// * `cache_version` - The cache version to use for serialization /// /// # Returns /// /// bytes: The serialized AST in mypy's format /// /// # Errors /// /// Normally should never raise. #[pyfunction] #[pyo3(signature = ( source, range, cache_version=0 ))] fn parse_type_string( py: Python, source: String, range: (u32, u32, u32, u32), cache_version: u32, ) -> PyResult> { // These should only affect reachability, so we can use random values here // (we use hardcoded instead of default ones for performance). let python_version = (3, 10); let platform = "linux".to_string(); let ast_bytes = py .detach(|| { serialize_ast::serialize_type_string( source.as_ref(), options::Options::new( python_version, platform, Vec::new(), Vec::new(), cache_version, ), range, ) }) .map_err(|e| PyErr::new::(e.to_string()))?; Ok(ast_bytes) } /// A Python module for parsing Python files and serializing to mypy AST format #[pymodule] fn ast_serialize(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(parse, m)?)?; m.add_function(wrap_pyfunction!(parse_type_string, m)?)?; Ok(()) } ast_serialize-0.13.1/src/mypy_inline_config.rs000064400000000000000000000235161046102023000163710ustar00/// Lightweight parsing of `# mypy: ...` inline configuration comments. /// /// This only extracts the options that affect AST parsing/serialization: /// - `always_true` / `always-true`: names treated as always true in reachability /// - `always_false` / `always-false`: names treated as always false in reachability /// - `ignore_errors` / `ignore-errors`: skip function bodies /// /// The full comment text is still returned to Python for complete config processing. /// Overrides extracted from a single `# mypy:` comment that affect parsing. #[derive(Debug, Default, PartialEq)] pub(crate) struct InlineConfigOverrides { pub always_true: Vec, pub always_false: Vec, pub ignore_errors: Option, } impl InlineConfigOverrides { /// Merge another set of overrides into this one (later comments win for /// `ignore_errors`; list values are extended). pub(crate) fn merge(&mut self, other: InlineConfigOverrides) { self.always_true.extend(other.always_true); self.always_false.extend(other.always_false); if other.ignore_errors.is_some() { self.ignore_errors = other.ignore_errors; } } } /// Process all `# mypy:` comments and return combined overrides. pub(crate) fn resolve_overrides(comments: &[(usize, String)]) -> InlineConfigOverrides { let mut result = InlineConfigOverrides::default(); for (_, text) in comments { result.merge(parse_single_mypy_comment(text)); } result } /// Parse a single `# mypy:` comment text (the part after `# mypy:`) and extract /// overrides for options that affect parsing. /// /// The format follows mypy's `split_directive` + `mypy_comments_to_config_map`: /// - Comma-separated entries /// - Each entry is `key=value` or bare `key` (bare key means `True`) /// - Quoted values preserve commas: `always-true="FOO, BAR"` /// - Dashes in keys are normalized to underscores /// /// Only `always_true`, `always_false`, and `ignore_errors` are extracted; /// all other options are silently ignored. pub(crate) fn parse_single_mypy_comment(text: &str) -> InlineConfigOverrides { let mut result = InlineConfigOverrides::default(); for (key, value) in split_directive(text) { let normalized = key.replace('-', "_"); match normalized.as_str() { "always_true" => { for name in split_commas(&value) { if !name.is_empty() { result.always_true.push(name); } } } "always_false" => { for name in split_commas(&value) { if !name.is_empty() { result.always_false.push(name); } } } "ignore_errors" => { if let Some(b) = parse_bool(&value) { result.ignore_errors = Some(b); } } _ => {} } } result } /// Split a directive string on commas, respecting double-quoted sections. /// Returns `(key, value)` pairs where bare keys get value `"True"`. fn split_directive(s: &str) -> Vec<(String, String)> { let parts = split_respecting_quotes(s); parts .into_iter() .filter_map(|part| { let trimmed = part.trim(); if trimmed.is_empty() { return None; } if let Some((key, value)) = trimmed.split_once('=') { Some((key.trim().to_string(), value.trim().to_string())) } else { Some((trimmed.to_string(), "True".to_string())) } }) .collect() } /// Split `s` on commas, but preserve commas inside double quotes. fn split_respecting_quotes(s: &str) -> Vec { let mut parts = Vec::new(); let mut current = String::new(); let mut chars = s.chars(); while let Some(c) = chars.next() { match c { ',' => { parts.push(current); current = String::new(); } '"' => { // Consume until closing quote for c2 in chars.by_ref() { if c2 == '"' { break; } current.push(c2); } } _ => current.push(c), } } parts.push(current); parts } /// Split a value string on commas (for list-type options like `always_true`). fn split_commas(s: &str) -> Vec { s.split(',').map(|part| part.trim().to_string()).collect() } /// Parse a boolean value the way configparser does. /// Returns None for values not recognized by configparser. fn parse_bool(s: &str) -> Option { match s.to_lowercase().as_str() { "1" | "yes" | "true" | "on" => Some(true), "0" | "no" | "false" | "off" => Some(false), _ => None, } } #[cfg(test)] mod tests { use super::*; #[test] fn test_empty_comment() { let result = parse_single_mypy_comment(""); assert_eq!(result, InlineConfigOverrides::default()); } #[test] fn test_irrelevant_options() { let result = parse_single_mypy_comment("disallow-untyped-defs, warn-return-any"); assert_eq!(result, InlineConfigOverrides::default()); } #[test] fn test_always_true_single() { let result = parse_single_mypy_comment("always-true=MYPY"); assert_eq!(result.always_true, vec!["MYPY"]); assert!(result.always_false.is_empty()); assert_eq!(result.ignore_errors, None); } #[test] fn test_always_false_single() { let result = parse_single_mypy_comment("always-false=SLOW_PATH"); assert!(result.always_true.is_empty()); assert_eq!(result.always_false, vec!["SLOW_PATH"]); } #[test] fn test_always_true_multiple_quoted() { let result = parse_single_mypy_comment("always-true=\"FOO, BAR\""); assert_eq!(result.always_true, vec!["FOO", "BAR"]); } #[test] fn test_always_true_and_false() { let result = parse_single_mypy_comment("always-true=FAST, always-false=SLOW"); assert_eq!(result.always_true, vec!["FAST"]); assert_eq!(result.always_false, vec!["SLOW"]); } #[test] fn test_ignore_errors_bare() { let result = parse_single_mypy_comment("ignore-errors"); assert_eq!(result.ignore_errors, Some(true)); } #[test] fn test_ignore_errors_explicit_true() { let result = parse_single_mypy_comment("ignore-errors=True"); assert_eq!(result.ignore_errors, Some(true)); } #[test] fn test_ignore_errors_explicit_false() { let result = parse_single_mypy_comment("ignore-errors=False"); assert_eq!(result.ignore_errors, Some(false)); } #[test] fn test_underscore_variant() { let result = parse_single_mypy_comment("always_true=FOO"); assert_eq!(result.always_true, vec!["FOO"]); } #[test] fn test_mixed_relevant_and_irrelevant() { let result = parse_single_mypy_comment("disallow-untyped-defs, always-true=FLAG, warn-return-any"); assert_eq!(result.always_true, vec!["FLAG"]); assert!(result.always_false.is_empty()); assert_eq!(result.ignore_errors, None); } #[test] fn test_extra_whitespace() { let result = parse_single_mypy_comment(" always-true = FOO , always-false = BAR "); assert_eq!(result.always_true, vec!["FOO"]); assert_eq!(result.always_false, vec!["BAR"]); } #[test] fn test_merge_overrides() { let mut first = parse_single_mypy_comment("always-true=A"); let second = parse_single_mypy_comment("always-true=B, ignore-errors"); first.merge(second); assert_eq!(first.always_true, vec!["A", "B"]); assert_eq!(first.ignore_errors, Some(true)); } #[test] fn test_merge_ignore_errors_last_wins() { let mut first = parse_single_mypy_comment("ignore-errors=True"); let second = parse_single_mypy_comment("ignore-errors=False"); first.merge(second); assert_eq!(first.ignore_errors, Some(false)); } #[test] fn test_bool_parsing_variants() { assert_eq!( parse_single_mypy_comment("ignore-errors=yes").ignore_errors, Some(true) ); assert_eq!( parse_single_mypy_comment("ignore-errors=1").ignore_errors, Some(true) ); assert_eq!( parse_single_mypy_comment("ignore-errors=on").ignore_errors, Some(true) ); assert_eq!( parse_single_mypy_comment("ignore-errors=no").ignore_errors, Some(false) ); assert_eq!( parse_single_mypy_comment("ignore-errors=0").ignore_errors, Some(false) ); assert_eq!( parse_single_mypy_comment("ignore-errors=off").ignore_errors, Some(false) ); assert_eq!( parse_single_mypy_comment("ignore-errors=false").ignore_errors, Some(false) ); // Unrecognized values are ignored (None), matching configparser // which would raise ValueError — Python side handles the error. assert_eq!( parse_single_mypy_comment("ignore-errors=maybe").ignore_errors, None ); } #[test] fn test_quoted_value_with_spaces() { let result = parse_single_mypy_comment("always-true=\"FOO , BAR , BAZ\""); assert_eq!(result.always_true, vec!["FOO", "BAR", "BAZ"]); } #[test] fn test_split_respecting_quotes_basic() { let parts = split_respecting_quotes("a, b, c"); assert_eq!(parts, vec!["a", " b", " c"]); } #[test] fn test_split_respecting_quotes_with_quotes() { let parts = split_respecting_quotes("x=\"a, b\", y"); assert_eq!(parts, vec!["x=a, b", " y"]); } } ast_serialize-0.13.1/src/options.rs000064400000000000000000000044661046102023000142060ustar00#[derive(Debug, Clone)] pub(crate) struct Options { python_version: (u32, u32), platform: String, always_true: Vec, always_false: Vec, cache_version: u32, } impl Default for Options { fn default() -> Self { Self { python_version: (3, 12), platform: String::from("linux"), always_true: Vec::new(), always_false: Vec::new(), // Always set to latest supported version. cache_version: 7, } } } // Add location range to except handlers, available in v0.1.2. pub(crate) const CV_HANDLER_LOCATIONS: u32 = 1; // Add error notes to RawExpressionTypes, available in v0.2.0. pub(crate) const CV_RAW_EXPRESSION_TYPE_NOTES: u32 = 2; // Write import flags in full serialized tree as well, available in v0.3.0. pub(crate) const CV_IMPORT_FLAGS: u32 = 3; // Handle optional keys in dictionary comprehensions (PEP 798). pub(crate) const CV_DICT_KEY_OPT: u32 = 4; // Set string unicode surrogate flag. pub(crate) const CV_UNICODE_SURROGATE: u32 = 5; // Add flag specifying if type comment(s) were used for a function. pub(crate) const CV_FUNC_TYPE_COMMENT_FLAG: u32 = 6; // Extract all type comments and ignores, not just ones before the first unrecognized part. pub(crate) const CV_FULL_TYPE_COMMENTS: u32 = 7; impl Options { pub(crate) fn new( python_version: (u32, u32), platform: String, always_true: Vec, always_false: Vec, cache_version: u32, ) -> Self { Self { python_version, platform, always_true, always_false, cache_version, } } pub(crate) fn python_version(&self) -> (u32, u32) { self.python_version } pub(crate) fn platform(&self) -> &str { &self.platform } pub(crate) fn always_true(&self) -> &[String] { &self.always_true } pub(crate) fn always_false(&self) -> &[String] { &self.always_false } pub(crate) fn cache_version(&self) -> u32 { self.cache_version } pub(crate) fn extend_always_true(&mut self, names: Vec) { self.always_true.extend(names); } pub(crate) fn extend_always_false(&mut self, names: Vec) { self.always_false.extend(names); } } ast_serialize-0.13.1/src/reachability.rs000064400000000000000000001241421046102023000151450ustar00use crate::options::Options; use ruff_python_ast as ast; /// Inferred truth value of an expression during reachability analysis. /// /// These values match the constants in mypy.reachability: /// - ALWAYS_TRUE: Expression is always true /// - MYPY_TRUE: True in mypy, False at runtime /// - ALWAYS_FALSE: Expression is always false /// - MYPY_FALSE: False in mypy, True at runtime /// - TRUTH_VALUE_UNKNOWN: Truth value cannot be determined #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] pub enum TruthValue { AlwaysTrue = 1, MypyTrue = 2, AlwaysFalse = 3, MypyFalse = 4, TruthValueUnknown = 5, } /// Represents different forms of sys.version_info access. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SysVersionInfo { /// sys.version_info (whole tuple, same as sys.version_info[:]) Whole, /// sys.version_info[index] (single element access) Index(i32), /// sys.version_info[begin:end] (slice access) Slice(Option, Option), } /// Represents an integer or tuple of integers. #[derive(Debug, Clone, PartialEq, Eq)] pub enum IntOrTuple { /// Single integer value Int(i32), /// Tuple of integer values Tuple(Vec), } impl TruthValue { /// Returns the inverted truth value (for handling `not` expressions). pub fn invert(self) -> Self { match self { TruthValue::AlwaysTrue => TruthValue::AlwaysFalse, TruthValue::AlwaysFalse => TruthValue::AlwaysTrue, TruthValue::MypyTrue => TruthValue::MypyFalse, TruthValue::MypyFalse => TruthValue::MypyTrue, TruthValue::TruthValueUnknown => TruthValue::TruthValueUnknown, } } } /// Reverse a comparison operator (for swapping operands). fn reverse_cmp_op(op: ast::CmpOp) -> ast::CmpOp { match op { ast::CmpOp::Eq => ast::CmpOp::Eq, ast::CmpOp::NotEq => ast::CmpOp::NotEq, ast::CmpOp::Lt => ast::CmpOp::Gt, ast::CmpOp::LtE => ast::CmpOp::GtE, ast::CmpOp::Gt => ast::CmpOp::Lt, ast::CmpOp::GtE => ast::CmpOp::LtE, op => op, // Other operators unchanged } } /// Perform a fixed comparison between two values with a given operator. /// Returns AlwaysTrue if the comparison is true, AlwaysFalse if false. fn fixed_comparison(left: T, op: ast::CmpOp, right: T) -> TruthValue { let result = match op { ast::CmpOp::Eq => left == right, ast::CmpOp::NotEq => left != right, ast::CmpOp::Lt => left < right, ast::CmpOp::LtE => left <= right, ast::CmpOp::Gt => left > right, ast::CmpOp::GtE => left >= right, // Other operators don't apply in this context _ => return TruthValue::TruthValueUnknown, }; if result { TruthValue::AlwaysTrue } else { TruthValue::AlwaysFalse } } /// Extract an integer value from a NumberLiteral expression. fn expr_to_int(expr: &ast::Expr) -> Option { if let ast::Expr::NumberLiteral(num) = expr { if let ast::Number::Int(int_val) = &num.value { return int_val.as_i32(); } } None } /// Check if an expression is an integer or tuple of integers. fn contains_int_or_tuple_of_ints(expr: &ast::Expr) -> Option { // Check for single integer if let Some(int_val) = expr_to_int(expr) { return Some(IntOrTuple::Int(int_val)); } // Check for tuple of integers if let ast::Expr::Tuple(tuple) = expr { let mut values = Vec::with_capacity(tuple.elts.len()); for item in &tuple.elts { let int_val = expr_to_int(item)?; values.push(int_val); } return Some(IntOrTuple::Tuple(values)); } None } /// Check whether a tuple, list, or set of string literals contains a string. fn string_literal_container_contains(expr: &ast::Expr, value: &str) -> Option { let items = match expr { ast::Expr::Tuple(tuple) => &tuple.elts, ast::Expr::List(list) => &list.elts, ast::Expr::Set(set) => &set.elts, _ => return None, }; let mut contains = false; for item in items { let ast::Expr::StringLiteral(string_lit) = item else { return None; }; contains |= string_lit.value.to_str() == value; } Some(contains) } /// Check if an expression is an attribute access on 'sys' with the given name. /// For example, `is_sys_attr(expr, "platform")` returns true for `sys.platform`. fn is_sys_attr(expr: &ast::Expr, name: &str) -> bool { if let ast::Expr::Attribute(attr) = expr { if attr.attr.as_str() == name { if let ast::Expr::Name(base_name) = &*attr.value { return base_name.id.as_str() == "sys"; } } } false } /// Check if an expression contains a sys.version_info access pattern. /// Returns the type of access (whole, index, or slice) if found. fn contains_sys_version_info(expr: &ast::Expr) -> Option { // Check for bare sys.version_info if is_sys_attr(expr, "version_info") { return Some(SysVersionInfo::Whole); } // Check for sys.version_info[...] subscript if let ast::Expr::Subscript(subscript) = expr { if !is_sys_attr(&subscript.value, "version_info") { return None; } match &*subscript.slice { // sys.version_info[index] - single integer index ast::Expr::NumberLiteral(_) => { let index = expr_to_int(&subscript.slice)?; return Some(SysVersionInfo::Index(index)); } // sys.version_info[begin:end] - slice ast::Expr::Slice(slice) => { // Check stride is None or 1 if let Some(stride) = &slice.step { if expr_to_int(stride)? != 1 { return None; } } // Extract begin and end values let begin = if let Some(lower) = &slice.lower { Some(expr_to_int(lower)?) } else { None }; let end = if let Some(upper) = &slice.upper { Some(expr_to_int(upper)?) } else { None }; return Some(SysVersionInfo::Slice(begin, end)); } _ => {} } } None } /// Check if a name corresponds to a special constant with known truth value. fn check_name_truth_value(name: &str, options: &Options) -> TruthValue { match name { "MYPY" | "TYPE_CHECKING" => TruthValue::MypyTrue, "PY2" => TruthValue::AlwaysFalse, "PY3" => TruthValue::AlwaysTrue, _ => { // Check user-provided always_true/always_false lists if options.always_true().iter().any(|s| s == name) { TruthValue::AlwaysTrue } else if options.always_false().iter().any(|s| s == name) { TruthValue::AlwaysFalse } else { TruthValue::TruthValueUnknown } } } } /// Combine truth values using a boolean operator (and/or). fn combine_bool_op(op: ast::BoolOp, values: &[TruthValue]) -> TruthValue { // Track what truth values we've seen (efficient single-pass) let mut has_always_true = false; let mut has_mypy_true = false; let mut has_always_false = false; let mut has_mypy_false = false; let mut has_unknown = false; for &val in values { match val { TruthValue::AlwaysTrue => has_always_true = true, TruthValue::MypyTrue => has_mypy_true = true, TruthValue::AlwaysFalse => has_always_false = true, TruthValue::MypyFalse => has_mypy_false = true, TruthValue::TruthValueUnknown => has_unknown = true, } } match op { ast::BoolOp::Or => { if has_always_true { TruthValue::AlwaysTrue } else if has_mypy_true { TruthValue::MypyTrue } else if !has_always_false && !has_unknown && has_mypy_false { // All values are MYPY_FALSE TruthValue::MypyFalse } else if !has_unknown && !has_always_true && !has_mypy_true { // All values are ALWAYS_FALSE or MYPY_FALSE TruthValue::AlwaysFalse } else { TruthValue::TruthValueUnknown } } ast::BoolOp::And => { if has_always_false { TruthValue::AlwaysFalse } else if has_mypy_false { TruthValue::MypyFalse } else if !has_mypy_true && !has_unknown && has_always_true { // All values are ALWAYS_TRUE TruthValue::AlwaysTrue } else if !has_unknown && !has_always_false && !has_mypy_false { // All values are ALWAYS_TRUE or MYPY_TRUE TruthValue::MypyTrue } else { TruthValue::TruthValueUnknown } } } } /// Consider whether expr is a comparison involving sys.version_info. pub(crate) fn consider_sys_version_info(expr: &ast::Expr, options: &Options) -> TruthValue { let python_version = options.python_version(); let ast::Expr::Compare(compare) = expr else { return TruthValue::TruthValueUnknown; }; // Don't support chained comparisons if compare.ops.len() > 1 { return TruthValue::TruthValueUnknown; } let mut op = compare.ops[0]; // Only support standard comparison operators if !matches!( op, ast::CmpOp::Eq | ast::CmpOp::NotEq | ast::CmpOp::Lt | ast::CmpOp::LtE | ast::CmpOp::Gt | ast::CmpOp::GtE ) { return TruthValue::TruthValueUnknown; } // Try to extract sys.version_info pattern from left and int/tuple from right let mut index = contains_sys_version_info(&compare.left); let mut thing = contains_int_or_tuple_of_ints(&compare.comparators[0]); // If that didn't work, try the reverse if index.is_none() || thing.is_none() { index = contains_sys_version_info(&compare.comparators[0]); thing = contains_int_or_tuple_of_ints(&compare.left); op = reverse_cmp_op(op); } let Some(index) = index else { return TruthValue::TruthValueUnknown; }; let Some(thing) = thing else { return TruthValue::TruthValueUnknown; }; match (index, thing) { // Handle sys.version_info[i] k (SysVersionInfo::Index(idx), IntOrTuple::Int(value)) => { if idx >= 0 && idx <= 1 { let version_component = if idx == 0 { python_version.0 as i32 } else { python_version.1 as i32 }; return fixed_comparison(version_component, op, value); } else { return TruthValue::TruthValueUnknown; } } // Handle sys.version_info[lo:hi] tuple or sys.version_info tuple (index, IntOrTuple::Tuple(target_tuple)) => { let (lo, hi) = match index { SysVersionInfo::Slice(begin, end) => { let lo = begin.unwrap_or(0); let hi = end.unwrap_or(2); (lo, hi) } SysVersionInfo::Whole => (0, 2), // sys.version_info is same as [0:2] _ => return TruthValue::TruthValueUnknown, }; // Validate bounds: 0 <= lo < hi <= 2 if lo < 0 || hi > 2 || lo >= hi { return TruthValue::TruthValueUnknown; } // Extract version slice let version_slice: Vec = match (lo, hi) { (0, 1) => vec![python_version.0 as i32], (0, 2) => vec![python_version.0 as i32, python_version.1 as i32], (1, 2) => vec![python_version.1 as i32], _ => return TruthValue::TruthValueUnknown, }; // Check length compatibility let version_len = version_slice.len(); let target_len = target_tuple.len(); // Allow comparison if lengths match, or if version is longer and op is not == or != if version_len == target_len || (version_len > target_len && !matches!(op, ast::CmpOp::Eq | ast::CmpOp::NotEq)) { // Compare tuples lexicographically return fixed_comparison(version_slice.as_slice(), op, target_tuple.as_slice()); } TruthValue::TruthValueUnknown } // Other combinations not supported _ => TruthValue::TruthValueUnknown, } } /// Consider whether expr is a comparison involving sys.platform. pub(crate) fn consider_sys_platform(expr: &ast::Expr, options: &Options) -> TruthValue { let platform = options.platform(); match expr { ast::Expr::Compare(compare) => { // Don't support chained comparisons if compare.ops.len() > 1 { return TruthValue::TruthValueUnknown; } let op = compare.ops[0]; // Check if left operand is sys.platform if !is_sys_attr(&compare.left, "platform") { return TruthValue::TruthValueUnknown; } let right = &compare.comparators[0]; if matches!(op, ast::CmpOp::Eq | ast::CmpOp::NotEq) { if let ast::Expr::StringLiteral(string_lit) = right { return fixed_comparison(platform, op, string_lit.value.to_str()); } } else if matches!(op, ast::CmpOp::In | ast::CmpOp::NotIn) { if let Some(mut result) = string_literal_container_contains(right, platform) { if op == ast::CmpOp::NotIn { result = !result; } return if result { TruthValue::AlwaysTrue } else { TruthValue::AlwaysFalse }; } } TruthValue::TruthValueUnknown } ast::Expr::Call(call) => { // Check if callee is an attribute expression let ast::Expr::Attribute(attr) = &*call.func else { return TruthValue::TruthValueUnknown; }; // Check that there's exactly one argument if call.arguments.args.len() != 1 { return TruthValue::TruthValueUnknown; } // Check if the attribute base is sys.platform if !is_sys_attr(&attr.value, "platform") { return TruthValue::TruthValueUnknown; } // Check if the method is "startswith" if attr.attr.as_str() != "startswith" { return TruthValue::TruthValueUnknown; } // Check if the argument is a string literal if let ast::Expr::StringLiteral(string_lit) = &call.arguments.args[0] { if platform.starts_with(string_lit.value.to_str()) { return TruthValue::AlwaysTrue; } else { return TruthValue::AlwaysFalse; } } TruthValue::TruthValueUnknown } _ => TruthValue::TruthValueUnknown, } } /// Infer whether a given statement is an assert that will always fail. pub(crate) fn assert_will_always_fail(stmt: &ast::Stmt, options: &Options) -> bool { if let ast::Stmt::Assert(a) = stmt { let truth_value = infer_condition_value(a.test.as_ref(), options); return truth_value == TruthValue::AlwaysFalse || truth_value == TruthValue::MypyFalse; } false } /// Infer whether the given condition is always true/false. pub(crate) fn infer_condition_value(expr: &ast::Expr, options: &Options) -> TruthValue { match expr { // Handle unary "not" expressions ast::Expr::UnaryOp(unary) if matches!(unary.op, ast::UnaryOp::Not) => { let positive = infer_condition_value(&unary.operand, options); positive.invert() } // Handle boolean literals (True/False) // Only treat as always true/false if explicitly listed in --always-true/--always-false, // since ruff parses True/False as BooleanLiteral rather than Name. ast::Expr::BooleanLiteral(lit) => { if lit.value { if options.always_true().iter().any(|s| s == "True") { TruthValue::AlwaysTrue } else { TruthValue::TruthValueUnknown } } else { if options.always_false().iter().any(|s| s == "False") { TruthValue::AlwaysFalse } else { TruthValue::TruthValueUnknown } } } // Handle name expressions (e.g., PY3, MYPY, TYPE_CHECKING) ast::Expr::Name(name) => check_name_truth_value(name.id.as_str(), options), // Handle attribute expressions (e.g., typing.TYPE_CHECKING, sys.platform) ast::Expr::Attribute(attr) => check_name_truth_value(attr.attr.as_str(), options), // Handle boolean operations (and/or) ast::Expr::BoolOp(bool_op) => { // Infer truth values for all operands let mut inferred_values = Vec::with_capacity(bool_op.values.len()); for value in &bool_op.values { inferred_values.push(infer_condition_value(value, options)); } combine_bool_op(bool_op.op, &inferred_values) } // Fallback: try sys.version_info and sys.platform checks _ => { let result = consider_sys_version_info(expr, options); if result != TruthValue::TruthValueUnknown { return result; } consider_sys_platform(expr, options) } } } pub(crate) fn infer_pattern_value(pattern: &ast::Pattern) -> TruthValue { match pattern { ast::Pattern::MatchAs(pattern) if pattern.pattern.is_none() => TruthValue::AlwaysTrue, ast::Pattern::MatchOr(pattern) if pattern .patterns .iter() .any(|p| infer_pattern_value(p) == TruthValue::AlwaysTrue) => { TruthValue::AlwaysTrue } _ => TruthValue::TruthValueUnknown, } } #[cfg(test)] mod tests { use super::*; #[test] fn test_enum_values() { // Verify the enum values match the Python constants assert_eq!(TruthValue::AlwaysTrue as u8, 1); assert_eq!(TruthValue::MypyTrue as u8, 2); assert_eq!(TruthValue::AlwaysFalse as u8, 3); assert_eq!(TruthValue::MypyFalse as u8, 4); assert_eq!(TruthValue::TruthValueUnknown as u8, 5); } #[test] fn test_invert() { assert_eq!(TruthValue::AlwaysTrue.invert(), TruthValue::AlwaysFalse); assert_eq!(TruthValue::AlwaysFalse.invert(), TruthValue::AlwaysTrue); assert_eq!(TruthValue::MypyTrue.invert(), TruthValue::MypyFalse); assert_eq!(TruthValue::MypyFalse.invert(), TruthValue::MypyTrue); assert_eq!( TruthValue::TruthValueUnknown.invert(), TruthValue::TruthValueUnknown ); } /// Helper to parse an expression and infer its truth value fn infer_expr(expr_str: &str) -> TruthValue { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parsed = parse_unchecked(expr_str, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; let options = Options::new((3, 10), String::from("linux"), Vec::new(), Vec::new(), 0); infer_condition_value(&expr_mod.body, &options) } #[test] fn test_infer_condition_value_placeholder() { assert_eq!(infer_expr("foo"), TruthValue::TruthValueUnknown); } #[test] fn test_always_true_always_false() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parse_and_infer = |code: &str, always_true: &[String], always_false: &[String]| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; let options = Options::new( (3, 10), String::from("linux"), always_true.to_vec(), always_false.to_vec(), 0, ); infer_condition_value(&expr_mod.body, &options) }; // Name in always_true list assert_eq!( parse_and_infer("DEBUG", &[String::from("DEBUG")], &[]), TruthValue::AlwaysTrue ); // Name in always_false list assert_eq!( parse_and_infer("PRODUCTION", &[], &[String::from("PRODUCTION")]), TruthValue::AlwaysFalse ); // Name not in either list assert_eq!( parse_and_infer( "UNKNOWN", &[String::from("DEBUG")], &[String::from("PRODUCTION")] ), TruthValue::TruthValueUnknown ); // Built-in names take precedence over always_true/always_false assert_eq!( parse_and_infer("PY3", &[], &[String::from("PY3")]), TruthValue::AlwaysTrue ); // Attribute expressions also check the lists assert_eq!( parse_and_infer("foo.DEBUG", &[String::from("DEBUG")], &[]), TruthValue::AlwaysTrue ); } #[test] fn test_true_false_boolean_literals_with_options() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parse_and_infer = |code: &str, always_true: &[String], always_false: &[String]| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; let options = Options::new( (3, 10), String::from("linux"), always_true.to_vec(), always_false.to_vec(), 0, ); infer_condition_value(&expr_mod.body, &options) }; assert_eq!( parse_and_infer("True", &[String::from("True")], &[]), TruthValue::AlwaysTrue ); assert_eq!( parse_and_infer("False", &[], &[String::from("False")]), TruthValue::AlwaysFalse ); } #[test] fn test_mypy_and_type_checking() { assert_eq!(infer_expr("MYPY"), TruthValue::MypyTrue); assert_eq!(infer_expr("TYPE_CHECKING"), TruthValue::MypyTrue); } #[test] fn test_py2_and_py3() { assert_eq!(infer_expr("PY2"), TruthValue::AlwaysFalse); assert_eq!(infer_expr("PY3"), TruthValue::AlwaysTrue); } #[test] fn test_unary_not() { assert_eq!(infer_expr("not MYPY"), TruthValue::MypyFalse); assert_eq!(infer_expr("not TYPE_CHECKING"), TruthValue::MypyFalse); assert_eq!(infer_expr("not PY2"), TruthValue::AlwaysTrue); assert_eq!(infer_expr("not PY3"), TruthValue::AlwaysFalse); assert_eq!(infer_expr("not foo"), TruthValue::TruthValueUnknown); } #[test] fn test_attribute_expressions() { assert_eq!(infer_expr("typing.TYPE_CHECKING"), TruthValue::MypyTrue); assert_eq!(infer_expr("foo.MYPY"), TruthValue::MypyTrue); assert_eq!(infer_expr("bar.PY2"), TruthValue::AlwaysFalse); assert_eq!(infer_expr("baz.PY3"), TruthValue::AlwaysTrue); assert_eq!(infer_expr("sys.platform"), TruthValue::TruthValueUnknown); } #[test] fn test_or_operation() { // ALWAYS_TRUE wins assert_eq!(infer_expr("PY3 or foo"), TruthValue::AlwaysTrue); assert_eq!(infer_expr("foo or PY3"), TruthValue::AlwaysTrue); // MYPY_TRUE wins if no ALWAYS_TRUE assert_eq!(infer_expr("MYPY or PY2"), TruthValue::MypyTrue); assert_eq!(infer_expr("PY2 or MYPY"), TruthValue::MypyTrue); // All MYPY_FALSE -> MYPY_FALSE assert_eq!( infer_expr("(not MYPY) or (not TYPE_CHECKING)"), TruthValue::MypyFalse ); // All ALWAYS_FALSE or MYPY_FALSE -> ALWAYS_FALSE assert_eq!(infer_expr("PY2 or (not MYPY)"), TruthValue::AlwaysFalse); // Mixed with unknown -> unknown assert_eq!(infer_expr("foo or bar"), TruthValue::TruthValueUnknown); } #[test] fn test_and_operation() { // ALWAYS_FALSE wins assert_eq!(infer_expr("PY2 and foo"), TruthValue::AlwaysFalse); assert_eq!(infer_expr("foo and PY2"), TruthValue::AlwaysFalse); // MYPY_FALSE wins if no ALWAYS_FALSE assert_eq!(infer_expr("(not MYPY) and PY3"), TruthValue::MypyFalse); assert_eq!(infer_expr("PY3 and (not MYPY)"), TruthValue::MypyFalse); // All ALWAYS_TRUE -> ALWAYS_TRUE assert_eq!(infer_expr("PY3 and PY3"), TruthValue::AlwaysTrue); // All ALWAYS_TRUE or MYPY_TRUE -> MYPY_TRUE assert_eq!(infer_expr("PY3 and MYPY"), TruthValue::MypyTrue); assert_eq!(infer_expr("MYPY and TYPE_CHECKING"), TruthValue::MypyTrue); // Mixed with unknown -> unknown assert_eq!(infer_expr("foo and bar"), TruthValue::TruthValueUnknown); } #[test] fn test_is_sys_attr() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parse_expr = |code: &str| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; expr_mod.body }; // Positive cases: sys.platform and sys.version_info assert!(is_sys_attr(&parse_expr("sys.platform"), "platform")); assert!(is_sys_attr(&parse_expr("sys.version_info"), "version_info")); // Wrong attribute name assert!(!is_sys_attr(&parse_expr("sys.platform"), "version_info")); assert!(!is_sys_attr(&parse_expr("sys.version_info"), "platform")); // Not sys module assert!(!is_sys_attr(&parse_expr("foo.platform"), "platform")); assert!(!is_sys_attr(&parse_expr("os.platform"), "platform")); // Not an attribute expression assert!(!is_sys_attr(&parse_expr("platform"), "platform")); assert!(!is_sys_attr(&parse_expr("sys"), "sys")); } #[test] fn test_consider_sys_version_info() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let options = Options::new((3, 10), String::from("linux"), Vec::new(), Vec::new(), 0); let parse_expr = |code: &str| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; expr_mod.body }; // Edge case: exact equality assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[0] == 3"), &options), TruthValue::AlwaysTrue ); // Edge case: one off from target assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[0] == 2"), &options), TruthValue::AlwaysFalse ); // Edge case: >= with exact boundary assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[1] >= 10"), &options), TruthValue::AlwaysTrue ); // Edge case: < with exact boundary (should be false) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[0] < 3"), &options), TruthValue::AlwaysFalse ); // Edge case: reversed operands with exact equality assert_eq!( consider_sys_version_info(&parse_expr("3 == sys.version_info[0]"), &options), TruthValue::AlwaysTrue ); // Edge case: reversed > with one above boundary assert_eq!( consider_sys_version_info(&parse_expr("11 > sys.version_info[1]"), &options), TruthValue::AlwaysTrue ); // Out of range index (only 0 and 1 supported) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[2] == 5"), &options), TruthValue::TruthValueUnknown ); // Not a comparison assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[0]"), &options), TruthValue::TruthValueUnknown ); // Chained comparison assert_eq!( consider_sys_version_info(&parse_expr("2 < sys.version_info[0] < 4"), &options), TruthValue::TruthValueUnknown ); // Tuple comparisons: sys.version_info >= (3, 8) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info >= (3, 8)"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: sys.version_info >= (3, 10) - exact boundary assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info >= (3, 10)"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: sys.version_info < (3, 10) - exact boundary assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info < (3, 10)"), &options), TruthValue::AlwaysFalse ); // Tuple comparisons: sys.version_info[:2] >= (3, 8) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[:2] >= (3, 8)"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: sys.version_info[0:2] >= (3, 10) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[0:2] >= (3, 10)"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: reversed operands assert_eq!( consider_sys_version_info(&parse_expr("(3, 8) <= sys.version_info"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: single element tuple with slice assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info[:1] >= (3,)"), &options), TruthValue::AlwaysTrue ); // Tuple comparisons: version longer than target (allowed for ordering) assert_eq!( consider_sys_version_info(&parse_expr("sys.version_info >= (3,)"), &options), TruthValue::AlwaysTrue ); } #[test] fn test_contains_int_or_tuple_of_ints() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parse_expr = |code: &str| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; expr_mod.body }; // Single integer assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("42")), Some(IntOrTuple::Int(42)) ); assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("0")), Some(IntOrTuple::Int(0)) ); // Tuple of integers assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("(3, 10)")), Some(IntOrTuple::Tuple(vec![3, 10])) ); assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("(3, 8, 2)")), Some(IntOrTuple::Tuple(vec![3, 8, 2])) ); // Empty tuple assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("()")), Some(IntOrTuple::Tuple(vec![])) ); // Single element tuple assert_eq!( contains_int_or_tuple_of_ints(&parse_expr("(5,)")), Some(IntOrTuple::Tuple(vec![5])) ); // Not an integer or tuple of integers assert_eq!(contains_int_or_tuple_of_ints(&parse_expr("'hello'")), None); assert_eq!(contains_int_or_tuple_of_ints(&parse_expr("3.14")), None); assert_eq!(contains_int_or_tuple_of_ints(&parse_expr("(1, 'a')")), None); assert_eq!(contains_int_or_tuple_of_ints(&parse_expr("(1, 2.5)")), None); } #[test] fn test_contains_sys_version_info() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let parse_expr = |code: &str| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; expr_mod.body }; // Bare sys.version_info assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info")), Some(SysVersionInfo::Whole) ); // Single index access assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[0]")), Some(SysVersionInfo::Index(0)) ); assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[1]")), Some(SysVersionInfo::Index(1)) ); // Slice with both bounds assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[0:2]")), Some(SysVersionInfo::Slice(Some(0), Some(2))) ); // Slice with only lower bound assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[1:]")), Some(SysVersionInfo::Slice(Some(1), None)) ); // Slice with only upper bound assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[:2]")), Some(SysVersionInfo::Slice(None, Some(2))) ); // Slice with no bounds (equivalent to [:]) assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[:]")), Some(SysVersionInfo::Slice(None, None)) ); // Slice with stride 1 (allowed) assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[0:2:1]")), Some(SysVersionInfo::Slice(Some(0), Some(2))) ); // Slice with stride != 1 (not allowed) assert_eq!( contains_sys_version_info(&parse_expr("sys.version_info[0:2:2]")), None ); // Not sys.version_info assert_eq!( contains_sys_version_info(&parse_expr("foo.version_info[0]")), None ); assert_eq!( contains_sys_version_info(&parse_expr("sys.platform[0]")), None ); // Not a subscript or attribute assert_eq!(contains_sys_version_info(&parse_expr("version_info")), None); } #[test] fn test_consider_sys_platform() { use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; let linux_options = Options::new((3, 10), String::from("linux"), Vec::new(), Vec::new(), 0); let win32_options = Options::new((3, 10), String::from("win32"), Vec::new(), Vec::new(), 0); let parse_expr = |code: &str| { let parsed = parse_unchecked(code, ParseOptions::from(Mode::Expression)); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("Expected expression"); }; expr_mod.body }; // sys.platform == "linux" on linux platform assert_eq!( consider_sys_platform(&parse_expr("sys.platform == 'linux'"), &linux_options), TruthValue::AlwaysTrue ); // sys.platform == "win32" on linux platform assert_eq!( consider_sys_platform(&parse_expr("sys.platform == 'win32'"), &linux_options), TruthValue::AlwaysFalse ); // sys.platform != "win32" on linux platform assert_eq!( consider_sys_platform(&parse_expr("sys.platform != 'win32'"), &linux_options), TruthValue::AlwaysTrue ); // sys.platform != "linux" on linux platform assert_eq!( consider_sys_platform(&parse_expr("sys.platform != 'linux'"), &linux_options), TruthValue::AlwaysFalse ); // Membership in tuple, list, and set literals for container in [ "('linux', 'darwin')", "['linux', 'darwin']", "{'linux', 'darwin'}", ] { assert_eq!( consider_sys_platform( &parse_expr(&format!("sys.platform in {container}")), &linux_options ), TruthValue::AlwaysTrue ); assert_eq!( consider_sys_platform( &parse_expr(&format!("sys.platform not in {container}")), &linux_options ), TruthValue::AlwaysFalse ); } // Membership when the configured platform is absent assert_eq!( consider_sys_platform( &parse_expr("sys.platform in ('win32', 'cygwin')"), &linux_options ), TruthValue::AlwaysFalse ); assert_eq!( consider_sys_platform( &parse_expr("sys.platform not in ('win32', 'cygwin')"), &linux_options ), TruthValue::AlwaysTrue ); // Empty tuple and list literals assert_eq!( consider_sys_platform(&parse_expr("sys.platform in ()"), &linux_options), TruthValue::AlwaysFalse ); assert_eq!( consider_sys_platform(&parse_expr("sys.platform not in []"), &linux_options), TruthValue::AlwaysTrue ); // Unsupported membership containers for expression in [ "sys.platform in ('linux', platform)", "sys.platform in {'linux': 1}", "sys.platform in platforms", "sys.platform in 'linux'", "'linux' in sys.platform", ] { assert_eq!( consider_sys_platform(&parse_expr(expression), &linux_options), TruthValue::TruthValueUnknown ); } // Unsupported: other comparison operators assert_eq!( consider_sys_platform(&parse_expr("sys.platform < 'linux'"), &linux_options), TruthValue::TruthValueUnknown ); // Unsupported: not sys.platform assert_eq!( consider_sys_platform(&parse_expr("foo.platform == 'linux'"), &linux_options), TruthValue::TruthValueUnknown ); // Unsupported: chained comparisons assert_eq!( consider_sys_platform(&parse_expr("'a' < sys.platform < 'z'"), &linux_options), TruthValue::TruthValueUnknown ); // startswith: platform starts with prefix assert_eq!( consider_sys_platform( &parse_expr("sys.platform.startswith('lin')"), &linux_options ), TruthValue::AlwaysTrue ); // startswith: platform doesn't start with prefix assert_eq!( consider_sys_platform( &parse_expr("sys.platform.startswith('win')"), &linux_options ), TruthValue::AlwaysFalse ); // startswith: exact match assert_eq!( consider_sys_platform( &parse_expr("sys.platform.startswith('linux')"), &linux_options ), TruthValue::AlwaysTrue ); // startswith on win32 platform assert_eq!( consider_sys_platform( &parse_expr("sys.platform.startswith('win')"), &win32_options ), TruthValue::AlwaysTrue ); } #[test] fn test_fixed_comparison() { // Equality with strings assert_eq!( fixed_comparison("linux", ast::CmpOp::Eq, "linux"), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison("linux", ast::CmpOp::Eq, "win32"), TruthValue::AlwaysFalse ); // Inequality with strings assert_eq!( fixed_comparison("linux", ast::CmpOp::NotEq, "win32"), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison("linux", ast::CmpOp::NotEq, "linux"), TruthValue::AlwaysFalse ); // Less than with integers assert_eq!( fixed_comparison(3, ast::CmpOp::Lt, 10), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison(10, ast::CmpOp::Lt, 3), TruthValue::AlwaysFalse ); assert_eq!( fixed_comparison(5, ast::CmpOp::Lt, 5), TruthValue::AlwaysFalse ); // Less than or equal with integers assert_eq!( fixed_comparison(3, ast::CmpOp::LtE, 10), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison(5, ast::CmpOp::LtE, 5), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison(10, ast::CmpOp::LtE, 3), TruthValue::AlwaysFalse ); // Greater than with strings assert_eq!( fixed_comparison("b", ast::CmpOp::Gt, "a"), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison("a", ast::CmpOp::Gt, "b"), TruthValue::AlwaysFalse ); // Greater than or equal with integers assert_eq!( fixed_comparison(10, ast::CmpOp::GtE, 3), TruthValue::AlwaysTrue ); assert_eq!( fixed_comparison(5, ast::CmpOp::GtE, 5), TruthValue::AlwaysTrue ); // Unsupported operators return unknown assert_eq!( fixed_comparison("a", ast::CmpOp::In, "b"), TruthValue::TruthValueUnknown ); assert_eq!( fixed_comparison(1, ast::CmpOp::Is, 2), TruthValue::TruthValueUnknown ); } } ast_serialize-0.13.1/src/serialize_ast.rs000064400000000000000000005211601046102023000153440ustar00//! Serialize the AST for a given Python file as a mypy AST use std::collections::{HashMap, HashSet}; use std::fmt::Write; use std::path::Path; use anyhow::Result; use ruff_python_ast::token::{TokenKind, Tokens}; use ruff_python_ast::{self as ast, AnyParameterRef, Number, PySourceType, StmtFunctionDef}; use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; use ruff_source_file::LineIndex; use ruff_text_size::{Ranged, TextRange}; use sha1::{Digest, Sha1}; use thin_vec::ThinVec; use crate::func_effect_visitor; use crate::options::{ CV_DICT_KEY_OPT, CV_FULL_TYPE_COMMENTS, CV_FUNC_TYPE_COMMENT_FLAG, CV_HANDLER_LOCATIONS, CV_IMPORT_FLAGS, CV_RAW_EXPRESSION_TYPE_NOTES, CV_UNICODE_SURROGATE, Options, }; use crate::reachability::TruthValue::AlwaysTrue; use crate::reachability::{ TruthValue, assert_will_always_fail, infer_condition_value, infer_pattern_value, }; use crate::type_comment; use crate::type_comment::parse_func_type_comment; /// Syntax error information with location details #[derive(Debug, Clone)] pub(crate) struct SyntaxError { pub line: usize, pub column: usize, pub message: String, pub blocker: bool, } // Fixed tags for primitive types (must match mypy/cache.py) const TAG_LITERAL_FALSE: u8 = 0; const TAG_LITERAL_TRUE: u8 = 1; const TAG_LITERAL_NONE: u8 = 2; const TAG_LITERAL_INT: u8 = 3; const TAG_LITERAL_STR: u8 = 4; const TAG_LITERAL_FLOAT: u8 = 6; // Fixed tags for collections (must match mypy/cache.py) const TAG_LIST_GEN: u8 = 20; const TAG_LIST_INT: u8 = 21; const TAG_DICT_STR_GEN: u8 = 30; const TAG_DECORATOR: u8 = 53; const TAG_CLASS_DEF: u8 = 60; // End tag for composite objects const TAG_END: u8 = 255; const TAG_LOCATION: u8 = 152; const TAG_EXPR_STMT: u8 = 160; const TAG_CALL_EXPR: u8 = 161; const TAG_NAME_EXPR: u8 = 162; const TAG_STR_EXPR: u8 = 163; const TAG_IMPORT: u8 = 164; const TAG_MEMBER_EXPR: u8 = 165; const TAG_OP_EXPR: u8 = 166; const TAG_INT_EXPR: u8 = 167; const TAG_IF: u8 = 168; const TAG_ASSIGN: u8 = 169; const TAG_TUPLE_EXPR: u8 = 170; const TAG_BLOCK: u8 = 171; const TAG_INDEX: u8 = 172; const TAG_LIST_EXPR: u8 = 173; const TAG_SET_EXPR: u8 = 174; const TAG_RETURN: u8 = 175; const TAG_WHILE: u8 = 176; const TAG_COMPARISON_EXPR: u8 = 177; const TAG_BOOL_OP_EXPR: u8 = 178; const TAG_FUNC_DEF: u8 = 179; const TAG_PASS_STMT: u8 = 180; const TAG_FLOAT_EXPR: u8 = 181; const TAG_UNARY_EXPR: u8 = 182; const TAG_DICT_EXPR: u8 = 183; const TAG_COMPLEX_EXPR: u8 = 184; const TAG_SLICE_EXPR: u8 = 185; const TAG_TEMP_NODE: u8 = 186; const TAG_RAISE_STMT: u8 = 187; const TAG_BREAK_STMT: u8 = 188; const TAG_CONTINUE_STMT: u8 = 189; const TAG_GENERATOR_EXPR: u8 = 190; const TAG_YIELD_EXPR: u8 = 191; const TAG_YIELD_FROM_EXPR: u8 = 192; const TAG_LIST_COMPREHENSION: u8 = 193; const TAG_SET_COMPREHENSION: u8 = 194; const TAG_DICT_COMPREHENSION: u8 = 195; const TAG_IMPORT_FROM: u8 = 196; const TAG_ASSERT_STMT: u8 = 197; const TAG_FOR_STMT: u8 = 198; const TAG_WITH_STMT: u8 = 199; const TAG_OPERATOR_ASSIGNMENT_STMT: u8 = 200; const TAG_TRY_STMT: u8 = 201; const TAG_ELLIPSIS_EXPR: u8 = 202; const TAG_CONDITIONAL_EXPR: u8 = 203; const TAG_DEL_STMT: u8 = 204; const TAG_FSTRING_EXPR: u8 = 205; const TAG_FSTRING_INTERPOLATION: u8 = 206; const TAG_LAMBDA_EXPR: u8 = 207; const TAG_ASSIGNMENT_EXPR: u8 = 208; const TAG_STAR_EXPR: u8 = 209; const TAG_BYTES_EXPR: u8 = 210; const TAG_GLOBAL_DECL: u8 = 211; const TAG_NONLOCAL_DECL: u8 = 212; const TAG_AWAIT_EXPR: u8 = 213; const TAG_BIG_INT_EXPR: u8 = 214; const TAG_IMPORT_ALL: u8 = 215; const TAG_MATCH_STMT: u8 = 216; const TAG_AS_PATTERN: u8 = 217; const TAG_OR_PATTERN: u8 = 218; const TAG_VALUE_PATTERN: u8 = 219; const TAG_SINGLETON_PATTERN: u8 = 220; const TAG_SEQUENCE_PATTERN: u8 = 221; const TAG_STARRED_PATTERN: u8 = 222; const TAG_MAPPING_PATTERN: u8 = 223; const TAG_CLASS_PATTERN: u8 = 224; const TAG_TYPE_ALIAS_STMT: u8 = 225; const TAG_IMPORT_METADATA: u8 = 226; const TAG_IMPORTFROM_METADATA: u8 = 227; const TAG_IMPORTALL_METADATA: u8 = 228; const TAG_TSTRING_EXPR: u8 = 229; const TAG_UNBOUND_TYPE: u8 = 104; const TAG_TUPLE_TYPE: u8 = 112; const TAG_TYPED_DICT_TYPE: u8 = 113; const TAG_UNION_TYPE: u8 = 115; const TAG_LIST_TYPE: u8 = 118; const TAG_ELLIPSIS_TYPE: u8 = 119; const TAG_RAW_EXPRESSION_TYPE: u8 = 120; const TAG_CALL_TYPE: u8 = 121; const TAG_UNPACK_TYPE: u8 = 105; // Argument kinds (must match mypy/nodes.py) const ARG_POS: i64 = 0; // Positional argument const ARG_OPT: i64 = 1; // Positional argument with default const ARG_STAR: i64 = 2; // *args const ARG_NAMED: i64 = 3; // Keyword-only argument const ARG_STAR2: i64 = 4; // **kwargs const ARG_NAMED_OPT: i64 = 5; // Keyword-only argument with default // TypeParam kinds (must match mypy/nodes.py) const TYPE_VAR_KIND: i64 = 0; // TypeVar const PARAM_SPEC_KIND: i64 = 1; // ParamSpec const TYPE_VAR_TUPLE_KIND: i64 = 2; // TypeVarTuple const MIN_SHORT_INT: i64 = -10; const MIN_TWO_BYTES_INT: i64 = -100; const MAX_TWO_BYTES_INT: i64 = 16283; // 2 ** (8 + 6) - 1 - 100 const MIN_FOUR_BYTES_INT: i64 = -10000; const MAX_FOUR_BYTES_INT: i64 = 536860911; // 2 ** (3 * 8 + 5) - 1 - 10000 const TWO_BYTES_INT_BIT: i64 = 1; const FOUR_BYTES_INT_TRAILER: i64 = 3; const LONG_INT_TRAILER: u8 = 15; /// Serialize a Python file to mypy AST format. /// /// # Arguments /// /// * `file_path` - Path to the Python file to serialize /// * `source` - File source contents to parse; if `None`, reads the contents from `file_path` /// * `skip_function_bodies` - If true, omit function bodies unless they have externally visible effects /// (for methods in classes only; module-level functions always have bodies omitted when this is true) /// * `options` - Reachability analysis options (python version, platform and always-true/-false names) /// /// # Returns /// /// A tuple containing: /// - A `Vec` with the serialized AST in mypy's binary format (may be partial if there are syntax errors) /// - A `Vec` containing any syntax errors with line/column information /// - A `Vec<(usize, Vec)>` containing tuples of (line_number, error_codes) for all type: ignore comments /// /// # Errors /// /// Returns an error if the file cannot be read (but not for syntax errors, which are returned in the tuple) pub(crate) fn serialize_python_file( file_path: &Path, source: Option<&str>, mut skip_function_bodies: bool, mut options: Options, ) -> Result<( Vec, Vec, Vec<(usize, Vec)>, Vec<(usize, Vec)>, Vec, bool, bool, String, Vec<(usize, String)>, )> { let source_type = PySourceType::from(file_path); let raw_source_text = match source { Some(source_text) => source_text, None => &std::fs::read_to_string(file_path)?, }; // Compute SHA1 hash of the source text (same as mypy's compute_hash) let hash_hex = { let hash = Sha1::digest(raw_source_text.as_bytes()); let mut hex = String::with_capacity(40); for byte in hash { write!(hex, "{byte:02x}").unwrap(); } hex }; // Apply universal newlines after hashing to match Python parser. let source_text = if !raw_source_text.contains('\r') { // Fast path: nothing to normalize. raw_source_text } else { &raw_source_text.replace("\r\n", "\n").replace("\r", "\n") }; let line_index = LineIndex::from_source_text(source_text); let is_stub_package = match file_path.file_name() { Some(file) => file.as_encoded_bytes() == b"__init__.pyi", _ => false, }; // Check if file is all ASCII and build per-line non-ASCII flags if needed let is_all_ascii = source_text.is_ascii(); let lines_with_non_ascii = if is_all_ascii { Vec::new() // No need to track per-line if whole file is ASCII } else { // Build a Vec indicating which lines have non-ASCII characters source_text.lines().map(|line| !line.is_ascii()).collect() }; // Parse the file - this always returns a result, even with syntax errors let parsed = parse_unchecked(source_text, ParseOptions::from(source_type)); // Extract syntax errors with location information let mut syntax_errors: Vec = parsed .errors() .iter() .map(|error| { let location = line_index.line_column(error.location.start(), source_text); SyntaxError { line: location.line.get(), column: location.column.get(), message: error.error.to_string(), blocker: true, } }) .collect(); // Extract both type: ignore comments and type annotation comments in a single pass let ( mut type_ignore_lines, mut mypy_ignore_lines, type_comments, mypy_comments, tc_syntax_errors, ) = extract_type_comments_and_ignores(parsed.tokens(), source_text, &line_index, &options); for syntax_error in tc_syntax_errors { syntax_errors.push(syntax_error); } // Apply inline config overrides that affect parsing/serialization. let inline_overrides = crate::mypy_inline_config::resolve_overrides(&mypy_comments); options.extend_always_true(inline_overrides.always_true); options.extend_always_false(inline_overrides.always_false); // Inline ignore-errors can only enable body skipping, not disable it, // since the caller may have set skip_function_bodies based on other // context (e.g. ignore_all from config file section matching). if inline_overrides.ignore_errors == Some(true) { skip_function_bodies = true; } let mut top_unreachable = false; // Find what is the first mypy/type ignore (if any). let mut first_ignore = None; if !type_ignore_lines.is_empty() || !mypy_ignore_lines.is_empty() { if type_ignore_lines.is_empty() { first_ignore = Some(mypy_ignore_lines[0].clone()); } else if mypy_ignore_lines.is_empty() { first_ignore = Some(type_ignore_lines[0].clone()); } else { let first_type_ignore = type_ignore_lines[0].clone(); let first_mypy_ignore = mypy_ignore_lines[0].clone(); if first_type_ignore.0 < first_mypy_ignore.0 { first_ignore = Some(first_type_ignore); } else { first_ignore = Some(first_mypy_ignore); } } }; let first_statement_line = first_statement_line(parsed.syntax(), source_text, &line_index); if first_ignore.is_some() { let (first_line, codes) = first_ignore.unwrap(); if first_line < first_statement_line { top_unreachable = true; type_ignore_lines = Vec::new(); mypy_ignore_lines = Vec::new(); if !codes.is_empty() { let joined = codes.join(", "); let error = format!( "Type ignore with error code is not supported for modules; \ use `# mypy: disable-error-code=\"{}\"`", joined ); syntax_errors.push(SyntaxError { line: first_line, column: 0, message: error, blocker: false, }) } } } // Serialize the AST (even if partial due to syntax errors) let mut ser = Serializer { bytes: Vec::new(), imports: Vec::new(), line_index, tokens: Some(parsed.tokens()), text: source_text, skip_function_bodies, in_class: false, in_function: false, is_all_ascii, lines_with_non_ascii, type_comments, options, current_unreachable: false, current_mypy_only: false, top_level_getattr: false, is_evaluated: true, extra_errors: Vec::new(), skipped_lines: HashSet::new(), uses_template_strings: false, has_surrogates: false, location_override: None, }; if top_unreachable { // Module is ignored completely. ser.write_tagged_int(0); } else { parsed.syntax().serialize(&mut ser); } // Serialize the collected imports, reusing the moved state from serializer let import_bytes = serialize_imports( &ser.imports, source_text, Some(ser.line_index), Some(is_all_ascii), Some(ser.lines_with_non_ascii), ); // Return this directly to caller, so that it can check this without deserialization let is_partial_package = is_stub_package && ser.top_level_getattr; syntax_errors.extend(ser.extra_errors); // Skip type ignores on unreachable lines, so that they are not flagged as unused. type_ignore_lines.retain(|(line, _)| !ser.skipped_lines.contains(line)); mypy_ignore_lines.retain(|(line, _)| !ser.skipped_lines.contains(line)); Ok(( ser.bytes, syntax_errors, type_ignore_lines, mypy_ignore_lines, import_bytes, is_partial_package, ser.uses_template_strings, hash_hex, mypy_comments, )) } // Bit flags for import statement metadata. Deserializers ignore unknown bits, // so adding a flag here doesn't require a cache version bump. const IMPORT_FLAG_TOP_LEVEL: u8 = 1 << 0; // true if import is not within a function const IMPORT_FLAG_UNREACHABLE: u8 = 1 << 1; // true if import is in unreachable code const IMPORT_FLAG_MYPY_ONLY: u8 = 1 << 2; // true if import is mypy-only (e.g., in TYPE_CHECKING block) const IMPORT_FLAG_LAZY: u8 = 1 << 3; // true if this is a lazy import (PEP 810), e.g. 'lazy import x' // Used to report which imports are used in a file pub(crate) enum ImportStatement { Import { name: String, relative: i32, // Number of dots in relative import 'import ..x' as_name: Option, // Set for 'import x as y' range: TextRange, // Source range of the import alias flags: u8, // Bitfield of IMPORT_FLAG_* constants }, ImportFrom { module: String, // Module being imported from (empty string for "from . import x") relative: i32, // Number of dots in relative import names: Vec<(String, Option)>, // List of (name, as_name) tuples range: TextRange, // Source range of the entire import statement flags: u8, // Bitfield of IMPORT_FLAG_* constants }, ImportAll { module: String, // Module being imported from (empty string for "from . import *") relative: i32, // Number of dots in relative import range: TextRange, // Source range of the entire import statement flags: u8, // Bitfield of IMPORT_FLAG_* constants }, } #[derive(Clone, Debug, PartialEq)] pub(crate) enum ParsedTypeComment { Regular(ast::Expr), // Comment like `# type: int` Function(Vec, ast::Expr), // Comment like `# type: (int, str) -> None` Invalid(String), // Error message for invalid type comment } // Represents Python source code originating from a Python object and converted into `String` pub(crate) enum Source<'a> { Text(String), Bytes(&'a [u8]), } // Implementation for converting a Python object into `Source` impl<'a, 'py> pyo3::FromPyObject<'a, 'py> for Source<'a> { type Error = pyo3::PyErr; fn extract(obj: pyo3::Borrowed<'a, 'py, pyo3::PyAny>) -> Result { if let Ok(s) = obj.extract::() { Ok(Source::Text(s)) } else if let Ok(s) = obj.extract::<&[u8]>() { Ok(Source::Bytes(s)) } else { Err(Self::Error::new::( "Source must be str or bytes", )) } } } // Parse a fixed size hex integer (known to be valid) fn parse_int(chars: &mut std::str::Chars, size: usize) -> u32 { let mut result: u32 = 0u32; for i in 1..=size { match chars.next() { // We know that there are no invalid escapes, since the string parsed successfully Some(c) => match c.to_digit(16) { Some(d) => result += d << ((size - i) * 4), None => unreachable!(), }, None => unreachable!(), } } result } // Check if given codepoint is a Unicode surrogate fn is_surrogate(ord: u32) -> bool { if ord >= 0xd800 && ord <= 0xdfff { return true; } false } struct Serializer<'a> { bytes: Vec, imports: Vec, // Encountered import statements line_index: LineIndex, tokens: Option<&'a Tokens>, // All tokens (not set when serializing imports, and in tests) text: &'a str, skip_function_bodies: bool, // Whether to omit function bodies without visible effects in_class: bool, // Whether we're currently inside a class definition in_function: bool, // Whether we're currently inside a function definition is_all_ascii: bool, // Whether the entire file contains only ASCII characters lines_with_non_ascii: Vec, // Per-line flags: true if line has non-ASCII (empty if is_all_ascii) type_comments: HashMap, // Type comments by line number (1-indexed) options: Options, // Reachability analysis options current_unreachable: bool, // Whether we're currently in an unreachable block current_mypy_only: bool, // Whether we're currently in a mypy-only block (e.g., if TYPE_CHECKING) top_level_getattr: bool, // Does module have top-level __getattr__() function is_evaluated: bool, // Current type is evaluated at runtime (or is it a type comment/string) extra_errors: Vec, // Additional errors found while processing parsed tree skipped_lines: HashSet, // Lines of blocks that were found unreachable uses_template_strings: bool, // Whether parsed file uses t-strings has_surrogates: bool, // Whether we have seen Unicode surrogate codepoints location_override: Option<(u32, u32, u32, u32)>, // Location override to use when serializing AST } impl<'a> Serializer<'a> { #[inline] fn write_tag(&mut self, i: u8) { self.bytes.push(i); } #[inline] fn write_end_tag(&mut self) { self.write_tag(TAG_END); } #[inline] fn write_tagged_int(&mut self, i: i64) { self.write_tag(TAG_LITERAL_INT); self.write_int(i); } #[inline] fn write_usize(&mut self, i: usize) { self.write_int(i as i64); } fn write_bytes(&mut self, b: &[u8]) { self.write_tag(TAG_LITERAL_STR); self.write_usize(b.len()); self.bytes.extend_from_slice(b); } fn write_bool(&mut self, b: bool) { self.bytes.push(if b { TAG_LITERAL_TRUE } else { TAG_LITERAL_FALSE }); } fn write_int(&mut self, i: i64) { if i >= MIN_SHORT_INT && i < 128 + MIN_SHORT_INT { // 1-byte format self.bytes.push(((i - MIN_SHORT_INT) << 1) as u8); } else if i >= MIN_TWO_BYTES_INT && i <= MAX_TWO_BYTES_INT { // 2-byte format let x: u16 = (((i - MIN_TWO_BYTES_INT) << 2) | TWO_BYTES_INT_BIT) as u16; self.bytes.extend_from_slice(&x.to_le_bytes()); } else if i >= MIN_FOUR_BYTES_INT && i <= MAX_FOUR_BYTES_INT { // 4-byte format let x: u32 = (((i - MIN_FOUR_BYTES_INT) << 3) | FOUR_BYTES_INT_TRAILER) as u32; self.bytes.extend_from_slice(&x.to_le_bytes()); } else { // Variable-length format self.bytes.push(LONG_INT_TRAILER); let neg = i < 0; let absval = if neg { i.wrapping_abs() as u64 } else { i as u64 }; let bytes = absval.to_le_bytes(); let mut n = bytes.len(); while n > 1 && bytes[n - 1] == 0 { n -= 1; } self.write_int(((n as i64) << 1) | (neg as i64)); self.bytes.extend_from_slice(&bytes[..n]); } } /// Find the largest byte offset <= target that is a UTF-8 character boundary. /// Similar to the unstable str::floor_char_boundary method. fn floor_char_boundary(&self, s: &str, mut target: usize) -> usize { if target > s.len() { target = s.len(); } // Walk backwards until we find a character boundary while target > 0 && !s.is_char_boundary(target) { target -= 1; } target } /// Convert a column number (UTF-8 byte offset) to a Unicode code point offset /// if the line contains non-ASCII characters. Returns the column as-is for ASCII lines. /// /// Note: This should only be called when is_all_ascii is false (checked by caller). fn convert_column_to_codepoint(&self, line_number: usize, byte_column: usize) -> usize { // Check if this specific line has non-ASCII // Note: line_number is 1-indexed, but Vec is 0-indexed let line_idx = line_number.saturating_sub(1); if line_idx < self.lines_with_non_ascii.len() && self.lines_with_non_ascii[line_idx] { // This line has non-ASCII, need to convert // Get the byte offset of the start of this line in the full text let line_start = self.line_index.line_start( ruff_source_file::OneIndexed::from_zero_indexed(line_idx), self.text, ); let line_start_byte = line_start.to_usize(); // Calculate the absolute byte position in the full text let target_byte = line_start_byte + byte_column; // Make sure we don't go past the end of the text and are at a char boundary let safe_target = target_byte.min(self.text.len()); // Ensure we're at a valid character boundary let char_boundary = self.floor_char_boundary(self.text, safe_target); // Extract the portion of the line from start to the target column let line_prefix = &self.text[line_start_byte..char_boundary]; // Count code points in this prefix line_prefix.chars().count() } else { // This line is ASCII, no conversion needed byte_column } } /// Record if the text range contains Unicode surrogates (including non-escaped ones) fn check_surrogate_codepoint(&mut self, parsed_value: &str, range: TextRange) { if !parsed_value.contains(char::REPLACEMENT_CHARACTER) { return; } if self.has_surrogates { // No need to check, we already have seen some surrogates return; } let mut chars = self.text[range].chars(); while let Some(char) = chars.next() { // Rust strings should not contain raw surrogates, but we are defensive. if is_surrogate(char.into()) { self.has_surrogates = true; return; } if char == '\\' { if let Some(next_char) = chars.next() { if next_char == 'u' && is_surrogate(parse_int(&mut chars, 4)) { self.has_surrogates = true; return; } if next_char == 'U' && is_surrogate(parse_int(&mut chars, 8)) { self.has_surrogates = true; return; } } } } } fn write_location(&mut self, range: TextRange) { self.write_tag(TAG_LOCATION); if let Some((line, column, end_line, end_column)) = self.location_override { self.write_int(line as i64); self.write_int(column as i64); self.write_int(end_line as i64 - line as i64); self.write_int(end_column as i64 - column as i64); return; } let st_loc = self.line_index.line_column(range.start(), self.text); let st_line = st_loc.line.get() as i64; let st_column_bytes = st_loc.column.get(); let end_loc = self.line_index.line_column(range.end(), self.text); let end_column_bytes = end_loc.column.get(); // Fast path for all-ASCII files: use byte offsets directly (no conversion needed) // Note: Ruff uses 1-based columns, but mypy expects 0-based, so subtract 1 if self.is_all_ascii { self.write_int(st_line); self.write_int((st_column_bytes - 1) as i64); // Convert to 0-based self.write_int((end_loc.line.get() as i64) - st_line); self.write_int((end_column_bytes as i64) - (st_column_bytes as i64)); } else { // Convert byte offset to code point offset for Python compatibility // Note: Ruff uses 1-based columns, but mypy expects 0-based, so subtract 1 let st_column = self.convert_column_to_codepoint(st_loc.line.get(), st_column_bytes) as i64; let end_column = self.convert_column_to_codepoint(end_loc.line.get(), end_column_bytes) as i64; self.write_int(st_line); self.write_int(st_column - 1); // Convert to 0-based self.write_int((end_loc.line.get() as i64) - st_line); self.write_int(end_column - st_column); } } /// Mark all statements between `from` and `to` (inclusive) as skipped. fn skip_lines(&mut self, from: &ast::Stmt, to: &ast::Stmt) { let st_loc = self.line_index.line_column(from.start(), self.text); let st_line = st_loc.line.get(); let end_loc = self.line_index.line_column(to.end(), self.text); let end_line = end_loc.line.get(); self.skipped_lines.extend(st_line..end_line + 1); } // fallback_range = None means deserializer can handle situations when this block is empty. fn serialize_block(&mut self, block: &ThinVec, fallback_range: Option) { self.write_tag(TAG_BLOCK); self.write_tag(TAG_LIST_GEN); self.write_usize(block.len()); self.write_bool(self.current_unreachable); if !block.is_empty() && self.current_unreachable { self.skip_lines(block.first().unwrap(), block.last().unwrap()); } if block.is_empty() && fallback_range.is_some() { // Body was not generated (likely due to a syntax error), but // deserializer expects location for empty bodies. self.write_location(fallback_range.unwrap()) } for stmt in block { stmt.serialize(self); } self.write_end_tag(); } fn serialize_empty_block(&mut self, range: TextRange) { self.write_tag(TAG_BLOCK); self.write_tag(TAG_LIST_GEN); self.write_int(0); // Empty list of statements self.write_bool(self.current_unreachable); self.write_location(range); // Write location after zero-length list self.write_end_tag(); } fn add_error(&mut self, error: String, range: TextRange, blocker: bool) { let st_loc = self.line_index.line_column(range.start(), self.text); let st_line = st_loc.line.get(); let st_column_bytes = st_loc.column.get(); let st_column = self.convert_column_to_codepoint(st_loc.line.get(), st_column_bytes); self.extra_errors.push(SyntaxError { line: st_line, column: st_column - 1, // convert to 0-based message: error, blocker, }); } } trait Ser { fn serialize(&self, ser: &mut Serializer); } impl Ser for Vec { fn serialize(&self, ser: &mut Serializer) { ser.write_tag(TAG_LIST_GEN); ser.write_int(self.len() as i64); for e in self { e.serialize(ser); } } } impl Ser for [ast::Expr] { fn serialize(&self, ser: &mut Serializer) { ser.write_tag(TAG_LIST_GEN); ser.write_int(self.len() as i64); for e in self { e.serialize(ser); } } } impl Ser for Option> { fn serialize(&self, ser: &mut Serializer) { if let Some(v) = &self { ser.write_bool(true); v.serialize(ser); } else { ser.write_bool(false); } } } impl Ser for ast::Mod { fn serialize(&self, ser: &mut Serializer) { match self { ast::Mod::Module(m) => { let mut body = Vec::new(); for (i, stmt) in m.body.iter().enumerate() { body.push(stmt); // This mimics behaviour of old parser; we strip everything // after a top-level assert that is always false. if assert_will_always_fail(stmt, &ser.options) { if i < m.body.len() - 1 { ser.skip_lines(&m.body[i + 1], m.body.last().unwrap()); } break; } } ser.write_tagged_int(body.len() as i64); for stmt in body { stmt.serialize(ser); } } ast::Mod::Expression(_) => { panic!("Expression unsupported"); } } } } fn first_statement_line(tree: &ast::Mod, source: &str, line_index: &LineIndex) -> usize { match tree { ast::Mod::Module(m) => { if m.body.is_empty() { return 0; } let stmt = &m.body[0]; let st_loc = line_index.line_column(stmt.start(), source); st_loc.line.get() } ast::Mod::Expression(_) => { panic!("Expression unsupported"); } } } /// Extract type comments (both type: ignore and type annotations) from tokens in a single pass. /// /// # Arguments /// /// * `tokens` - Reference to the tokens from parsing /// * `source` - The source code text /// * `line_index` - Line index for converting positions to line numbers /// /// # Returns /// /// A tuple containing: /// - A vector of tuples (line_number, error_codes) where `type: ignore` comments appear /// - A vector of tuples (line_number, error_codes) where `mypy: ignore` comments appear /// - A HashMap mapping line numbers (1-indexed) to parsed type annotation AST expressions /// - A vector of tuples (line_number, inline_config) where `mypy: inline-config` comments appear /// - A vector of SyntaxErrors for invalid `type: ignore` and `mypy: ignore` comments /// /// This function combines the functionality of extract_type_ignore_lines and extract_type_comments /// to avoid two separate passes over the token sequence, improving cache locality. fn extract_type_comments_and_ignores( tokens: &Tokens, source: &str, line_index: &LineIndex, options: &Options, ) -> ( Vec<(usize, Vec)>, Vec<(usize, Vec)>, HashMap, Vec<(usize, String)>, Vec, ) { let mut type_ignore_lines = Vec::new(); let mut mypy_ignore_lines = Vec::new(); let mut type_comments = HashMap::new(); let mut mypy_comments = Vec::new(); let mut syntax_errors = Vec::new(); for token in tokens.iter() { if token.kind().is_comment() { let comment_text = &source[token.range()]; let location = line_index.line_column(token.start(), source); let line_number = location.line.get(); let column = location.column.get(); // Check for "# mypy: " inline configuration comments at start of line. // Skip "# mypy: ignore" / "# mypy: ignore[...]" which are already // collected in mypy_ignore_lines. if location.column.get() == 1 { if let Some(after_mypy) = comment_text.strip_prefix("# mypy:") { let trimmed = after_mypy.trim(); if !trimmed.is_empty() { let is_ignore = trimmed == "ignore" || trimmed.starts_with("ignore[") || trimmed.starts_with("ignore "); if !is_ignore { mypy_comments.push((line_number, trimmed.to_string())); } } } } let before_comment = TextRange::new(line_index.line_start(location.line, source), token.start()); // Note: if the code before the comment is all whitespace, we extract only comment // parts before the first unrecognized part. This helps to avoid: // * Spurious unused type ignores in commented out blocks of code. // * Accidental whole-file type ignore (if appears before first statement). let skip_commented = source[before_comment.range()].trim().is_empty() || options.cache_version() < CV_FULL_TYPE_COMMENTS; if let Some(parts) = type_comment::parse_type_comments_full(comment_text, skip_commented) { let mut seen_type_ignore = false; let mut seen_mypy_ignore = false; for part in parts { match part { type_comment::TypeComment::InvalidIgnore(is_mypy) => { let message = format!( "Invalid \"{}: ignore\" comment", if is_mypy { "mypy" } else { "type" } ); syntax_errors.push(SyntaxError { line: line_number, column, message: message.to_string(), blocker: false, }); } type_comment::TypeComment::TypeIgnore(error_codes) => { if seen_type_ignore { syntax_errors.push(SyntaxError { line: line_number, column, message: "Multiple type ignores on the same line".to_string(), blocker: false, }); continue; } type_ignore_lines.push((line_number, error_codes)); seen_type_ignore = true; } type_comment::TypeComment::MypyIgnore(error_codes) => { if seen_mypy_ignore { syntax_errors.push(SyntaxError { line: line_number, column, message: "Multiple mypy ignores on the same line".to_string(), blocker: false, }); continue; } mypy_ignore_lines.push((line_number, error_codes)); seen_mypy_ignore = true; } type_comment::TypeComment::TypeAnnotation(annotation) => { if type_comments.contains_key(&line_number) { syntax_errors.push(SyntaxError { line: line_number, column, message: "Multiple type comments on the same line".to_string(), blocker: false, }); continue; } // Special case: empty type comment is considered an error if annotation.is_empty() { type_comments.insert( line_number, ParsedTypeComment::Invalid( "Syntax error in type comment \"\"".to_string(), ), ); continue; } let wrapped = format!("({})", annotation); let parse_result = parse_unchecked(&wrapped, ParseOptions::from(Mode::Expression)); if parse_result.errors().is_empty() { if let ast::Mod::Expression(expr_mod) = parse_result.into_syntax() { type_comments.insert( line_number, ParsedTypeComment::Regular(*expr_mod.body), ); } } else { // If parsing as regular type failed, try parsing it as a function type comment. let as_function_comment = parse_func_type_comment(annotation.as_str()); if let Some((arg_types, ret_type)) = as_function_comment { let parsed_function_comment = function_comment_to_expr(arg_types, ret_type); if let Some((parsed_arg_types, parsed_ret_type)) = parsed_function_comment { type_comments.insert( line_number, ParsedTypeComment::Function( parsed_arg_types, parsed_ret_type, ), ); continue; } } // If nothing worked (but we know it is a `# type:` comment), record an error. type_comments.insert( line_number, ParsedTypeComment::Invalid( format!("Syntax error in type comment \"{annotation}\"") .to_string(), ), ); } } } } } } } ( type_ignore_lines, mypy_ignore_lines, type_comments, mypy_comments, syntax_errors, ) } fn function_comment_to_expr( arg_types: Vec, ret_type: String, ) -> Option<(Vec, ast::Expr)> { let mut parsed_arg_types = Vec::with_capacity(arg_types.len()); for arg_type in arg_types { let wrapped = format!("({})", arg_type); let parse_result = parse_unchecked(&wrapped, ParseOptions::from(Mode::Expression)); if parse_result.errors().is_empty() { if let ast::Mod::Expression(expr_mod) = parse_result.into_syntax() { parsed_arg_types.push(*expr_mod.body); } } else { return None; } } let wrapped = format!("({})", ret_type); let parse_result = parse_unchecked(&wrapped, ParseOptions::from(Mode::Expression)); if parse_result.errors().is_empty() { if let ast::Mod::Expression(expr_mod) = parse_result.into_syntax() { return Some((parsed_arg_types, *expr_mod.body)); } } None } /// Helper function to serialize bytes literal to escaped string representation /// Used for BytesExpr in expression contexts where we need a human-readable form fn serialize_bytes_to_escaped_string(bytes_lit: &ast::ExprBytesLiteral) -> Vec { let mut result = Vec::new(); // This replicates "smart-quote" logic in PyBytes_Repr (which is used by old parser) let mut squotes = false; let mut dquotes = false; for bytes_part in bytes_lit.value.iter() { for &byte in bytes_part.value.iter() { if byte == b'\'' { squotes = true; } if byte == b'"' { dquotes = true; } } } let escape_quote = squotes && dquotes; for bytes_part in bytes_lit.value.iter() { for &byte in bytes_part.value.iter() { match byte { b'\r' => result.extend_from_slice(b"\\r"), b'\n' => result.extend_from_slice(b"\\n"), b'\t' => result.extend_from_slice(b"\\t"), b'\\' => result.extend_from_slice(b"\\\\"), b'\'' if escape_quote => result.extend_from_slice(b"\\'"), // Printable ASCII characters (space to ~) 32..=126 => result.push(byte), // Everything else as hex escape _ => { result.extend_from_slice(b"\\x"); result.push(b"0123456789abcdef"[(byte >> 4) as usize]); result.push(b"0123456789abcdef"[(byte & 0xf) as usize]); } } } } result } /// Helper function to serialize comprehensions (shared by Generator, ListComp, SetComp) fn serialize_comprehension( ser: &mut Serializer, elt: &ast::Expr, generators: &[ast::Comprehension], range: ruff_text_size::TextRange, ) { // Serialize element expression elt.serialize(ser); // Serialize number of generators ser.write_tagged_int(generators.len() as i64); // Serialize all indices (targets) for comp in generators { comp.target.serialize(ser); } // Serialize all sequences (iters) for comp in generators { comp.iter.serialize(ser); } // Serialize all condlists (ifs for each generator) for comp in generators { comp.ifs.serialize(ser); } // Serialize all is_async flags for comp in generators { ser.write_bool(comp.is_async); } ser.write_location(range); } /// Check if argument name should be elided (treated as positional-only). /// Returns true if the name starts with "__" but doesn't end with "__". /// This matches the behavior of mypy.sharedparse.argument_elide_name. fn argument_elide_name(name: &str) -> bool { name.starts_with("__") && !name.ends_with("__") } fn serialize_parameters( ser: &mut Serializer, params: &ast::Parameters, arg_comments: &Vec>, ) { // Count total number of arguments let mut arg_count = 0; arg_count += params.posonlyargs.len(); arg_count += params.args.len(); if params.vararg.is_some() { arg_count += 1; } arg_count += params.kwonlyargs.len(); if params.kwarg.is_some() { arg_count += 1; } // Write argument list ser.write_tag(TAG_LIST_GEN); ser.write_int(arg_count as i64); let mut idx = 0; // Serialize positional-only arguments for param in ¶ms.posonlyargs { serialize_argument( ser, ¶m.parameter, &arg_comments[idx], param.default.as_deref(), ARG_POS, ARG_OPT, true, ); idx += 1; } // Serialize regular positional arguments for param in ¶ms.args { let pos_only = argument_elide_name(¶m.parameter.name); serialize_argument( ser, ¶m.parameter, &arg_comments[idx], param.default.as_deref(), ARG_POS, ARG_OPT, pos_only, ); idx += 1; } // Serialize *args if let Some(vararg) = ¶ms.vararg { serialize_argument( ser, vararg, &arg_comments[idx], None, ARG_STAR, ARG_STAR, false, ); idx += 1; } // Serialize keyword-only arguments for param in ¶ms.kwonlyargs { serialize_argument( ser, ¶m.parameter, &arg_comments[idx], param.default.as_deref(), ARG_NAMED, ARG_NAMED_OPT, false, ); idx += 1; } // Serialize **kwargs if let Some(kwarg) = ¶ms.kwarg { serialize_argument( ser, kwarg, &arg_comments[idx], None, ARG_STAR2, ARG_STAR2, false, ); } } fn serialize_argument( ser: &mut Serializer, param: &ast::Parameter, arg_comment: &Option, default_expr: Option<&ast::Expr>, kind_no_default: i64, kind_with_default: i64, pos_only: bool, ) { // Argument name ser.write_bytes(param.name.as_bytes()); // Argument kind let kind = if default_expr.is_some() { kind_with_default } else { kind_no_default }; ser.write_tagged_int(kind); if param.annotation.is_some() && arg_comment.is_some() { ser.add_error( "Function has duplicate type signatures".to_string(), param.range(), false, ); } if let Some(ann) = ¶m.annotation { ser.write_bool(true); serialize_type(ser, ann); } else if arg_comment.is_some() { ser.write_bool(true); let mut arg_comment = arg_comment.clone().unwrap(); ast::relocate::relocate_expr(&mut arg_comment, param.range()); let was_evaluated = ser.is_evaluated; ser.is_evaluated = false; serialize_type(ser, &arg_comment); ser.is_evaluated = was_evaluated; } else { ser.write_bool(false); } // Default value if let Some(expr) = default_expr { ser.write_bool(true); expr.serialize(ser); } else { ser.write_bool(false); } // pos_only flag ser.write_bool(pos_only); ser.write_location(param.range()); } fn serialize_type_params(ser: &mut Serializer, type_params: &ast::TypeParams) { // Serialize each type parameter for type_param in &type_params.type_params { match type_param { ast::TypeParam::TypeVar(tv) => { // Type param kind ser.write_tagged_int(TYPE_VAR_KIND); // Name ser.write_bytes(tv.name.as_bytes()); // Check if bound is a tuple (constrained TypeVar) let (has_upper_bound, values) = if let Some(bound) = &tv.bound { if let ast::Expr::Tuple(tuple_expr) = bound.as_ref() { // Constrained TypeVar: T: (int, str) // Values come from the tuple elements (false, tuple_expr.elts.as_slice()) } else { // Regular bounded TypeVar: T: str (true, &[] as &[ast::Expr]) } } else { (false, &[] as &[ast::Expr]) }; // Upper bound if has_upper_bound { ser.write_bool(true); serialize_type(ser, tv.bound.as_ref().unwrap()); } else { ser.write_bool(false); } // Values (for constrained TypeVar) ser.write_tag(TAG_LIST_GEN); ser.write_int(values.len() as i64); for value in values { serialize_type(ser, value); } // Default if let Some(default) = &tv.default { ser.write_bool(true); serialize_type(ser, default); } else { ser.write_bool(false); } } ast::TypeParam::ParamSpec(ps) => { // Type param kind ser.write_tagged_int(PARAM_SPEC_KIND); // Name ser.write_bytes(ps.name.as_bytes()); // Upper bound (None for ParamSpec) ser.write_bool(false); // Values (empty for ParamSpec) ser.write_tag(TAG_LIST_GEN); ser.write_int(0); // Default if let Some(default) = &ps.default { ser.write_bool(true); serialize_type(ser, default); } else { ser.write_bool(false); } } ast::TypeParam::TypeVarTuple(tvt) => { // Type param kind ser.write_tagged_int(TYPE_VAR_TUPLE_KIND); // Name ser.write_bytes(tvt.name.as_bytes()); // Upper bound (None for TypeVarTuple) ser.write_bool(false); // Values (empty for TypeVarTuple) ser.write_tag(TAG_LIST_GEN); ser.write_int(0); // Default if let Some(default) = &tvt.default { ser.write_bool(true); serialize_type(ser, default); } else { ser.write_bool(false); } } } } } fn find_func_type_comment( ser: &mut Serializer, func: &StmtFunctionDef, ) -> (Vec>, Option) { let mut arg_types = Vec::with_capacity(func.parameters.len()); for _ in 0..func.parameters.len() { arg_types.push(None); } let mut ret_type = None; if func.body.is_empty() { return (arg_types, ret_type); } let first_stmt = func.body[0].start(); if ser.tokens.is_none() { return (arg_types, ret_type); } let tokens = ser.tokens.unwrap(); let tokens_before = tokens.before(first_stmt); let mut idx = tokens_before.len() - 1; loop { // Look for function type comments between colon in `def foo(...):` anr first statement. let token = tokens_before[idx].kind(); if idx == 0 || token == TokenKind::Colon { break; } if token == TokenKind::Comment { let location = ser .line_index .line_column(tokens_before[idx].start(), ser.text); let line_number = location.line.get(); if let Some(ParsedTypeComment::Function(args, ret)) = ser.type_comments.get(&line_number) { ret_type = Some(ret.clone()); if args.len() == 1 { if let Some(ast::Expr::EllipsisLiteral(_)) = args.get(0) { // Special case, single ellipsis like literally `# type: (...) -> None`. break; } } if args.len() == func.parameters.len() { for idx in 0..args.len() { arg_types[idx] = Some(args[idx].clone()); } } else if ser.in_class && args.len() == func.parameters.len() - 1 { // Skip the self or cls argument in methods. for idx in 1..func.parameters.len() { arg_types[idx] = Some(args[idx - 1].clone()); } } else { let err = if args.len() > func.parameters.len() { "Type signature has too many parameters" } else { "Type signature has too few parameters" }; ser.add_error(err.to_string(), func.range(), false); } break; } if let Some(ParsedTypeComment::Invalid(error)) = ser.type_comments.get(&line_number) { ser.add_error(error.to_string(), func.range(), false); break; } } idx -= 1; } // Also look for per-argument (regular) type comments (in multi-line signatures). for (idx, param) in func.parameters.iter().enumerate() { if let AnyParameterRef::Variadic(param) = param { let location = ser.line_index.line_column(param.start(), ser.text); let line = location.line.get(); if let Some(ParsedTypeComment::Regular(arg_type)) = ser.type_comments.get(&line) { if arg_types[idx].is_some() { ser.add_error( "Function has duplicate type signatures".to_string(), func.range(), false, ); } else { arg_types[idx] = Some(arg_type.clone()); } } } // Repeating this block twice is a bit unfortunate, but we do it // because two enum options are slightly different. if let AnyParameterRef::NonVariadic(param) = param { let location = ser.line_index.line_column(param.start(), ser.text); let line = location.line.get(); if let Some(ParsedTypeComment::Regular(arg_type)) = ser.type_comments.get(&line) { if arg_types[idx].is_some() { ser.add_error( "Function has duplicate type signatures".to_string(), func.range(), false, ); } else { arg_types[idx] = Some(arg_type.clone()); } } } } (arg_types, ret_type) } impl Ser for ast::Stmt { fn serialize(&self, ser: &mut Serializer) { match self { ast::Stmt::FunctionDef(f) => { let (arg_comments, ret_comment) = find_func_type_comment(ser, f); if !f.decorator_list.is_empty() { ser.write_tag(TAG_DECORATOR); // Serialize decorators ser.write_tag(TAG_LIST_GEN); ser.write_usize(f.decorator_list.len()); for dec in &f.decorator_list { dec.expression.serialize(ser); } // Serialize start location of the decorator. End is same as the func def. // Note: Decorator column intentionally uses 1-based (legacy parser behavior) let start_loc = ser .line_index .line_column(f.decorator_list.first().unwrap().range().start(), ser.text); ser.write_tagged_int(start_loc.line.get() as i64); ser.write_tagged_int(start_loc.column.get() as i64); } ser.write_tag(TAG_FUNC_DEF); // Function name ser.write_bytes(f.name.as_bytes()); // Parameters serialize_parameters(ser, &f.parameters, &arg_comments); // Body - may be omitted if skip_function_bodies is enabled let should_serialize_body = if ser.skip_function_bodies { // Check for externally visible effects // For methods (in_class), check both attributes and yield // For top-level functions, check only yield func_effect_visitor::has_externally_visible_effect( &f.body, &f.parameters, ser.in_class, // Only check attributes for methods in classes ) } else { true }; if !ser.in_class && !ser.in_function && f.name.as_str() == "__getattr__" { ser.top_level_getattr = true; }; // Body - mark that we're inside a function let was_in_function = ser.in_function; ser.in_function = true; if should_serialize_body { ser.serialize_block(&f.body, Some(f.range())); } else { // Use the range covering the entire body (start of first stmt to end of last stmt) let body_range = if !f.body.is_empty() { TextRange::new(f.body[0].start(), f.body[f.body.len() - 1].end()) } else { f.range() }; ser.serialize_empty_block(body_range); } ser.in_function = was_in_function; ser.write_bool(f.is_async); // Type parameters if let Some(type_params) = &f.type_params { ser.write_bool(true); ser.write_int(type_params.type_params.len() as i64); serialize_type_params(ser, type_params); } else { ser.write_bool(false); } // Return type annotation if f.returns.is_some() && ret_comment.is_some() { ser.add_error( "Function has duplicate type signatures".to_string(), f.range(), false, ); } if let Some(ret) = &f.returns { ser.write_bool(true); // No return annotation serialize_type(ser, ret); } else if ret_comment.is_some() { ser.write_bool(true); let mut ret_comment = ret_comment.clone().unwrap(); ast::relocate::relocate_expr(&mut ret_comment, f.range()); let was_evaluated = ser.is_evaluated; ser.is_evaluated = false; serialize_type(ser, &ret_comment); ser.is_evaluated = was_evaluated; } else { ser.write_bool(false); // No return annotation } // Record that type comment was present for this function if ser.options.cache_version() >= CV_FUNC_TYPE_COMMENT_FLAG { if arg_comments.iter().any(|ac| ac.is_some()) || ret_comment.is_some() { ser.write_bool(true); } else { ser.write_bool(false); } } // Write location if !f.decorator_list.is_empty() { // For decorated functions, compute def keyword position from function name // Assuming single space between tokens: "def " or "async def " ser.write_tag(TAG_LOCATION); let name_loc = ser.line_index.line_column(f.name.range.start(), ser.text); let end_loc = ser.line_index.line_column(f.range().end(), ser.text); // Compute def keyword column by subtracting offset from name position // "def " = 4 characters, "async def " = 10 characters // Note: Ruff uses 1-based columns, convert to 0-based for mypy let def_offset = if f.is_async { 10 } else { 4 }; let def_column = (name_loc.column.get() - 1) as i64 - def_offset; let st_line = name_loc.line.get() as i64; ser.write_int(st_line); ser.write_int(def_column); // End deltas (relative to start) ser.write_int((end_loc.line.get() as i64) - st_line); ser.write_int((end_loc.column.get() - 1) as i64 - def_column); } else { // No decorators: use the full range (already starts at async/def) ser.write_location(f.range()); } if !f.decorator_list.is_empty() { // Extra end tag for the Decorator wrapper in mypy AST ser.write_end_tag(); } } ast::Stmt::Expr(e) => { ser.write_tag(TAG_EXPR_STMT); e.value.serialize(ser); } ast::Stmt::Assign(a) => { ser.write_tag(TAG_ASSIGN); a.targets.serialize(ser); a.value.serialize(ser); // Check if there's a type comment on the same line as this assignment let location = ser.line_index.line_column(a.start(), ser.text); let line_number = location.line.get(); let end_location = ser.line_index.line_column(a.end(), ser.text); let end_line_number = end_location.line.get(); // Allow type comment on last line to match common use case with old parser. // Clone the type expression to avoid borrow checker issues let type_expr = ser .type_comments .get(&line_number) .or(ser.type_comments.get(&end_line_number)) .cloned(); if let Some(ParsedTypeComment::Regular(mut type_expr)) = type_expr { // Has type annotation from type comment ser.write_bool(true); ast::relocate::relocate_expr(&mut type_expr, a.range()); let was_evaluated = ser.is_evaluated; ser.is_evaluated = false; serialize_type(ser, &type_expr); ser.is_evaluated = was_evaluated; } else if let Some(ParsedTypeComment::Invalid(error)) = type_expr { ser.add_error(error, a.range(), false); ser.write_bool(true); serialize_invalid_type(ser, None, None, None); ser.write_location(a.range()); ser.write_end_tag(); } else { // No type annotation ser.write_bool(false); } // new_syntax = false (not using PEP 526 syntax, using type comment) ser.write_bool(false); ser.write_location(a.range()); } ast::Stmt::AnnAssign(a) => { ser.write_tag(TAG_ASSIGN); // Serialize target as a single-element list ser.write_tag(TAG_LIST_GEN); ser.write_int(1); a.target.serialize(ser); // Serialize value (or TempNode if annotation-only) if let Some(value) = &a.value { value.serialize(ser); } else { // For annotation-only (x: int), serialize as TempNode ser.write_tag(TAG_TEMP_NODE); ser.write_end_tag(); } // has_type = true ser.write_bool(true); // Serialize type annotation serialize_type(ser, &a.annotation); // new_syntax = true (using PEP 526 syntax) ser.write_bool(true); ser.write_location(a.range()); } ast::Stmt::AugAssign(a) => { ser.write_tag(TAG_OPERATOR_ASSIGNMENT_STMT); // Serialize operator as string ser.write_bytes(a.op.as_str().as_bytes()); // Serialize lvalue (target) a.target.serialize(ser); // Serialize rvalue (value) a.value.serialize(ser); ser.write_location(a.range()); } ast::Stmt::Import(i) => { let flags = make_import_flags(ser, i.is_lazy); ser.write_tag(TAG_IMPORT); // Write number of imports ser.write_tagged_int(i.names.len() as i64); for name in &i.names { // Write import name ser.write_bytes(name.name.as_bytes()); // Write as_name (optional) if let Some(asname) = &name.asname { ser.write_bool(true); ser.write_bytes(asname.as_bytes()); } else { ser.write_bool(false); } ser.imports.push(ImportStatement::Import { name: name.name.to_string(), relative: 0, // Not a relative import as_name: name.asname.as_ref().map(|n| n.to_string()), range: name.range, flags, }); } ser.write_location(i.range()); if ser.options.cache_version() >= CV_IMPORT_FLAGS { ser.write_tagged_int(flags as i64); } } ast::Stmt::ImportFrom(ifrom) => { let flags = make_import_flags(ser, ifrom.is_lazy); // Check if this is a wildcard import (from m import *) if ifrom.names.len() == 1 && ifrom.names[0].name.as_str() == "*" { // Serialize as ImportAll ser.write_tag(TAG_IMPORT_ALL); // Write module name (empty string for "from . import *") ser.write_bytes(ifrom.module.as_ref().map_or(b"", |m| m.as_bytes())); // Write relative import level (number of dots) ser.write_tagged_int(ifrom.level as i64); ser.write_location(ifrom.range()); if ser.options.cache_version() >= CV_IMPORT_FLAGS { ser.write_tagged_int(flags as i64); } // Track in imports list for dependency tracking ser.imports.push(ImportStatement::ImportAll { module: ifrom .module .as_ref() .map_or(String::new(), |m| m.to_string()), relative: ifrom.level as i32, range: ifrom.range(), flags, }); } else { // Regular from...import statement ser.write_tag(TAG_IMPORT_FROM); // Write relative import level (number of dots) ser.write_tagged_int(ifrom.level as i64); // Write module name (empty string for "from . import x") ser.write_bytes(ifrom.module.as_ref().map_or(b"", |m| m.as_bytes())); // Write number of imported names ser.write_tagged_int(ifrom.names.len() as i64); // Collect names for dependency tracking let mut names = Vec::new(); // Write each name and optional alias for alias in &ifrom.names { ser.write_bytes(alias.name.as_bytes()); if let Some(asname) = &alias.asname { ser.write_bool(true); ser.write_bytes(asname.as_bytes()); } else { ser.write_bool(false); } // Collect for dependency tracking names.push(( alias.name.to_string(), alias.asname.as_ref().map(|n| n.to_string()), )); } // Track in imports list for dependency tracking ser.imports.push(ImportStatement::ImportFrom { module: ifrom .module .as_ref() .map_or(String::new(), |m| m.to_string()), relative: ifrom.level as i32, names, range: ifrom.range(), flags, }); ser.write_location(ifrom.range()); if ser.options.cache_version() >= CV_IMPORT_FLAGS { ser.write_tagged_int(flags as i64); } } } ast::Stmt::Return(s) => { ser.write_tag(TAG_RETURN); s.value.serialize(ser); ser.write_location(s.range()); } ast::Stmt::Raise(r) => { ser.write_tag(TAG_RAISE_STMT); // Serialize exception expression (optional) r.exc.serialize(ser); // Serialize from expression (optional) r.cause.serialize(ser); ser.write_location(r.range()); } ast::Stmt::Assert(a) => { ser.write_tag(TAG_ASSERT_STMT); // Serialize test expression a.test.serialize(ser); // Serialize optional message expression a.msg.serialize(ser); ser.write_location(a.range()); } ast::Stmt::If(s) => serialize_if_stmt(ser, s), ast::Stmt::While(s) => { ser.write_tag(TAG_WHILE); s.test.serialize(ser); ser.serialize_block(&s.body, Some(s.range())); ser.serialize_block(&s.orelse, None); ser.write_location(s.range()); } ast::Stmt::For(f) => { ser.write_tag(TAG_FOR_STMT); // Serialize index (target) f.target.serialize(ser); // Serialize iterator expression f.iter.serialize(ser); // Serialize body ser.serialize_block(&f.body, Some(f.range())); // Serialize else clause ser.serialize_block(&f.orelse, None); // Serialize is_async flag ser.write_bool(f.is_async); ser.write_location(f.range()); } ast::Stmt::With(w) => { ser.write_tag(TAG_WITH_STMT); // Write number of items ser.write_tagged_int(w.items.len() as i64); // Serialize each item for item in &w.items { // Serialize context expression item.context_expr.serialize(ser); // Serialize optional target item.optional_vars.serialize(ser); } // Serialize body ser.serialize_block(&w.body, Some(w.range())); // Serialize is_async flag ser.write_bool(w.is_async); ser.write_location(w.range()); } ast::Stmt::Pass(s) => { ser.write_tag(TAG_PASS_STMT); ser.write_location(s.range()); } ast::Stmt::Break(s) => { ser.write_tag(TAG_BREAK_STMT); ser.write_location(s.range()); } ast::Stmt::Continue(s) => { ser.write_tag(TAG_CONTINUE_STMT); ser.write_location(s.range()); } ast::Stmt::ClassDef(c) => { ser.write_tag(TAG_CLASS_DEF); // Class name ser.write_bytes(c.name.as_bytes()); // Body - mark that we're inside a class let was_in_class = ser.in_class; ser.in_class = true; ser.serialize_block(&c.body, Some(c.range())); ser.in_class = was_in_class; // Base classes (positional arguments in class definition) ser.write_tag(TAG_LIST_GEN); if let Some(args) = &c.arguments { ser.write_int(args.args.len() as i64); for base in &args.args { base.serialize(ser); } } else { ser.write_int(0); // No base classes } // Decorators ser.write_tag(TAG_LIST_GEN); ser.write_int(c.decorator_list.len() as i64); for dec in &c.decorator_list { dec.expression.serialize(ser); } // Type parameters if let Some(type_params) = &c.type_params { ser.write_bool(true); ser.write_int(type_params.type_params.len() as i64); serialize_type_params(ser, type_params); } else { ser.write_bool(false); } // Keywords (all keyword arguments including metaclass) ser.write_tag(TAG_DICT_STR_GEN); if let Some(args) = &c.arguments { // Count keywords with argument names (exclude **kwargs which have no arg) let named_keywords: Vec<_> = args.keywords.iter().filter(|kw| kw.arg.is_some()).collect(); ser.write_int(named_keywords.len() as i64); // Serialize each keyword: name then value for kw in named_keywords { if let Some(arg_name) = &kw.arg { ser.write_bytes(arg_name.as_bytes()); kw.value.serialize(ser); } } } else { ser.write_int(0); // No keywords } // Write location if !c.decorator_list.is_empty() { // Custom location: use class name's line with last decorator's column ser.write_tag(TAG_LOCATION); let last_decorator = c.decorator_list.last().unwrap(); let decorator_loc = ser .line_index .line_column(last_decorator.range().start(), ser.text); let name_loc = ser.line_index.line_column(c.name.range.start(), ser.text); let end_loc = ser.line_index.line_column(c.range().end(), ser.text); // Start: name's line, decorator's column // Note: Ruff uses 1-based columns, convert to 0-based for mypy let st_line = name_loc.line.get() as i64; let st_column = (decorator_loc.column.get() - 1) as i64; ser.write_int(st_line); ser.write_int(st_column); // End deltas (relative to start) ser.write_int((end_loc.line.get() as i64) - st_line); ser.write_int((end_loc.column.get() - 1) as i64 - st_column); } else { // No decorators: use the full range ser.write_location(c.range()); } } ast::Stmt::Try(t) => { ser.write_tag(TAG_TRY_STMT); // Serialize try body ser.serialize_block(&t.body, Some(t.range())); // Serialize number of except handlers ser.write_tagged_int(t.handlers.len() as i64); // Serialize exception types for each handler for handler in &t.handlers { match handler { ast::ExceptHandler::ExceptHandler(h) => { if let Some(type_expr) = &h.type_ { ser.write_bool(true); type_expr.serialize(ser); if let ast::Expr::Tuple(t) = type_expr.as_ref() { // Python version checks for syntax features are usually // done on the mypy side, but in this case it is easier to // do it here (as it avoids storing/reading an extra flag). if ser.options.python_version() < (3, 14) && !t.parenthesized && h.name.is_none() { ser.add_error( "multiple exception types must be parenthesized" .to_string(), t.range(), false, ); } } } else { ser.write_bool(false); } } } } // Serialize variable names for each handler for handler in &t.handlers { match handler { ast::ExceptHandler::ExceptHandler(h) => { if let Some(name) = &h.name { ser.write_bool(true); ser.write_bytes(name.as_bytes()); if ser.options.cache_version() >= CV_HANDLER_LOCATIONS { ser.write_location(name.range()); } } else { ser.write_bool(false); } } } } // Serialize handler bodies for handler in &t.handlers { match handler { ast::ExceptHandler::ExceptHandler(h) => { ser.serialize_block(&h.body, Some(h.range())); } } } // Serialize else body (optional) if !t.orelse.is_empty() { ser.write_bool(true); ser.serialize_block(&t.orelse, Some(t.range())); } else { ser.write_bool(false); } // Serialize finally body (optional) if !t.finalbody.is_empty() { ser.write_bool(true); ser.serialize_block(&t.finalbody, Some(t.range())); } else { ser.write_bool(false); } // Serialize is_star flag (for except* in Python 3.11+) ser.write_bool(t.is_star); ser.write_location(t.range()); } ast::Stmt::Delete(d) => { ser.write_tag(TAG_DEL_STMT); // Serialize the target expression // If there's only one target, serialize it directly // If there are multiple targets, serialize as a tuple if d.targets.len() == 1 { d.targets[0].serialize(ser); } else { // Serialize as a tuple expression ser.write_tag(TAG_TUPLE_EXPR); d.targets.serialize(ser); ser.write_location(d.range()); ser.write_end_tag(); } ser.write_location(d.range()); } ast::Stmt::Global(g) => { ser.write_tag(TAG_GLOBAL_DECL); // Write number of names ser.write_tagged_int(g.names.len() as i64); // Write each name for name in &g.names { ser.write_bytes(name.as_bytes()); } ser.write_location(g.range()); } ast::Stmt::Nonlocal(n) => { ser.write_tag(TAG_NONLOCAL_DECL); // Write number of names ser.write_tagged_int(n.names.len() as i64); // Write each name for name in &n.names { ser.write_bytes(name.as_bytes()); } ser.write_location(n.range()); } ast::Stmt::Match(m) => { // Infer all the reachability flags first (to avoid borrowing issues). let flags = { let mut analyzer = IfReachabilityAnalyzer::new(&ser.options); let mut flags = Vec::with_capacity(m.cases.len()); for case in &m.cases { flags.push(analyzer.match_case_flags(&case.pattern, case.guard.as_ref())) } flags }; ser.write_tag(TAG_MATCH_STMT); // Serialize subject expression m.subject.serialize(ser); // Write number of cases ser.write_tagged_int(m.cases.len() as i64); // Serialize each case for (case, (case_unreachable, case_mypy_only)) in m.cases.iter().zip(flags.iter().copied()) { // Serialize pattern case.pattern.serialize(ser); // Serialize optional guard case.guard.serialize(ser); // Serialize body with_branch_flags(ser, case_unreachable, case_mypy_only, |ser| { ser.serialize_block(&case.body, Some(case.range())) }); } ser.write_location(m.range()); } ast::Stmt::TypeAlias(ta) => { ser.write_tag(TAG_TYPE_ALIAS_STMT); // Name (as NameExpr) ta.name.serialize(ser); // Type parameters if let Some(type_params) = &ta.type_params { ser.write_int(type_params.type_params.len() as i64); serialize_type_params(ser, type_params); } else { ser.write_int(0); } // Value (the RHS type expression - deserialization will wrap it in LambdaExpr) ta.value.serialize(ser); // TypeAliasStmt location ser.write_location(ta.range()); } _ => { panic!("unsupported: {self:?}"); } }; ser.write_end_tag() } } fn is_always_or_mypy_false(truth: TruthValue) -> bool { matches!(truth, TruthValue::AlwaysFalse | TruthValue::MypyFalse) } fn is_always_or_mypy_true(truth: TruthValue) -> bool { matches!(truth, TruthValue::AlwaysTrue | TruthValue::MypyTrue) } /// Stateful reachability analyzer for if/elif/else chains. /// /// This is intentionally kept separate from serialization so emit logic can /// eventually call it in sequence: /// - `condition_flags(expr)` for each if/elif condition /// - `else_flags()` for the optional else block #[allow(dead_code)] struct IfReachabilityAnalyzer<'a> { options: &'a Options, tail_unreachable: bool, seen_mypy_true: bool, seen_mypy_false: bool, } #[allow(dead_code)] impl<'a> IfReachabilityAnalyzer<'a> { fn new(options: &'a Options) -> Self { Self { options, tail_unreachable: false, seen_mypy_true: false, seen_mypy_false: false, } } /// Analyze one if/elif condition and advance analyzer state. /// /// Returns `(unreachable, mypy_only)` for the corresponding block. fn condition_flags(&mut self, expr: &ast::Expr) -> (bool, bool) { let truth = infer_condition_value(expr, &self.options); let unreachable = self.tail_unreachable || is_always_or_mypy_false(truth); let mypy_only = !unreachable && !self.seen_mypy_true && truth == TruthValue::MypyTrue; self.tail_unreachable = self.tail_unreachable || is_always_or_mypy_true(truth); self.seen_mypy_true = self.seen_mypy_true || truth == TruthValue::MypyTrue; self.seen_mypy_false = self.seen_mypy_false || truth == TruthValue::MypyFalse; (unreachable, mypy_only) } /// Returns `(unreachable, mypy_only)` for the else block. fn else_flags(&self) -> (bool, bool) { let unreachable = self.tail_unreachable; let mypy_only = !unreachable && self.seen_mypy_false && !self.seen_mypy_true; (unreachable, mypy_only) } /// Similar to condition_flags() but for match statement cases. fn match_case_flags( &mut self, pattern: &ast::Pattern, guard: Option<&Box>, ) -> (bool, bool) { let pattern_truth = infer_pattern_value(pattern); let mut guard_truth = AlwaysTrue; if guard.is_some() { guard_truth = infer_condition_value(guard.as_ref().unwrap(), &self.options); } let unreachable = self.tail_unreachable || is_always_or_mypy_false(pattern_truth) || is_always_or_mypy_false(guard_truth); // Since patterns can never be MypyTrue, there is some asymmetry that only guard decides // mypy_only status, and a case cannot be mypy_only because we have seen mypy_false before. // This mimics the logic in old mypy parser. let mypy_only = !unreachable && !self.seen_mypy_true && guard_truth == TruthValue::MypyTrue && is_always_or_mypy_true(pattern_truth); self.tail_unreachable = self.tail_unreachable || is_always_or_mypy_true(guard_truth) && is_always_or_mypy_true(pattern_truth); self.seen_mypy_true = self.seen_mypy_true || guard_truth == TruthValue::MypyTrue && is_always_or_mypy_true(pattern_truth); (unreachable, mypy_only) } } #[inline(always)] fn with_branch_flags( ser: &mut Serializer, branch_unreachable: bool, branch_mypy_only: bool, f: impl FnOnce(&mut Serializer), ) { let old_unreachable = ser.current_unreachable; let old_mypy_only = ser.current_mypy_only; ser.current_unreachable = ser.current_unreachable || branch_unreachable; ser.current_mypy_only = ser.current_mypy_only || branch_mypy_only; f(ser); ser.current_unreachable = old_unreachable; ser.current_mypy_only = old_mypy_only; } fn serialize_if_stmt(ser: &mut Serializer, stmt: &ast::StmtIf) { let has_else = stmt .elif_else_clauses .last() .is_some_and(|clause| clause.test.is_none()); // First analyze reachability of each block let (main_flags, clause_flags, synthetic_else_flags) = { let mut analyzer = IfReachabilityAnalyzer::new(&ser.options); let main_flags = analyzer.condition_flags(&stmt.test); let mut clause_flags = Vec::with_capacity(stmt.elif_else_clauses.len()); for clause in &stmt.elif_else_clauses { let flags = match &clause.test { Some(expr) => analyzer.condition_flags(expr), None => analyzer.else_flags(), }; clause_flags.push(flags); } let synthetic_else_flags = if has_else { None } else { Some(analyzer.else_flags()) }; (main_flags, clause_flags, synthetic_else_flags) }; ser.write_tag(TAG_IF); stmt.test.serialize(ser); // Serialize main body with analyzer-provided flags. let (main_body_unreachable, main_body_mypy_only) = main_flags; with_branch_flags(ser, main_body_unreachable, main_body_mypy_only, |ser| { ser.serialize_block(&stmt.body, Some(stmt.range())) }); let num_elif = stmt.elif_else_clauses.len() - if has_else { 1 } else { 0 }; ser.write_tagged_int(num_elif as i64); // Process elif/else clauses for (clause, (branch_unreachable, branch_mypy_only)) in stmt .elif_else_clauses .iter() .zip(clause_flags.iter().copied()) { match &clause.test { Some(expr) => { // elif clause expr.serialize(ser); with_branch_flags(ser, branch_unreachable, branch_mypy_only, |ser| { ser.serialize_block(&clause.body, Some(clause.range())) }); } None => { // else clause ser.write_bool(true); with_branch_flags(ser, branch_unreachable, branch_mypy_only, |ser| { ser.serialize_block(&clause.body, Some(clause.range())) }); } } } if !has_else { let (else_unreachable, else_mypy_only) = synthetic_else_flags.expect("synthetic else flags must exist when there is no else"); if else_unreachable { // Serialize an empty block so that we can pass reachability information ser.write_bool(true); with_branch_flags(ser, else_unreachable, else_mypy_only, |ser| { ser.serialize_empty_block(stmt.range()) }); } else { ser.write_bool(false); } } ser.write_location(stmt.range()); } impl Ser for ast::Expr { fn serialize(&self, ser: &mut Serializer) { match self { ast::Expr::Name(n) => { ser.write_tag(TAG_NAME_EXPR); ser.write_bytes(n.id.as_bytes()); ser.write_location(n.range()); } ast::Expr::Attribute(a) => { ser.write_tag(TAG_MEMBER_EXPR); a.value.serialize(ser); ser.write_bytes(a.attr.as_bytes()); ser.write_location(a.range()); } ast::Expr::StringLiteral(s) => { ser.write_tag(TAG_STR_EXPR); let value = &s.value; ser.write_tag(TAG_LITERAL_STR); ser.write_usize(value.len()); ser.has_surrogates = false; for part in value.iter() { ser.bytes.extend_from_slice(part.as_bytes()); ser.check_surrogate_codepoint(&part.value, part.range()); } if ser.options.cache_version() >= CV_UNICODE_SURROGATE { ser.write_bool(ser.has_surrogates) } ser.write_location(s.range()); } ast::Expr::Call(c) => { ser.write_tag(TAG_CALL_EXPR); c.func.serialize(ser); let args = &c.arguments; // Serialize all arguments (positional + keyword + **kwargs) let total_args = args.args.len() + args.keywords.len(); ser.write_tag(TAG_LIST_GEN); ser.write_int(total_args as i64); for arg in &args.args { // Unwrap starred expressions match arg { ast::Expr::Starred(starred) => starred.value.serialize(ser), _ => arg.serialize(ser), } } for kwarg in &args.keywords { kwarg.value.serialize(ser); } // Serialize argument kinds ser.write_tag(TAG_LIST_INT); ser.write_int(total_args as i64); for arg in &args.args { match arg { ast::Expr::Starred(_) => ser.write_int(ARG_STAR), _ => ser.write_int(ARG_POS), } } for kwarg in &args.keywords { if kwarg.arg.is_none() { ser.write_int(ARG_STAR2); // **kwargs } else { ser.write_int(ARG_NAMED); // keyword arg } } // Serialize argument names ser.write_tag(TAG_LIST_GEN); ser.write_int(total_args as i64); for _ in &args.args { ser.write_tag(TAG_LITERAL_NONE); } for kwarg in &args.keywords { if let Some(arg_name) = &kwarg.arg { ser.write_bytes(arg_name.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } } ser.write_location(c.range()); } ast::Expr::BinOp(e) => { ser.write_tag(TAG_OP_EXPR); ser.write_tagged_int(e.op as i64); e.left.serialize(ser); e.right.serialize(ser); } ast::Expr::NumberLiteral(num) => { match &num.value { Number::Int(n) => { match n.as_i64() { Some(x) => { ser.write_tag(TAG_INT_EXPR); ser.write_tagged_int(x); } None => { // Use a string representation for big integers. It's not // very efficient, but these are rare. ser.write_tag(TAG_BIG_INT_EXPR); ser.write_bytes(n.to_string().as_bytes()); } } } Number::Float(f) => { ser.write_tag(TAG_FLOAT_EXPR); ser.write_tag(TAG_LITERAL_FLOAT); ser.bytes.extend_from_slice(&f.to_le_bytes()); } Number::Complex { real, imag } => { ser.write_tag(TAG_COMPLEX_EXPR); // Serialize real part ser.write_tag(TAG_LITERAL_FLOAT); ser.bytes.extend_from_slice(&real.to_le_bytes()); // Serialize imaginary part ser.write_tag(TAG_LITERAL_FLOAT); ser.bytes.extend_from_slice(&imag.to_le_bytes()); } } ser.write_location(num.range()); } ast::Expr::Subscript(e) => { ser.write_tag(TAG_INDEX); e.value.serialize(ser); e.slice.serialize(ser); ser.write_location(e.range()); } ast::Expr::List(e) => { // In mypy, lists in assignment contexts (Store) are converted to tuples // e.g., `a, [b, c] = x, [1, 2]` has `[b, c]` as TupleExpr on LHS if matches!(e.ctx, ast::ExprContext::Store) { ser.write_tag(TAG_TUPLE_EXPR); } else { ser.write_tag(TAG_LIST_EXPR); } e.elts.serialize(ser); ser.write_location(e.range()); } ast::Expr::Tuple(e) => { ser.write_tag(TAG_TUPLE_EXPR); e.elts.serialize(ser); ser.write_location(e.range()); } ast::Expr::Set(e) => { ser.write_tag(TAG_SET_EXPR); e.elts.serialize(ser); ser.write_location(e.range()); } ast::Expr::Generator(g) => { ser.write_tag(TAG_GENERATOR_EXPR); serialize_comprehension(ser, &g.elt, &g.generators, g.range()); } ast::Expr::ListComp(lc) => { ser.write_tag(TAG_LIST_COMPREHENSION); serialize_comprehension(ser, &lc.elt, &lc.generators, lc.range()); } ast::Expr::SetComp(sc) => { ser.write_tag(TAG_SET_COMPREHENSION); serialize_comprehension(ser, &sc.elt, &sc.generators, sc.range()); } ast::Expr::DictComp(dc) => { ser.write_tag(TAG_DICT_COMPREHENSION); // Serialize key expression if ser.options.cache_version() >= CV_DICT_KEY_OPT { dc.key.serialize(ser); } else { if dc.key.is_some() { dc.key.as_ref().unwrap().serialize(ser); } else { ser.add_error("PEP 798 is not supported yet".to_string(), dc.range(), true); // Recover by serializing key as None. ser.write_tag(TAG_NAME_EXPR); ser.write_bytes(b"None"); ser.write_location(dc.range()); } } // Serialize value expression dc.value.serialize(ser); // Serialize number of generators ser.write_tagged_int(dc.generators.len() as i64); // Serialize all indices (targets) for comp in &dc.generators { comp.target.serialize(ser); } // Serialize all sequences (iters) for comp in &dc.generators { comp.iter.serialize(ser); } // Serialize all condlists (ifs for each generator) for comp in &dc.generators { comp.ifs.serialize(ser); } // Serialize all is_async flags for comp in &dc.generators { ser.write_bool(comp.is_async); } ser.write_location(dc.range()); } ast::Expr::Yield(y) => { ser.write_tag(TAG_YIELD_EXPR); // Serialize optional value expression y.value.serialize(ser); ser.write_location(y.range()); } ast::Expr::YieldFrom(y) => { ser.write_tag(TAG_YIELD_FROM_EXPR); // Serialize value expression (required for yield from) y.value.serialize(ser); ser.write_location(y.range()); } ast::Expr::BoolOp(e) => { ser.write_tag(TAG_BOOL_OP_EXPR); ser.write_tagged_int(match e.op { ast::BoolOp::And => 0, ast::BoolOp::Or => 1, }); e.values.serialize(ser); ser.write_location(e.range()); } ast::Expr::Compare(e) => { ser.write_tag(TAG_COMPARISON_EXPR); e.left.serialize(ser); // Serialize operators ser.write_tag(TAG_LIST_INT); ser.write_usize(e.ops.len()); for op in &e.ops { ser.write_int(match op { ast::CmpOp::Eq => 0, ast::CmpOp::NotEq => 1, ast::CmpOp::Lt => 2, ast::CmpOp::LtE => 3, ast::CmpOp::Gt => 4, ast::CmpOp::GtE => 5, ast::CmpOp::Is => 6, ast::CmpOp::IsNot => 7, ast::CmpOp::In => 8, ast::CmpOp::NotIn => 9, }); } // Serialize comparators e.comparators.serialize(ser); ser.write_location(e.range()); } ast::Expr::BooleanLiteral(b) => { // Serialize as NameExpr with "True" or "False" ser.write_tag(TAG_NAME_EXPR); ser.write_bytes(if b.value { b"True" } else { b"False" }); ser.write_location(b.range()); } ast::Expr::NoneLiteral(n) => { // Serialize as NameExpr with "None" ser.write_tag(TAG_NAME_EXPR); ser.write_bytes(b"None"); ser.write_location(n.range()); } ast::Expr::EllipsisLiteral(e) => { ser.write_tag(TAG_ELLIPSIS_EXPR); ser.write_location(e.range()); } ast::Expr::If(i) => { ser.write_tag(TAG_CONDITIONAL_EXPR); // Serialize if_expr (body - value when condition is true) i.body.serialize(ser); // Serialize cond (test - the condition) i.test.serialize(ser); // Serialize else_expr (orelse - value when condition is false) i.orelse.serialize(ser); ser.write_location(i.range()); } ast::Expr::UnaryOp(u) => { ser.write_tag(TAG_UNARY_EXPR); // Serialize operator as integer ser.write_tagged_int(u.op as i64); // Serialize operand u.operand.serialize(ser); ser.write_location(u.range()); } ast::Expr::Dict(d) => { ser.write_tag(TAG_DICT_EXPR); // Serialize keys ser.write_tag(TAG_LIST_GEN); ser.write_int(d.items.len() as i64); for item in &d.items { if let Some(key) = &item.key { ser.write_bool(true); key.serialize(ser); } else { // Dict unpacking: {**other_dict} ser.write_bool(false); } } // Serialize values ser.write_tag(TAG_LIST_GEN); ser.write_int(d.items.len() as i64); for item in &d.items { item.value.serialize(ser); } ser.write_location(d.range()); } ast::Expr::Slice(s) => { ser.write_tag(TAG_SLICE_EXPR); // Serialize lower (begin_index in mypy) s.lower.serialize(ser); // Serialize upper (end_index in mypy) s.upper.serialize(ser); // Serialize step (stride in mypy) s.step.serialize(ser); ser.write_location(s.range()); } ast::Expr::FString(fs) => { ser.write_tag(TAG_FSTRING_EXPR); ser.write_tagged_int(fs.value.iter().len() as i64); ser.has_surrogates = false; for part in fs.value.iter() { match part { ast::FStringPart::FString(fstring_part) => { ser.write_bool(true); serialize_fstring_elements(ser, fstring_part.elements.iter().collect()); } ast::FStringPart::Literal(lit) => { ser.write_bool(false); ser.write_bytes(lit.value.as_bytes()); ser.check_surrogate_codepoint(&lit.value, lit.range()); ser.write_location(lit.range()); } } } if ser.options.cache_version() >= CV_UNICODE_SURROGATE { ser.write_bool(ser.has_surrogates) } ser.write_location(fs.range()); } ast::Expr::Lambda(lambda) => { ser.write_tag(TAG_LAMBDA_EXPR); // Arguments (parameters) if let Some(params) = &lambda.parameters { let mut empty = Vec::with_capacity(params.len()); for _ in 0..params.len() { empty.push(None); } serialize_parameters(ser, params, &empty); } else { // No parameters - empty argument list ser.write_tag(TAG_LIST_GEN); ser.write_int(0); } // Body - lambda body is a single expression, wrap in return statement // Serialize as a block containing a single return statement ser.write_tag(TAG_BLOCK); ser.write_tag(TAG_LIST_GEN); ser.write_int(1); // One statement (the return) ser.write_bool(ser.current_unreachable); // Write unreachable flag ser.write_tag(TAG_RETURN); // Return statement has an optional value, we always have a value for lambda ser.write_bool(true); lambda.body.serialize(ser); ser.write_location(lambda.body.range()); ser.write_end_tag(); // End of return statement ser.write_end_tag(); // End of block ser.write_location(lambda.range()); } ast::Expr::Named(named) => { ser.write_tag(TAG_ASSIGNMENT_EXPR); // Serialize target expression named.target.serialize(ser); // Serialize value expression named.value.serialize(ser); ser.write_location(named.range()); } ast::Expr::Starred(starred) => { ser.write_tag(TAG_STAR_EXPR); // Serialize the wrapped expression starred.value.serialize(ser); ser.write_location(starred.range()); } ast::Expr::BytesLiteral(bytes_lit) => { ser.write_tag(TAG_BYTES_EXPR); // Convert bytes to string representation with escape sequences let result = serialize_bytes_to_escaped_string(bytes_lit); ser.write_bytes(&result); ser.write_location(bytes_lit.range()); } ast::Expr::Await(await_expr) => { ser.write_tag(TAG_AWAIT_EXPR); // Serialize the awaited expression await_expr.value.serialize(ser); ser.write_location(await_expr.range()); } ast::Expr::TString(ts) => { ser.uses_template_strings = true; ser.write_tag(TAG_TSTRING_EXPR); ser.write_tagged_int(ts.value.elements().count() as i64); ser.has_surrogates = false; for part in ts.value.elements() { match part { ast::InterpolatedStringElement::Interpolation(tstring_part) => { ser.write_bool(true); tstring_part.expression.serialize(ser); ser.write_bytes(ser.text[tstring_part.expression.range()].as_bytes()); // This matches how mypy old parser handles conversions, but this is // inconsistent with f-strings, where we use "!s", not just "s", etc. match tstring_part.conversion { ast::ConversionFlag::None => { ser.write_bool(false); } ast::ConversionFlag::Str => { ser.write_bool(true); ser.write_bytes(b"s"); } ast::ConversionFlag::Repr => { ser.write_bool(true); ser.write_bytes(b"r"); } ast::ConversionFlag::Ascii => { ser.write_bool(true); ser.write_bytes(b"a"); } } // Reuse f-string logic for format specifiers. This is weird, but this is // what other parsers do (including Python, ruff, and mypy old parser). if let Some(format_spec) = &tstring_part.format_spec { ser.write_bool(true); serialize_fstring_elements( ser, format_spec.elements.iter().collect(), ); ser.write_location(format_spec.range()); } else { ser.write_bool(false); } } ast::InterpolatedStringElement::Literal(lit) => { ser.write_bool(false); ser.write_bytes(lit.value.as_bytes()); ser.check_surrogate_codepoint(&lit.value, lit.range()); ser.write_location(lit.range()); } } } if ser.options.cache_version() >= CV_UNICODE_SURROGATE { ser.write_bool(ser.has_surrogates) } ser.write_location(ts.range()); } _ => { panic!("unsupported: {self:?}"); } }; ser.write_end_tag() } } impl Ser for ast::Pattern { fn serialize(&self, ser: &mut Serializer) { match self { ast::Pattern::MatchAs(p) => { ser.write_tag(TAG_AS_PATTERN); // Serialize optional pattern if let Some(pattern) = &p.pattern { ser.write_bool(true); pattern.serialize(ser); } else { ser.write_bool(false); } // Serialize optional name if let Some(name) = &p.name { ser.write_bool(true); ser.write_bytes(name.as_bytes()); ser.write_location(name.range); } else { ser.write_bool(false); } ser.write_location(p.range()); } ast::Pattern::MatchOr(p) => { ser.write_tag(TAG_OR_PATTERN); // Write number of patterns ser.write_tagged_int(p.patterns.len() as i64); // Serialize each pattern for pattern in &p.patterns { pattern.serialize(ser); } ser.write_location(p.range()); } ast::Pattern::MatchValue(p) => { ser.write_tag(TAG_VALUE_PATTERN); // Serialize value expression p.value.serialize(ser); ser.write_location(p.range()); } ast::Pattern::MatchSingleton(p) => { ser.write_tag(TAG_SINGLETON_PATTERN); // Serialize singleton value (True, False, or None) match p.value { ast::Singleton::True => ser.write_bool(true), ast::Singleton::False => ser.write_bool(false), ast::Singleton::None => { // Special marker for None ser.write_tag(TAG_LITERAL_NONE); } } ser.write_location(p.range()); } ast::Pattern::MatchSequence(p) => { ser.write_tag(TAG_SEQUENCE_PATTERN); // Write number of patterns ser.write_tagged_int(p.patterns.len() as i64); // Serialize each pattern for pattern in &p.patterns { pattern.serialize(ser); } ser.write_location(p.range()); } ast::Pattern::MatchStar(p) => { ser.write_tag(TAG_STARRED_PATTERN); // Serialize optional capture name if let Some(name) = &p.name { ser.write_bool(true); ser.write_bytes(name.as_bytes()); ser.write_location(name.range); } else { ser.write_bool(false); } ser.write_location(p.range()); } ast::Pattern::MatchMapping(p) => { ser.write_tag(TAG_MAPPING_PATTERN); // Write number of key-value pairs ser.write_tagged_int(p.keys.len() as i64); // Serialize keys and patterns for (key, pattern) in p.keys.iter().zip(&p.patterns) { key.serialize(ser); pattern.serialize(ser); } // Serialize optional rest pattern if let Some(rest) = &p.rest { ser.write_bool(true); ser.write_bytes(rest.as_bytes()); ser.write_location(rest.range); } else { ser.write_bool(false); } ser.write_location(p.range()); } ast::Pattern::MatchClass(p) => { ser.write_tag(TAG_CLASS_PATTERN); // Serialize class reference p.cls.serialize(ser); // Write number of positional patterns ser.write_tagged_int(p.arguments.patterns.len() as i64); // Serialize positional patterns for pattern in &p.arguments.patterns { pattern.serialize(ser); } // Write number of keyword patterns ser.write_tagged_int(p.arguments.keywords.len() as i64); // Serialize keyword patterns for keyword in &p.arguments.keywords { ser.write_bytes(keyword.attr.as_bytes()); keyword.pattern.serialize(ser); } ser.write_location(p.range()); } }; ser.write_end_tag() } } fn serialize_fstring_elements(ser: &mut Serializer, elems: Vec<&ast::InterpolatedStringElement>) { // Debug items like {var=} need two elements per item: literal for expression // and actual interpolation item. let mut extra = 0; for elem in &elems { if let ast::InterpolatedStringElement::Interpolation(interp) = elem { if interp.debug_text.is_some() { extra += 1; } } } ser.write_tagged_int(elems.len() as i64 + extra); for elem in elems { match elem { ast::InterpolatedStringElement::Literal(lit) => { ser.write_bytes(lit.value.as_bytes()); ser.check_surrogate_codepoint(&lit.value, lit.range()); ser.write_location(lit.range()); } ast::InterpolatedStringElement::Interpolation(interp) => { // Ruff parser doesn't have any handling of debug f-strings, unlike Python parser, // so we (roughly) mimic the behavior of the latter, see _PyPegen_interpolation(). // For full 1:1 correspondence, the deserializer needs to collapse consecutive // literal parts, e.g. f"test {x=}" -> "".join("test x=", "{!r:{}}".format(x)). let mut use_r = false; if let Some(debug_text) = &interp.debug_text { let range = interp.expression.range(); let text = String::from(debug_text.leading()) + &ser.text[range] + debug_text.trailing(); ser.write_bytes(text.as_bytes()); ser.write_location(range); // This logic mimics _get_interpolation_conversion() in Python parser: only // auto-apply `!r` conversion in debug item if there is no format specifier. if interp.conversion == ast::ConversionFlag::None && interp.format_spec.is_none() { use_r = true; } } ser.write_tag(TAG_FSTRING_INTERPOLATION); interp.expression.serialize(ser); let mut conversion = interp.conversion; if use_r { conversion = ast::ConversionFlag::Repr; } match conversion { ast::ConversionFlag::None => { ser.write_bool(false); } ast::ConversionFlag::Str => { // !s conversion: f"{name!s}" ser.write_bool(true); ser.write_bytes(b"!s"); } ast::ConversionFlag::Repr => { // !r conversion: f"{name!r}" ser.write_bool(true); ser.write_bytes(b"!r"); } ast::ConversionFlag::Ascii => { // !a conversion: f"{name!a}" ser.write_bool(true); ser.write_bytes(b"!a"); } } if let Some(format_spec) = &interp.format_spec { ser.write_bool(true); serialize_fstring_elements(ser, format_spec.elements.iter().collect()); ser.write_location(format_spec.range()); } else { ser.write_bool(false); } ser.write_end_tag(); } } } } // ============================================================================ // Type Serialization Functions // ============================================================================ /// Helper to serialize an invalid type annotation as RawExpressionType with typing.Any. /// This is used for expressions that are not valid in type contexts (e.g., 3.14, int + str). fn serialize_invalid_type( ser: &mut Serializer, note: Option<&[u8]>, original_str_expr: Option<&str>, original_str_fallback: Option<&str>, ) { ser.write_tag(TAG_RAW_EXPRESSION_TYPE); if let Some(original_str_expr) = original_str_expr { // Whenever this is called from parsing a string literal as type, // convert it back to a regular (valid) RawExpressionType. // This is needed for literal types (and matches old parser behavior). ser.write_bytes(original_str_fallback.unwrap().as_bytes()); ser.write_bytes(original_str_expr.as_bytes()); return; } else { ser.write_bytes(b"typing.Any"); ser.write_tag(TAG_LITERAL_NONE); } if ser.options.cache_version() >= CV_RAW_EXPRESSION_TYPE_NOTES { if let Some(note) = note { ser.write_bytes(note); } else { ser.write_tag(TAG_LITERAL_NONE); } } } fn is_string_or_none(e: &Option) -> bool { match e { Some(ast::Expr::StringLiteral(_)) => true, None => true, _ => false, } } /// Serialize a type expression that appears inside a List context. /// Call expressions are treated as argument constructors (Arg/DefaultArg/VarArg/KwArg) /// only in this context (e.g., Callable[[Arg(int, 'x')], ret]). fn serialize_type_in_list(ser: &mut Serializer, t: &ast::Expr) { if let ast::Expr::Call(c) = t { ser.write_tag(TAG_CALL_TYPE); // Serialize callee serialize_type(ser, &c.func); // Serialize positional arguments ser.write_tag(TAG_LIST_GEN); ser.write_int(c.arguments.args.len() as i64); for arg in &c.arguments.args { serialize_type(ser, arg); } // Serialize keyword arguments (name, value pairs) ser.write_tag(TAG_LIST_GEN); ser.write_int(c.arguments.keywords.len() as i64); for keyword in &c.arguments.keywords { // Write keyword name (could be None for **kwargs) if let Some(name) = &keyword.arg { ser.write_bytes(name.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } // Write keyword value serialize_type(ser, &keyword.value); } ser.write_location(c.range()); ser.write_end_tag(); return; } serialize_type(ser, t); } /// Main entry point for serializing type annotations. /// Handles all Python type expressions including names, attributes, subscripts, /// unions, literals, and forward references (string literals). fn serialize_type(ser: &mut Serializer, t: &ast::Expr) { match t { ast::Expr::Name(e) => { serialize_simple_unbound_type(ser, e.id.as_bytes(), None, None); } ast::Expr::Attribute(_e) => { serialize_attribute_type(ser, t, None, None); } ast::Expr::Subscript(e) => { serialize_subscript_type(ser, e, None, None); } ast::Expr::NoneLiteral(_) => { serialize_simple_unbound_type(ser, b"None", None, None); } ast::Expr::BooleanLiteral(b) => { // Serialize as RawExpressionType with bool value ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.bool"); ser.write_bool(b.value); } ast::Expr::NumberLiteral(n) => { // Serialize integer literals as RawExpressionType with int value if n.value.is_int() { if let Some(int_val) = extract_int_literal_value(t) { ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.int"); ser.write_tagged_int(int_val); } else { // Integer too large for i64 - serialize as invalid type serialize_invalid_type(ser, None, None, None); } } else { // Float/complex number literals are not valid in type annotations // Serialize as invalid type serialize_invalid_type(ser, None, None, None); } } ast::Expr::BinOp(e) => { // Handle union types (x | y) if matches!(e.op, ast::Operator::BitOr) { serialize_union_type(ser, e, t.range(), None, None); return; } else { // Other binary operators are not valid in type annotations // Serialize as invalid type serialize_invalid_type(ser, None, None, None); } } ast::Expr::List(e) => { ser.write_tag(TAG_LIST_TYPE); // Serialize items list ser.write_tag(TAG_LIST_GEN); ser.write_int(e.elts.len() as i64); for item in &e.elts { // Use serialize_type_in_list so that Call expressions are treated // as argument constructors (Arg/DefaultArg/VarArg/KwArg) only // when inside a list context (e.g., Callable[[Arg(int, 'x')], ret]). serialize_type_in_list(ser, item); } } ast::Expr::Tuple(e) => { ser.write_tag(TAG_TUPLE_TYPE); // Serialize items list ser.write_tag(TAG_LIST_GEN); ser.write_int(e.elts.len() as i64); for item in &e.elts { serialize_type(ser, item); } // Write implicit = True (i.e. from (T, S) syntax) ser.write_bool(true); } ast::Expr::Dict(e) => { if !e.items.is_empty() && e.items.iter().all(|it| is_string_or_none(&it.key)) { ser.write_tag(TAG_TYPED_DICT_TYPE); // Serialize keys ser.write_tag(TAG_LIST_GEN); ser.write_int(e.items.len() as i64); for item in &e.items { if let Some(ast::Expr::StringLiteral(s)) = &item.key { let value = &s.value; ser.write_tag(TAG_LITERAL_STR); ser.write_usize(value.len()); for part in value.iter() { ser.bytes.extend_from_slice(part.as_bytes()); } } else { // Dict unpacking: {**other_dict} ser.write_tag(TAG_LITERAL_NONE); } } // Serialize values ser.write_tag(TAG_LIST_GEN); ser.write_int(e.items.len() as i64); for item in &e.items { serialize_type(ser, &item.value); } } else { serialize_invalid_type(ser, None, None, None); } } ast::Expr::Call(c) => { // Call expressions are usually not valid as types. Argument constructor // calls (Arg/DefaultArg/VarArg/KwArg) are an exception and are handled // in serialize_type_in_list. let mut name = Vec::new(); let note = if get_qualified_type_name(&mut name, &c.func) { if c.arguments.keywords.is_empty() { let mut note = b"Suggestion: use ".to_vec(); note.extend_from_slice(&name); note.extend_from_slice(b"[...] instead of "); note.extend_from_slice(&name); note.extend_from_slice(b"(...)"); Some(note) } else { Some(b"Cannot use a function call in a type annotation".to_vec()) } } else { None }; serialize_invalid_type(ser, note.as_deref(), None, None); } ast::Expr::EllipsisLiteral(_) => { ser.write_tag(TAG_ELLIPSIS_TYPE); // EllipsisType has no attributes } ast::Expr::Starred(e) => { ser.write_tag(TAG_UNPACK_TYPE); serialize_type(ser, &e.value); // Write from_star_syntax flag (true for * syntax, false for Unpack[...]) ser.write_bool(true); } ast::Expr::UnaryOp(e) => { // Handle unary operators on integer literals in types if matches!(e.op, ast::UnaryOp::USub) { // Negative integer literal (e.g., Literal[-1]) if let Some(int_val) = extract_int_literal_value(t) { ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.int"); ser.write_tagged_int(int_val); // Return early since we've already written location and end tag below ser.write_location(e.range()); ser.write_end_tag(); return; } else { // Negative number too large - serialize as invalid type serialize_invalid_type(ser, None, None, None); } } else if matches!(e.op, ast::UnaryOp::UAdd) { // Positive unary operator (+) - preserve the underlying value // This matches fastparse.py behavior where +5 returns the value unchanged if let Some(int_val) = extract_int_literal_value(&e.operand) { ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.int"); ser.write_tagged_int(int_val); // Return early since we've already written location and end tag below ser.write_location(e.range()); ser.write_end_tag(); return; } else { // Number too large or not an integer - serialize as invalid type serialize_invalid_type(ser, None, None, None); } } else { // Other unary operators (not, ~, etc.) are not valid in type annotations // Serialize as invalid type serialize_invalid_type(ser, None, None, None); } } ast::Expr::StringLiteral(s) => { // String literals in type context (forward references or Literal["x"]) // Extract the string value (concatenate all parts) let mut string_value = String::new(); for part in &s.value { string_value.push_str(part.as_str()); } // Try to parse the string as a type expression let was_evaluated = ser.is_evaluated; ser.is_evaluated = false; serialize_string_type(ser, &string_value, s.range()); ser.is_evaluated = was_evaluated; return; // serialize_string_type handles location and end tag } ast::Expr::BytesLiteral(bytes_lit) => { // Bytes literals in type context (e.g., Literal[b"foo"]) // Unlike string literals, bytes literals can't be used for forward references, // so they're treated similar to integer literals. // We serialize the bytes as an escaped string (similar to BytesExpr) ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.bytes"); let result = serialize_bytes_to_escaped_string(bytes_lit); ser.write_bytes(&result); } _ => { // Unsupported expression type in type annotation // Serialize as invalid type serialize_invalid_type(ser, None, None, None); } } ser.write_location(t.range()); ser.write_end_tag(); } /// A thin wrapper exposing serialize_string_type() below as a standalone function. pub(crate) fn serialize_type_string( source: &str, options: Options, range: (u32, u32, u32, u32), ) -> Result> { let mut ser = Serializer { bytes: Vec::new(), imports: Vec::new(), // Fake/empty values given because they are required, // actual location is set by `location_override` line_index: LineIndex::from_source_text(""), tokens: None, text: "", skip_function_bodies: false, in_class: false, in_function: false, is_all_ascii: false, lines_with_non_ascii: Vec::new(), type_comments: HashMap::new(), options, current_unreachable: false, current_mypy_only: false, top_level_getattr: false, is_evaluated: false, extra_errors: Vec::new(), skipped_lines: HashSet::new(), uses_template_strings: false, has_surrogates: false, location_override: Some(range), }; serialize_string_type(&mut ser, source, TextRange::default()); Ok(ser.bytes) } /// Parse and serialize a string literal that appears in a type context. /// This handles forward references like `x: "int"` and string literals in Literal types. fn serialize_string_type(ser: &mut Serializer, string_value: &str, range: TextRange) { // Try to parse the string as a type expression, similar to fastparse.py's parse_type_string // We wrap it in parentheses to parse it as an expression let wrapped = format!("({})", string_value); let parse_result = parse_unchecked(&wrapped, ParseOptions::from(Mode::Expression)); // Check if parsing succeeded and we got a valid type expression if parse_result.errors().is_empty() { // Extract the expression from the parsed module if let ast::Mod::Expression(expr_mod) = parse_result.into_syntax() { let mut expr = expr_mod.body; // Check if this is a type expression that should have original_str_expr set // (UnboundType or UnionType in mypy terms, which are Name/Attribute/Subscript or BinOp with | in AST) match expr.as_mut() { ast::Expr::Name(e) => { serialize_simple_unbound_type( ser, e.id.as_bytes(), Some(string_value), Some("builtins.str"), ); ser.write_location(range); ser.write_end_tag(); return; } ast::Expr::Attribute(_e) => { serialize_attribute_type( ser, expr.as_ref(), Some(string_value), Some("builtins.str"), ); ser.write_location(range); ser.write_end_tag(); return; } ast::Expr::Subscript(e) => { // Move nested types to correct location ast::relocate::relocate_expr(&mut e.slice, range); serialize_subscript_type(ser, &e, Some(string_value), Some("builtins.str")); ser.write_location(range); ser.write_end_tag(); return; } ast::Expr::BinOp(binop) if matches!(binop.op, ast::Operator::BitOr) => { // Move nested types to correct location ast::relocate::relocate_expr(&mut binop.left, range); ast::relocate::relocate_expr(&mut binop.right, range); // Serialize as UnionType with original_str_expr and original_str_fallback serialize_union_type( ser, binop, range, Some(string_value), Some("builtins.str"), ); return; } ast::Expr::NoneLiteral(_) => { serialize_simple_unbound_type( ser, b"None", Some(string_value), Some("builtins.str"), ); ser.write_location(range); ser.write_end_tag(); return; } _ => { // Other expressions - serialize as RawExpressionType } } } } // If parsing failed or resulted in non-type expression, serialize as RawExpressionType ser.write_tag(TAG_RAW_EXPRESSION_TYPE); ser.write_bytes(b"builtins.str"); ser.write_bytes(string_value.as_bytes()); ser.write_location(range); ser.write_end_tag(); } /// Serialize a union type (BinOp with |) with optional original_str_expr and original_str_fallback. fn serialize_union_type( ser: &mut Serializer, binop: &ast::ExprBinOp, range: TextRange, original_str_expr: Option<&str>, original_str_fallback: Option<&str>, ) { ser.write_tag(TAG_UNION_TYPE); // Serialize items list with exactly two items (left and right) ser.write_tag(TAG_LIST_GEN); ser.write_int(2); serialize_type(ser, &binop.left); serialize_type(ser, &binop.right); // uses_pep604_syntax = true (using | operator) ser.write_bool(true); // Write optional original_str_expr if let Some(s) = original_str_expr { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } // Write optional original_str_fallback if let Some(s) = original_str_fallback { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } ser.write_bool(ser.is_evaluated); ser.write_location(range); ser.write_end_tag(); } /// Serialize an Attribute type (e.g., foo.bar.Baz) with optional original_str_expr. fn serialize_attribute_type( ser: &mut Serializer, expr: &ast::Expr, original_str_expr: Option<&str>, original_str_fallback: Option<&str>, ) { let mut v = Vec::new(); if !get_qualified_type_name(&mut v, expr) { // Invalid expression for qualified name - serialize as invalid type serialize_invalid_type(ser, None, original_str_expr, original_str_fallback); return; } ser.write_tag(TAG_UNBOUND_TYPE); ser.write_bytes(&v); ser.write_tag(TAG_LIST_GEN); ser.write_int(0); // Write empty_tuple_index ser.write_bool(false); // Write optional original_str_expr if let Some(s) = original_str_expr { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } // Write optional original_str_fallback if let Some(s) = original_str_fallback { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } } /// Serialize a Subscript type (e.g., List[int], Dict[str, int]) with optional original_str_expr. fn serialize_subscript_type( ser: &mut Serializer, subscript: &ast::ExprSubscript, original_str_expr: Option<&str>, original_str_fallback: Option<&str>, ) { let mut v = Vec::new(); if !get_qualified_type_name(&mut v, &subscript.value) { // Invalid expression for qualified name - serialize as invalid type serialize_invalid_type(ser, None, original_str_expr, original_str_fallback); return; } ser.write_tag(TAG_UNBOUND_TYPE); ser.write_bytes(&v); ser.write_tag(TAG_LIST_GEN); match subscript.slice.as_ref() { ast::Expr::Tuple(t) => { ser.write_usize(t.len()); for item in &t.elts { serialize_type(ser, item); } // Write empty_tuple_index. ser.write_bool(t.len() == 0); } _ => { ser.write_int(1); serialize_type(ser, &subscript.slice); ser.write_bool(false); } } // Write optional original_str_expr if let Some(s) = original_str_expr { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } // Write optional original_str_fallback if let Some(s) = original_str_fallback { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } } /// Serialize a simple unbound type (just a name like `int` or `None`). fn serialize_simple_unbound_type( ser: &mut Serializer, name: &[u8], original_str_expr: Option<&str>, original_str_fallback: Option<&str>, ) { ser.write_tag(TAG_UNBOUND_TYPE); ser.write_bytes(name); ser.write_tag(TAG_LIST_GEN); ser.write_int(0); // Write empty_tuple_index ser.write_bool(false); // Write optional original_str_expr if let Some(s) = original_str_expr { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } // Write optional original_str_fallback if let Some(s) = original_str_fallback { ser.write_bytes(s.as_bytes()); } else { ser.write_tag(TAG_LITERAL_NONE); } } /// Helper to build a qualified type name from nested attributes (e.g., `foo.bar.Baz`). /// Returns true if successful, false if the expression is not a valid qualified name. fn get_qualified_type_name(v: &mut Vec, e: &ast::Expr) -> bool { match e { ast::Expr::Name(e) => { v.extend_from_slice(e.id.as_bytes()); true } ast::Expr::Attribute(e) => { if get_qualified_type_name(v, &e.value) { v.extend_from_slice(b"."); v.extend_from_slice(e.attr.as_bytes()); true } else { false } } _ => { // Not a valid qualified name - caller should handle this false } } } /// Extract an integer literal value from a type expression, handling both /// positive literals (NumberLiteral) and negative literals (UnaryOp(USub, NumberLiteral)). fn extract_int_literal_value(expr: &ast::Expr) -> Option { match expr { ast::Expr::NumberLiteral(n) => { if let Number::Int(int_val) = &n.value { int_val.as_i64() } else { None } } ast::Expr::UnaryOp(e) if matches!(e.op, ast::UnaryOp::USub) => { // Recursively extract value from operand and negate it extract_int_literal_value(&e.operand).map(|v| -v) } _ => None, } } /// Build import flags from current serializer state and the `lazy` modifier of the statement fn make_import_flags(ser: &Serializer, is_lazy: bool) -> u8 { (if !ser.in_function { IMPORT_FLAG_TOP_LEVEL } else { 0 }) | (if ser.current_unreachable { IMPORT_FLAG_UNREACHABLE } else { 0 }) | (if ser.current_mypy_only { IMPORT_FLAG_MYPY_ONLY } else { 0 }) | (if is_lazy { IMPORT_FLAG_LAZY } else { 0 }) } /// Serialize a list of import statements to bytes. /// /// # Arguments /// /// * `imports` - List of import statements to serialize /// * `text` - Source text (used for creating LineIndex to serialize ranges) /// * `line_index` - Optional pre-computed LineIndex (if None, will be computed from text) /// * `is_all_ascii` - Optional pre-computed ASCII flag (if None, will be computed from text) /// * `lines_with_non_ascii` - Optional pre-computed per-line non-ASCII flags (if None, will be computed from text) /// /// # Returns /// /// Serialized bytes representing the imports pub(crate) fn serialize_imports( imports: &[ImportStatement], text: &str, line_index: Option, is_all_ascii: Option, lines_with_non_ascii: Option>, ) -> Vec { let line_index = line_index.unwrap_or_else(|| LineIndex::from_source_text(text)); let is_all_ascii = is_all_ascii.unwrap_or_else(|| text.is_ascii()); let lines_with_non_ascii = lines_with_non_ascii.unwrap_or_else(|| { if is_all_ascii { Vec::new() } else { text.lines().map(|line| !line.is_ascii()).collect() } }); let mut ser = Serializer { bytes: Vec::new(), imports: Vec::new(), line_index, tokens: None, text, skip_function_bodies: false, in_class: false, in_function: false, is_all_ascii, lines_with_non_ascii, type_comments: HashMap::new(), options: Options::default(), current_unreachable: false, current_mypy_only: false, top_level_getattr: false, is_evaluated: true, extra_errors: Vec::new(), skipped_lines: HashSet::new(), uses_template_strings: false, has_surrogates: false, location_override: None, }; // Write list of imports ser.write_tag(TAG_LIST_GEN); ser.write_usize(imports.len()); for import in imports { match import { ImportStatement::Import { name, relative, as_name, range, flags, } => { ser.write_tag(TAG_IMPORT_METADATA); ser.write_bytes(name.as_bytes()); ser.write_tagged_int(*relative as i64); if let Some(asname) = as_name { ser.write_bool(true); ser.write_bytes(asname.as_bytes()); } else { ser.write_bool(false); } ser.write_location(*range); ser.write_tagged_int(*flags as i64); } ImportStatement::ImportFrom { module, relative, names, range, flags, } => { ser.write_tag(TAG_IMPORTFROM_METADATA); ser.write_bytes(module.as_bytes()); ser.write_tagged_int(*relative as i64); // Write list of (name, as_name) tuples ser.write_tag(TAG_LIST_GEN); ser.write_usize(names.len()); for (name, as_name) in names { ser.write_bytes(name.as_bytes()); if let Some(asname) = as_name { ser.write_bool(true); ser.write_bytes(asname.as_bytes()); } else { ser.write_bool(false); } } ser.write_location(*range); ser.write_tagged_int(*flags as i64); } ImportStatement::ImportAll { module, relative, range, flags, } => { ser.write_tag(TAG_IMPORTALL_METADATA); ser.write_bytes(module.as_bytes()); ser.write_tagged_int(*relative as i64); ser.write_location(*range); ser.write_tagged_int(*flags as i64); } } } ser.bytes } #[cfg(test)] mod tests { use super::*; fn int_val(x: i64) -> u8 { return ((x - MIN_SHORT_INT) << 1) as u8; } fn parse_expr_for_test(expr: &str) -> ast::Expr { let parsed = parse_unchecked(expr, ParseOptions::from(Mode::Expression)); assert!( parsed.errors().is_empty(), "failed to parse test expression: {expr}" ); let ast::Mod::Expression(expr_mod) = parsed.into_syntax() else { panic!("expected expression AST for test input: {expr}"); }; *expr_mod.body } fn analyze_if_chain(condition_exprs: &[&str]) -> (Vec<(bool, bool)>, (bool, bool)) { let options = Options::default(); let mut analyzer = IfReachabilityAnalyzer::new(&options); let mut condition_flags = Vec::with_capacity(condition_exprs.len()); for expr in condition_exprs { let parsed = parse_expr_for_test(expr); condition_flags.push(analyzer.condition_flags(&parsed)); } let else_flags = analyzer.else_flags(); (condition_flags, else_flags) } fn make_ser<'a>(text: &'a str) -> Serializer<'a> { let index = LineIndex::from_source_text(text); let is_all_ascii = text.is_ascii(); let lines_with_non_ascii = if is_all_ascii { Vec::new() } else { text.lines().map(|line| !line.is_ascii()).collect() }; Serializer { bytes: Vec::new(), imports: Vec::new(), line_index: index, tokens: None, text, skip_function_bodies: false, in_class: false, in_function: false, is_all_ascii, lines_with_non_ascii, type_comments: HashMap::new(), options: Options::default(), current_unreachable: false, current_mypy_only: false, top_level_getattr: false, is_evaluated: true, extra_errors: Vec::new(), skipped_lines: HashSet::new(), uses_template_strings: false, has_surrogates: false, location_override: None, } } #[test] fn test_if_reachability_analyzer_flags() { struct Case { name: &'static str, conditions: &'static [&'static str], expected_condition_flags: &'static [(bool, bool)], expected_else_flags: (bool, bool), } let cases = [ Case { name: "all_unknown", conditions: &["x", "y"], expected_condition_flags: &[(false, false), (false, false)], expected_else_flags: (false, false), }, Case { name: "always_true_makes_tail_unreachable", conditions: &["x", "PY3", "z"], expected_condition_flags: &[(false, false), (false, false), (true, false)], expected_else_flags: (true, false), }, Case { name: "mypy_true_is_mypy_only_then_closes_tail", conditions: &["MYPY", "z"], expected_condition_flags: &[(false, true), (true, false)], expected_else_flags: (true, false), }, Case { name: "mypy_false_makes_else_mypy_only", conditions: &["x", "not MYPY"], expected_condition_flags: &[(false, false), (true, false)], expected_else_flags: (false, true), }, ]; for case in cases { let (condition_flags, else_flags) = analyze_if_chain(case.conditions); assert_eq!( condition_flags.as_slice(), case.expected_condition_flags, "condition flags mismatch for {}", case.name ); assert_eq!( else_flags, case.expected_else_flags, "else flags mismatch for {}", case.name ); } } #[test] fn test_write_short_int() { for x in [-10, -1, 0, 1, 117] { let mut ser = make_ser(""); ser.write_int(x); assert_eq!(ser.bytes, &[((x - MIN_SHORT_INT) << 1) as u8]); } } #[test] fn test_write_2_byte_int() { let mut ser = make_ser(""); ser.write_int(118); assert_eq!(ser.bytes, &[105, 3]); let mut ser = make_ser(""); ser.write_int(-11); assert_eq!(ser.bytes, &[101, 1]); let mut ser = make_ser(""); ser.write_int(-100); assert_eq!(ser.bytes, &[1, 0]); let mut ser = make_ser(""); ser.write_int(16283); assert_eq!(ser.bytes, &[253, 255]); } #[test] fn test_write_4_byte_int() { let mut ser = make_ser(""); ser.write_int(-101); assert_eq!(ser.bytes, &[91, 53, 1, 0]); let mut ser = make_ser(""); ser.write_int(16284); assert_eq!(ser.bytes, &[99, 53, 3, 0]); let mut ser = make_ser(""); ser.write_int(-10000); assert_eq!(ser.bytes, &[3, 0, 0, 0]); let mut ser = make_ser(""); ser.write_int(536860911); assert_eq!(ser.bytes, &[251, 255, 255, 255]); } #[test] fn test_write_long_int() { let mut ser = make_ser(""); ser.write_int(-10001); assert_eq!(ser.bytes, &[15, 30, 17, 39]); let mut ser = make_ser(""); ser.write_int(536860912); assert_eq!(ser.bytes, &[15, 36, 240, 216, 255, 31]); } #[test] fn test_unicode_support() { // Test that we can parse and serialize files with Unicode characters let text = "# Comment with 中文\ndef привет():\n x = \"🎉\"\n"; let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); let mut ser = make_ser(text); ser.tokens = Some(parsed.tokens()); // Should not panic ast.serialize(&mut ser); // Verify that is_all_ascii is correctly set assert!(!ser.is_all_ascii); // Verify that lines_with_non_ascii is correctly populated assert_eq!(ser.lines_with_non_ascii.len(), 3); assert!(ser.lines_with_non_ascii[0]); // Line with Chinese assert!(ser.lines_with_non_ascii[1]); // Line with Cyrillic assert!(ser.lines_with_non_ascii[2]); // Line with emoji } #[test] fn test_mixed_ascii_unicode() { // Test file with some ASCII and some Unicode lines let text = "# ASCII comment\ndef hello():\n x = \"мир\"\n y = 42\n"; let ser = make_ser(text); assert!(!ser.is_all_ascii); assert_eq!(ser.lines_with_non_ascii.len(), 4); assert!(!ser.lines_with_non_ascii[0]); // ASCII line assert!(!ser.lines_with_non_ascii[1]); // ASCII line assert!(ser.lines_with_non_ascii[2]); // Unicode line assert!(!ser.lines_with_non_ascii[3]); // ASCII line } #[test] fn test_all_ascii_optimization() { // Test that all-ASCII files use the optimized path let text = "def hello():\n return 42\n"; let ser = make_ser(text); assert!(ser.is_all_ascii); assert!(ser.lines_with_non_ascii.is_empty()); // No per-line tracking } #[test] fn test_syntax_error_empty_func() { // Test that we do not panic on invalid function definition. let text = "def hello()\n pass\n"; let mut ser = make_ser(text); let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); // Should not panic ast.serialize(&mut ser); // Syntax error is reported normally assert!(ser.extra_errors.is_empty()); } #[test] fn test_syntax_error_empty_func_2() { // Same as above, but after a valid function. let text = "def ok():\n pass\ndef hello()\n pass\n"; let mut ser = make_ser(text); let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); // Should not panic ast.serialize(&mut ser); // Syntax error is reported normally assert!(ser.extra_errors.is_empty()); } #[test] fn test_syntax_error_broken_args() { // Test that we do not panic on invalid function arguments. let source = "def f(x, (y, z)): pass\n"; let path = write_temp_py("test_source", source); // Simply check that we do not panic let _ = serialize_python_file(&path, None, false, Options::default()).unwrap(); let _ = std::fs::remove_file(&path); } #[test] fn test_syntax_error_broken_args_2() { // Same as above, but after a valid function. let source = "def ok(x): pass\ndef f(x, (y, z)): pass\n"; let path = write_temp_py("test_source", source); // Simply check that we do not panic let _ = serialize_python_file(&path, None, false, Options::default()).unwrap(); let _ = std::fs::remove_file(&path); } #[test] fn test_has_surrogate_positive() { let text = "print('\\ud800')\n"; let mut ser = make_ser(text); let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); ast.serialize(&mut ser); assert!(ser.has_surrogates); } #[test] fn test_has_surrogate_reset() { let text = "print('\\ud800')\nprint('ok')\n"; let mut ser = make_ser(text); let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); ast.serialize(&mut ser); assert!(!ser.has_surrogates); } #[test] fn test_global_ignore_positive() { let source = "# type: ignore\nsomething = else\n"; let path = write_temp_py("test_source", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); // Check that we serialize empty module. assert_eq!(result.0, &[TAG_LITERAL_INT, int_val(0)]); let _ = std::fs::remove_file(&path); } #[test] fn test_global_mypy_ignore_positive() { let source = "# mypy: ignore\nsomething = else\n"; let path = write_temp_py("test_source", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); // Check that we serialize empty module. assert_eq!(result.0, &[TAG_LITERAL_INT, int_val(0)]); let _ = std::fs::remove_file(&path); } #[test] fn test_global_ignore_negative() { let source = "# something: else # type: ignore\nsomething = else\n"; let path = write_temp_py("test_source", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); // Check that we serialize some non-trivial bytes. assert!(result.0.len() > 40); let _ = std::fs::remove_file(&path); } #[test] fn test_global_mypy_ignore_negative() { let source = "# mypy: ignore *some* errors\nsomething = else\n"; let path = write_temp_py("test_source", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); // Check that we serialize some non-trivial bytes. assert!(result.0.len() > 40); let _ = std::fs::remove_file(&path); } #[test] fn test_global_type_ignore_deletes_mypy_ignores() { let source = "# type: ignore\nsomething = 1 # mypy: ignore\n"; let path = write_temp_py("test_source", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); // Check that there are no mypy ignores. assert!(result.3.is_empty()); let _ = std::fs::remove_file(&path); } #[test] fn test_multiple_type_comments_errors() { let text = "x = 1 # type: int # type: str\n"; let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let line_index = LineIndex::from_source_text(text); let (_, _, _, _, syntax_errors) = extract_type_comments_and_ignores( parsed.tokens(), text, &line_index, &Options::default(), ); assert_eq!(syntax_errors.iter().collect::>().len(), 1); } #[test] fn test_multiple_type_ignores_errors() { let text = "x = 1 # type: ignore[foo] # type: ignore[bar]\n"; let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let line_index = LineIndex::from_source_text(text); let (_, _, _, _, syntax_errors) = extract_type_comments_and_ignores( parsed.tokens(), text, &line_index, &Options::default(), ); assert_eq!(syntax_errors.len(), 1); } #[test] fn test_multiple_mypy_ignores_errors() { let text = "x = 1 # mypy: ignore[foo] # mypy: ignore[bar]\n"; let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let line_index = LineIndex::from_source_text(text); let (_, _, _, _, syntax_errors) = extract_type_comments_and_ignores( parsed.tokens(), text, &line_index, &Options::default(), ); assert_eq!(syntax_errors.len(), 1); } #[test] fn test_unicode_with_crlf_line_endings() { // Test that Unicode handling works correctly with Windows (CRLF) line endings let text = "# Comment with 中文\r\ndef привет():\r\n x = \"🎉\"\r\n"; let opt = ParseOptions::from(PySourceType::Python); let parsed = parse_unchecked(text, opt); let ast = parsed.syntax(); let mut ser = make_ser(text); ser.tokens = Some(parsed.tokens()); // Should not panic with CRLF line endings ast.serialize(&mut ser); // Verify that is_all_ascii is correctly set assert!(!ser.is_all_ascii); // Verify that lines_with_non_ascii is correctly populated assert_eq!(ser.lines_with_non_ascii.len(), 3); assert!(ser.lines_with_non_ascii[0]); // Line with Chinese assert!(ser.lines_with_non_ascii[1]); // Line with Cyrillic assert!(ser.lines_with_non_ascii[2]); // Line with emoji } #[test] fn test_mixed_crlf_and_lf() { // Test files with mixed line endings (both CRLF and LF) let text = "# ASCII with CRLF\r\ndef hello():\n x = \"мир\"\r\n y = 42\n"; let ser = make_ser(text); assert!(!ser.is_all_ascii); assert_eq!(ser.lines_with_non_ascii.len(), 4); assert!(!ser.lines_with_non_ascii[0]); // ASCII line with CRLF assert!(!ser.lines_with_non_ascii[1]); // ASCII line with LF assert!(ser.lines_with_non_ascii[2]); // Unicode line with CRLF assert!(!ser.lines_with_non_ascii[3]); // ASCII line with LF } #[test] fn print_hello() { let opt = ParseOptions::from(PySourceType::Python); let text = "print('hello')"; let ast = parse_unchecked(text, opt).into_syntax(); let mut ser = make_ser(text); ast.serialize(&mut ser); let _ = ser; // TODO: drop when not needed let expected = &[ TAG_LITERAL_INT, int_val(1), TAG_EXPR_STMT, TAG_CALL_EXPR, TAG_NAME_EXPR, TAG_LITERAL_STR, int_val(5), b'p', b'r', b'i', b'n', b't', TAG_LOCATION, int_val(1), int_val(0), int_val(0), int_val(5), TAG_END, TAG_LIST_GEN, int_val(1), TAG_STR_EXPR, TAG_LITERAL_STR, int_val(5), b'h', b'e', b'l', b'l', b'o', 0, // no surrogates TAG_LOCATION, int_val(1), int_val(6), int_val(0), int_val(7), TAG_END, TAG_LIST_INT, int_val(1), int_val(0), // ARG_POS TAG_LIST_GEN, int_val(1), TAG_LITERAL_NONE, TAG_LOCATION, int_val(1), int_val(0), int_val(0), int_val(14), TAG_END, TAG_END, ]; assert_eq!(ser.bytes, expected); } #[test] fn test_serialize_single_import() { // Create a simple import: "import os" at line 1, columns 0-9 let text = "import os\n"; let imports = vec![ImportStatement::Import { name: "os".to_string(), relative: 0, as_name: None, range: TextRange::new(0.into(), 9.into()), flags: IMPORT_FLAG_TOP_LEVEL, }]; let bytes = serialize_imports(&imports, text, None, None, None); // Expected byte sequence: // TAG_LIST_GEN (20) + length (1) // TAG_IMPORT_METADATA (226) // name: TAG_LITERAL_STR (4) + length (2) + "os" // relative: TAG_LITERAL_INT (3) + int_val(0) // as_name: TAG_LITERAL_FALSE (0) // range: TAG_LOCATION (152) + line (1) + col (0) + line_diff (0) + col_diff (9) // Note: write_location writes start line, start col, line difference, col difference // flags: TAG_LITERAL_INT (3) + int_val(1) - IMPORT_FLAG_TOP_LEVEL set let expected = vec![ TAG_LIST_GEN, int_val(1), // list length = 1 TAG_IMPORT_METADATA, TAG_LITERAL_STR, int_val(2), // "os" length b'o', b's', TAG_LITERAL_INT, int_val(0), // relative = 0 TAG_LITERAL_FALSE, // no as_name TAG_LOCATION, int_val(1), // start line 1 int_val(0), // start column 0 (0-based) int_val(0), // line difference (same line) int_val(9), // column difference (9 chars) TAG_LITERAL_INT, // flags tag int_val(1), // flags: IMPORT_FLAG_TOP_LEVEL (bit 0 set) ]; assert_eq!(bytes, expected); } /// Serialize `text` and return the import flags of each encountered import statement. fn import_flags(text: &str) -> Vec { let ast = parse_unchecked(text, ParseOptions::from(PySourceType::Python)).into_syntax(); let mut ser = make_ser(text); ast.serialize(&mut ser); ser.imports .iter() .map(|import| match import { ImportStatement::Import { flags, .. } | ImportStatement::ImportFrom { flags, .. } | ImportStatement::ImportAll { flags, .. } => *flags, }) .collect() } #[test] fn test_lazy_import_flag() { // Lazy imports (PEP 810) set IMPORT_FLAG_LAZY. let lazy = IMPORT_FLAG_TOP_LEVEL | IMPORT_FLAG_LAZY; assert_eq!(import_flags("lazy import foo\n"), [lazy]); assert_eq!(import_flags("lazy import foo as bar\n"), [lazy]); assert_eq!(import_flags("lazy import foo, bar\n"), [lazy, lazy]); assert_eq!(import_flags("lazy from foo import bar\n"), [lazy]); assert_eq!(import_flags("lazy from foo import bar as baz\n"), [lazy]); assert_eq!(import_flags("lazy from . import foo\n"), [lazy]); // 'lazy from foo import *' is invalid, but we still serialize the flag. assert_eq!(import_flags("lazy from foo import *\n"), [lazy]); // Regular imports don't set the flag. let plain = IMPORT_FLAG_TOP_LEVEL; assert_eq!(import_flags("import foo\n"), [plain]); assert_eq!(import_flags("from foo import bar\n"), [plain]); assert_eq!(import_flags("from foo import *\n"), [plain]); // 'lazy' is a soft keyword, so it can still be used as a name. assert_eq!(import_flags("import foo as lazy\n"), [plain]); assert_eq!(import_flags("from lazy import foo\n"), [plain]); } fn extract_mypy_comments(source: &str) -> Vec<(usize, String)> { let parsed = parse_unchecked(source, ParseOptions::from(PySourceType::Python)); let line_index = LineIndex::from_source_text(source); let (_, _, _, mypy_comments, _) = extract_type_comments_and_ignores( parsed.tokens(), source, &line_index, &Options::default(), ); mypy_comments } #[test] fn test_mypy_comment_config_override() { let source = indoc::indoc! {" # mypy: disallow-untyped-defs x = 1 "}; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![(1, "disallow-untyped-defs".to_string())]); } #[test] fn test_mypy_comment_multiple() { let source = indoc::indoc! {" # mypy: disallow-untyped-defs x = 1 # mypy: warn-return-any "}; let comments = extract_mypy_comments(source); assert_eq!( comments, vec![ (1, "disallow-untyped-defs".to_string()), (3, "warn-return-any".to_string()), ] ); } #[test] fn test_mypy_comment_not_at_start_of_line() { // Inline mypy comments after code should not be picked up let source = "x = 1 # mypy: disallow-untyped-defs\n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); } #[test] fn test_mypy_comment_indented() { // Indented mypy comments should not be picked up let source = indoc::indoc! {" if True: # mypy: disallow-untyped-defs pass "}; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); } #[test] fn test_mypy_comment_ignore_not_included() { // "# mypy: ignore" is handled separately via mypy_ignore_lines let source = "# mypy: ignore[attr-defined]\n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); let source = "# mypy: ignore\n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); // Extra whitespace around "ignore" let source = "# mypy: ignore \n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); let source = "# mypy: ignore[arg-type] \n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); } #[test] fn test_mypy_comment_ignore_prefix_config() { // Config options starting with "ignore" should not be filtered out let source = "# mypy: ignore-missing-imports\n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![(1, "ignore-missing-imports".to_string())]); } #[test] fn test_mypy_comment_none() { let source = "x = 1\n"; let comments = extract_mypy_comments(source); assert_eq!(comments, vec![]); } /// Write source to a temporary .py file and return its path. /// The file is named using `label` and a timestamp to avoid collisions. fn write_temp_py(label: &str, source: &str) -> std::path::PathBuf { let ts = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); let path = std::env::temp_dir().join(format!("{label}_{ts}.py")); std::fs::write(&path, source).unwrap(); path } #[test] fn test_inline_always_true_affects_serialization() { // Verify that "# mypy: always-true=FLAG" in the source has the same // effect on serialization as passing always_true=["FLAG"] via options. let source_with_comment = indoc::indoc! {" # mypy: always-true=FLAG if FLAG: import a else: import b "}; // Same structure but with a plain comment so line numbers match. let source_without_comment = indoc::indoc! {" # just a regular comment if FLAG: import a else: import b "}; let path1 = write_temp_py("test_inline_at_1", source_with_comment); let path2 = write_temp_py("test_inline_at_2", source_without_comment); // Parse with inline comment, no caller-provided always_true let result_inline = serialize_python_file(&path1, None, false, Options::default()).unwrap(); // Parse without comment, but pass always_true via options let options_with_flag = Options::new( (3, 12), "linux".to_string(), vec!["FLAG".to_string()], vec![], 5, ); let result_option = serialize_python_file(&path2, None, false, options_with_flag).unwrap(); let _ = std::fs::remove_file(&path1); let _ = std::fs::remove_file(&path2); // The AST bytes should be identical — the inline comment had the // same effect as the caller-provided option. assert_eq!(result_inline.0, result_option.0, "AST bytes differ"); // Import bytes should also match (same unreachability flags). assert_eq!(result_inline.4, result_option.4, "import bytes differ"); } #[test] fn test_source_hash() { let source = "x = 1\n"; let path = write_temp_py("test_source_hash", source); let result = serialize_python_file(&path, None, false, Options::default()).unwrap(); let _ = std::fs::remove_file(&path); let hash_hex = &result.7; assert_eq!(hash_hex, "e139f73e34322031189110afc1939eb1877a8954"); } } ast_serialize-0.13.1/src/type_comment.rs000064400000000000000000000573101046102023000152120ustar00//! Parse type comments from Python source code use ruff_python_ast::token::TokenKind; use ruff_python_parser; use ruff_python_parser::{Mode, ParseOptions, parse_unchecked}; use ruff_text_size::Ranged; use std::char; /// Individual type comment found in a comment line #[derive(Debug, Clone, PartialEq, Eq)] pub enum TypeComment { /// A type: ignore with optional error codes TypeIgnore(Vec), /// A mypy: ignore with optional error codes MypyIgnore(Vec), /// A type annotation (e.g., `list[int]`) TypeAnnotation(String), /// An invalid type ignore InvalidIgnore(bool), } fn parse_type_comments(comment: &str) -> Option> { parse_type_comments_full(comment, false) } /// Parse a type comment and extract all parts (type annotation and/or type: ignore). /// /// # Arguments /// /// * `comment` - The comment string to parse (must include the leading `#`) /// /// # Returns /// /// - `Some(Vec)` with one or more parts if valid type comment(s) found /// - `None` if it's not a type comment /// /// # Examples /// /// ``` /// use mypy_parser::type_comment::{parse_type_comments_full, TypeComment}; /// /// // Pure type: ignore /// let result = parse_type_comments_full("# type: ignore").unwrap(); /// assert_eq!(result.len(), 1); /// /// // Type annotation with type: ignore on same line /// let result = parse_type_comments_full("# type: int # type: ignore[arg-type]").unwrap(); /// assert_eq!(result.len(), 2); // Both annotation and ignore /// ``` pub fn parse_type_comments_full(comment: &str, skip_commented: bool) -> Option> { if !comment.starts_with('#') { // Guard against some possible parse error recovery return None; } let mut parts = Vec::new(); let mut ignore_next = false; for part in comment.strip_prefix('#').unwrap().split("#") { // Special case: ignore components prefixed with two hashes. // This allows to ignore a type ignore, see test_commented_out_comment(). if part.trim() == "" { ignore_next = true; continue; } if ignore_next { ignore_next = false; continue; } if let Some(parsed) = parse_comment_part(part) { parts.push(parsed); } else if skip_commented { break; } } if parts.is_empty() { None } else { Some(parts) } } pub(crate) fn parse_comment_part(part: &str) -> Option { let trimmed = part.trim(); let mypy_comment = trimmed.starts_with("mypy:"); // Check if it starts with "type:" if !trimmed.starts_with("type:") && !mypy_comment { return None; } // Get the part after "type:" or "mypy:" let after_type = trimmed["type:".len()..].trim_start(); // Check if it's a type: ignore comment (without type annotation) if after_type.starts_with("ignore") { // Check if "ignore" is followed by whitespace, '[', or end of string let after_ignore = &after_type["ignore".len()..]; if after_ignore.is_empty() || after_ignore.starts_with(|c: char| c.is_whitespace() || c == '[') { // Parse as type: ignore let error_codes = parse_error_codes(after_ignore); if error_codes.is_none() { return Some(TypeComment::InvalidIgnore(mypy_comment)); } if mypy_comment { return Some(TypeComment::MypyIgnore(error_codes.unwrap())); } return Some(TypeComment::TypeIgnore(error_codes.unwrap())); } } // Anything like `mypy: enable` etc. doesn't have any special meaning in this context. // Note we do not flag it as an invalid ignore, since then some mypy inline configs // may cause spurious errors. if mypy_comment { return None; } Some(TypeComment::TypeAnnotation(after_type.to_string())) } fn parse_error_codes(after_ignore: &str) -> Option> { let mut after_ignore_trimmed = after_ignore.trim_start(); if let Some(hash_pos) = after_ignore_trimmed.find('#') { after_ignore_trimmed = &after_ignore_trimmed[..hash_pos] } after_ignore_trimmed = after_ignore_trimmed.trim_end(); // Check if there are error codes in brackets if after_ignore_trimmed.starts_with('[') { if !after_ignore_trimmed.ends_with(']') { return None; } // Extract the content between brackets let codes_str = &after_ignore_trimmed[1..after_ignore_trimmed.len() - 1]; // Split by comma and collect error codes let error_codes: Vec = codes_str .split(',') .map(|s| s.trim().to_string()) .filter(|s| !s.is_empty()) .collect(); // Validate error codes syntax for error_code in &error_codes { for char in error_code.chars() { if !char.is_alphanumeric() && char != '_' && char != '-' && char != ':' { return None; } } } return Some(error_codes); } if !after_ignore_trimmed.is_empty() { // Something invalid like `# type: ignore xyz` return None; } // No error codes specified (just "# type: ignore") Some(Vec::new()) } /// Parse a type comment and extract error codes if it contains a type ignore comment. /// /// # Arguments /// /// * `comment` - The comment string to parse (should include the leading `#`) /// /// # Returns /// /// `Some(Vec)` containing error codes if it contains a type ignore comment, /// `None` if it doesn't contain a type ignore comment. /// Error codes are parsed from brackets like `[code1, code2]`. /// Only whitespace is allowed between 'ignore' and '['. /// /// # Examples /// /// ``` /// use mypy_parser::type_comment::parse_type_comment; /// /// assert_eq!(parse_type_comment("# type: ignore"), Some(vec![])); /// assert_eq!(parse_type_comment("# type: ignore[arg-type]"), Some(vec!["arg-type".to_string()])); /// assert_eq!(parse_type_comment("# type: int # type: ignore[override]"), Some(vec!["override".to_string()])); /// assert_eq!(parse_type_comment("# regular comment"), None); /// ``` pub fn parse_type_comment(comment: &str) -> Option> { let parts = parse_type_comments(comment)?; // Find the first Ignore part for part in parts { if let TypeComment::TypeIgnore(codes) = part { return Some(codes); } } None } /// Parse a function type comments like `# type: (list[int], *str) -> None`. /// /// # Arguments /// /// * `comment` - The comment to parse (should *not* include the leading `# type:` part) /// /// # Returns /// /// `Some((Vec, ))` argument types and return type, if comment looks valid. /// `None` otherise. /// /// Note: this function does *not* validate syntactic validity of individual types. pub fn parse_func_type_comment(comment: &str) -> Option<(Vec, String)> { let result = parse_unchecked(comment, ParseOptions::from(Mode::Expression)); let mut tokens = result.tokens().iter_with_context(); let mut arg_types = Vec::new(); // Function type comment must start with `(`. let mut token = tokens.next(); if token?.kind() != TokenKind::Lpar { return None; } // Initialize the argument types loop with empty range. // Use peek() heer and below to handle spaces nicely. let mut arg_start = tokens.peek()?.start(); let mut arg_end = arg_start; let mut star_stripped = false; loop { token = tokens.next(); // If we reach the end before seeing closing `)`, it is invalid type. if token.is_none() { return None; } let token = token.unwrap(); match token.kind() { TokenKind::Comma if tokens.nesting() == 1 => { arg_types.push(comment[arg_start.to_usize()..arg_end.to_usize()].to_string()); // Reset the argument types loop after comma. arg_start = tokens.peek()?.start(); arg_end = arg_start; star_stripped = false; } TokenKind::Star | TokenKind::DoubleStar if tokens.nesting() == 1 => { // Skip no more than two initial stars. if star_stripped { return None; } if arg_start == token.start() { arg_start = tokens.peek()?.start(); arg_end = arg_start; star_stripped = true; } } TokenKind::Rpar if tokens.nesting() == 0 => { if arg_end != arg_start { // This logic will allow trailing comma in argument list. arg_types.push(comment[arg_start.to_usize()..arg_end.to_usize()].to_string()); } break; } _ => { // Common case, advance to next token. arg_end = token.end(); } } } token = tokens.next(); // Token immediately following closing `)` must be `->`. if token?.kind() != TokenKind::Rarrow { return None; } // Put the rest in the return type (may be syntactically invalid). let ret_type = &comment[tokens.next()?.start().to_usize()..]; Some((arg_types, ret_type.to_string())) } #[cfg(test)] mod tests { use super::*; #[test] fn test_type_ignore_basic() { assert_eq!(parse_type_comment("# type: ignore"), Some(vec![])); } #[test] fn test_type_ignore_with_single_code() { assert_eq!( parse_type_comment("# type: ignore[arg-type]"), Some(vec!["arg-type".to_string()]) ); assert_eq!( parse_type_comment("# type: ignore[override]"), Some(vec!["override".to_string()]) ); } #[test] fn test_type_ignore_with_multiple_codes() { assert_eq!( parse_type_comment("# type: ignore[arg-type, override]"), Some(vec!["arg-type".to_string(), "override".to_string()]) ); assert_eq!( parse_type_comment("# type: ignore[name-defined,no-untyped-def]"), Some(vec![ "name-defined".to_string(), "no-untyped-def".to_string() ]) ); } #[test] fn test_type_ignore_with_whitespace() { assert_eq!(parse_type_comment("#type: ignore"), Some(vec![])); assert_eq!(parse_type_comment("# type: ignore"), Some(vec![])); assert_eq!(parse_type_comment("# type: ignore "), Some(vec![])); // Whitespace before bracket is ok assert_eq!( parse_type_comment("# type: ignore [arg-type]"), Some(vec!["arg-type".to_string()]) ); // Whitespace around codes assert_eq!( parse_type_comment("# type: ignore[ arg-type , override ]"), Some(vec!["arg-type".to_string(), "override".to_string()]) ); } #[test] fn test_not_type_ignore() { assert_eq!(parse_type_comment("# regular comment"), None); assert_eq!(parse_type_comment("# TODO: fix this"), None); assert_eq!(parse_type_comment("# type: int"), None); // Non-whitespace between 'ignore' and '[' should fail assert_eq!(parse_type_comment("# type: ignore-[arg-type]"), None); assert_eq!(parse_type_comment("# type: ignorefoo[arg-type]"), None); } #[test] fn test_empty_comment() { assert_eq!(parse_type_comment("#"), None); assert_eq!(parse_type_comment(""), None); } #[test] fn test_commented_out_comment() { assert_eq!(parse_type_comment("## type: ignore"), None); assert_eq!(parse_type_comment("## type: ignore[arg-type]"), None); // Double-hash only deactivates the next directive/pragma, not all of them let result = parse_type_comments("## type: ignore # type: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(s) if s.is_empty())); let result = parse_type_comments("# type: ignore ## type: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(s) if s.is_empty())); } #[test] fn test_empty_part_is_also_special() { assert_eq!(parse_type_comments("# # type: ignore"), None); assert_eq!(parse_type_comments("# # type: ignore[arg-type]"), None); // Double-hash only deactivates the next directive/pragma, not all of them let result = parse_type_comments("# # type: ignore # type: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(s) if s.is_empty())); let result = parse_type_comments("# type: ignore # # type: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(s) if s.is_empty())); } #[test] fn test_skip_commented() { assert_eq!( parse_type_comments_full("# x: str = 1 # type: ignore", true), None ); assert_eq!( parse_type_comments_full("# avoid more # type: ignores", true), None ); } #[test] fn test_empty_error_codes() { // Empty brackets should return empty vec assert_eq!(parse_type_comment("# type: ignore[]"), Some(vec![])); } #[test] fn test_ignore_tight_comment() { assert_eq!(parse_type_comment("# type: ignore# reasons"), Some(vec![])); assert_eq!( parse_type_comment("# type: ignore[foo]# reasons"), Some(vec!["foo".to_string()]) ); } #[test] fn test_invalid_ignore_comment() { assert_eq!(parse_type_comment("# type: ignore foo"), None); assert_eq!(parse_type_comment("# type: ignore["), None); assert_eq!(parse_type_comment("# type: ignore[]]"), None); assert_eq!( parse_type_comment("# type: ignore[only+dashes+allowed]"), None ); } #[test] fn test_type_comment_kind_ignore() { let result = parse_type_comments("# type: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(codes) if codes.is_empty())); let result = parse_type_comments("# type: ignore[arg-type]").unwrap(); assert_eq!(result.len(), 1); assert!( matches!(&result[0], TypeComment::TypeIgnore(codes) if codes == &vec!["arg-type".to_string()]) ); } #[test] fn test_type_comment_kind_mypy_ignore() { let result = parse_type_comments("# mypy: ignore").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::MypyIgnore(codes) if codes.is_empty())); let result = parse_type_comments("# mypy: ignore[arg-type]").unwrap(); assert_eq!(result.len(), 1); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["arg-type".to_string()]) ); let result = parse_type_comments("# mypy: ignore[arg-type] # whatever").unwrap(); assert_eq!(result.len(), 1); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["arg-type".to_string()]) ); } #[test] fn test_type_comment_kind_ignore_mixed() { let result = parse_type_comments("# mypy: ignore[foo] # type: ignore[bar]").unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::TypeIgnore(codes) if codes == &vec!["bar".to_string()]) ); let result = parse_type_comments("# type: ignore[foo] # mypy: ignore[bar]").unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::TypeIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::MypyIgnore(codes) if codes == &vec!["bar".to_string()]) ); } #[test] fn test_type_comment_kind_ignore_mixed_with_suffix() { let result = parse_type_comments("# mypy: ignore[foo] # type: ignore[bar] # whatever").unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::TypeIgnore(codes) if codes == &vec!["bar".to_string()]) ); let result = parse_type_comments("# type: ignore[foo] # mypy: ignore[bar] # whatever").unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::TypeIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::MypyIgnore(codes) if codes == &vec!["bar".to_string()]) ); } #[test] fn test_type_ignore_mixed_order() { let result = parse_type_comments("# other: ignore[hm] # mypy: ignore[foo] # type: ignore[bar]") .unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::TypeIgnore(codes) if codes == &vec!["bar".to_string()]) ); let result = parse_type_comments("# mypy: ignore[foo] # other: ignore[hm] # type: ignore[bar]") .unwrap(); assert_eq!(result.len(), 2); assert!( matches!(&result[0], TypeComment::MypyIgnore(codes) if codes == &vec!["foo".to_string()]) ); assert!( matches!(&result[1], TypeComment::TypeIgnore(codes) if codes == &vec!["bar".to_string()]) ); } #[test] fn test_type_comment_kind_mypy_ignore_with_annotation() { // Type annotation followed by mypy: ignore on the same line let result = parse_type_comments("# type: str # mypy: ignore").unwrap(); assert_eq!(result.len(), 2); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "str")); assert!(matches!(&result[1], TypeComment::MypyIgnore(codes) if codes.is_empty())); let result = parse_type_comments("# type: list[int] # mypy: ignore[arg-type]").unwrap(); assert_eq!(result.len(), 2); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "list[int]")); assert!( matches!(&result[1], TypeComment::MypyIgnore(codes) if codes == &vec!["arg-type".to_string()]) ); } #[test] fn test_type_comment_kind_annotation() { let result = parse_type_comments("# type: int").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "int")); let result = parse_type_comments("# type: list[int]").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "list[int]")); let result = parse_type_comments("# type: Dict[str, int]").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "Dict[str, int]")); } #[test] fn test_type_comment_kind_annotation_with_trailing_comment() { let result = parse_type_comments("# type: int # This is a comment").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "int")); let result = parse_type_comments("# type: list[int] # comment").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "list[int]")); } #[test] fn test_type_comment_kind_annotation_with_type_ignore() { // Type annotation followed by type: ignore on the same line let result = parse_type_comments("# type: str # type: ignore").unwrap(); assert_eq!(result.len(), 2); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "str")); assert!(matches!(&result[1], TypeComment::TypeIgnore(codes) if codes.is_empty())); let result = parse_type_comments("# type: list[int] # type: ignore[arg-type]").unwrap(); assert_eq!(result.len(), 2); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "list[int]")); assert!( matches!(&result[1], TypeComment::TypeIgnore(codes) if codes == &vec!["arg-type".to_string()]) ); } #[test] fn test_type_comment_kind_not_type_comment() { assert_eq!(parse_type_comments("# regular comment"), None); assert_eq!(parse_type_comments("# TODO: fix this"), None); assert_eq!( parse_type_comments("# type:"), // Empty annotation Some(vec![TypeComment::TypeAnnotation("".to_string())]) ); } #[test] fn test_type_comment_kind_whitespace_handling() { let result = parse_type_comments("#type: int").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "int")); let result = parse_type_comments("# type: int ").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeAnnotation(s) if s == "int")); } #[test] fn test_type_ignore_colon_allowed() { let result = parse_type_comments("# type: ignore[mypy:assign-rule_22]").unwrap(); assert_eq!(result.len(), 1); assert!(matches!(&result[0], TypeComment::TypeIgnore(s) if s[0] == "mypy:assign-rule_22")); } #[test] fn test_mypy_is_not_type() { assert_eq!(parse_type_comments("# mypy: ignore-errors"), None); } #[test] fn test_function_type_comments_basics() { let result = parse_func_type_comment("(dict[str, int], *str) -> None"); assert_eq!( Some(( vec!["dict[str, int]".to_string(), "str".to_string()], "None".to_string() )), result ); } #[test] fn test_function_type_comments_spaces() { let result = parse_func_type_comment("( dict[str , int], * str ) -> None"); assert_eq!( Some(( vec!["dict[str , int]".to_string(), "str".to_string()], "None".to_string() )), result ); } #[test] fn test_function_type_comments_trailing_comma() { let result = parse_func_type_comment("(str,) -> None"); assert_eq!(Some((vec!["str".to_string()], "None".to_string())), result); } #[test] fn test_function_type_comments_empty_ok() { let result = parse_func_type_comment("() -> ()"); assert_eq!(Some((vec![], "()".to_string())), result); } #[test] fn test_function_type_comments_empty_bad() { let result = parse_func_type_comment("( , ) -> "); assert_eq!(Some((vec!["".to_string()], "".to_string())), result); } #[test] fn test_function_type_comments_triple_star() { let result = parse_func_type_comment("(***str) -> None"); assert_eq!(None, result); } #[test] fn test_function_type_comments_invalid_multiply_kept() { let result = parse_func_type_comment("(a * b) -> a * b"); assert_eq!( Some((vec!["a * b".to_string()], "a * b".to_string())), result ); } #[test] fn test_function_type_comments_literal_special() { let result = parse_func_type_comment("(Literal[',->']) -> {}"); assert_eq!( Some((vec!["Literal[',->']".to_string()], "{}".to_string())), result ); } } ast_serialize-0.13.1/test_ast_serialize.py000064400000000000000000000016721046102023000156210ustar00#!/usr/bin/env python3 """Smoke test for ast_serialize extension.""" import tempfile import ast_serialize def test_parse_simple_file(): """Test that we can parse a simple Python file.""" # Create a temporary Python file with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f: f.write("print('hello')\n") fname = f.name try: # Parse the file result = ast_serialize.parse(fname) # Verify we got bytes back assert isinstance(result[0], bytes), f"Expected bytes, got {type(result)}" assert len(result[0]) > 0, "Expected non-empty result" print(f"Successfully parsed file: {len(result[0])} bytes") return True except Exception as e: print(f"Test failed: {e}") return False finally: import os os.unlink(fname) if __name__ == '__main__': success = test_parse_simple_file() exit(0 if success else 1)