Skip to content

Refactor large parser modules into smaller components under 400 lines (#223)#259

Open
leynos wants to merge 25 commits into
mainfrom
refactor-parser-modules-d2nyz5
Open

Refactor large parser modules into smaller components under 400 lines (#223)#259
leynos wants to merge 25 commits into
mainfrom
refactor-parser-modules-d2nyz5

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Apr 23, 2026

Summary

  • Refactors large parser modules into smaller, focused components to improve maintainability and testability. No user-facing behavior changes.

Changes

Core Refactor

  • Introduced dedicated S-expression formatting for Expr via a new module: src/parser/ast/expr/sexpr.rs and wired it into the Expr API (Expr::to_sexpr moved from the main file).
  • Moved rule-body expression classification logic into a dedicated module: src/parser/ast/rule/classification.rs and updated rule.rs to delegate classification to it.
  • Extracted Pratt postfix handling into separate modules:
    • src/parser/expression/pratt/delay.rs
    • src/parser/expression/pratt/diff.rs
    • src/parser/expression/pratt/postfix.rs
    • Updated src/parser/expression/pratt.rs to wire in the new modules (mod delay; mod diff; mod postfix).
  • Adjusted module layout and imports to reflect the new structure, reducing file sizes and coupling in core parser files.

Tests and Fixtures

  • Reworked tests to rely on a structured fixtures system for expression parsing:
    • Added new test fixtures module: src/parser/tests/expression/fixtures.rs
    • Split valid expression fixtures into submodules (basic, collections, control_flow, postfix, structured) and wired them into a single expression_cases() entry point
    • Added error fixtures at: src/parser/tests/expression/fixtures/errors.rs
    • Added postfix error fixtures at: src/parser/tests/expression/fixtures/valid/postfix.rs and related fixtures modules
  • Introduced a dedicated sexpr rendering helper for tests (via the new sexpr.rs) and updated tests to use to_sexpr() for compact comparison of parsed structures.

Miscellaneous

  • Minor cleanup to remove inline to_sexpr implementation from Expr and rely on the new sexpr module.
  • Code organization improvements align with the 400-line module guideline mentioned in the task, while preserving functionality.

How to test

  • Run: cargo test
  • Specifically validate that expression parsing tests pass with the new fixtures layout and that S-expression representations render as expected via Expr::to_sexpr().
  • Ensure no public API changes in user-facing behavior; changes are internal restructuring and test shims.

Notes

  • This refactor improves maintainability and testability of parser components by modularizing: S-expression formatting, rule classification, and Pratt postfix handling.
  • If any downstream tooling relies on file locations, please update accordingly; public behavior remains unchanged.

◳ Generated by DevBoxer


ℹ️ Tag @devboxerhub to ask questions and address PR feedback

📎 Task: https://www.devboxer.com/task/4e7f979f-30bc-45b5-844c-4e890802856c

📝 Closes #223

Summary by Sourcery

Refactor parser internals and tests into smaller, focused modules while preserving existing parsing behavior.

Enhancements:

  • Extract rule body classification logic into a dedicated module and delegate from the main rule AST type.
  • Split Pratt parser postfix, diff, and delay handling into separate helper modules to reduce pratt.rs size and coupling.
  • Move S-expression formatting for expressions into its own module to decouple test-oriented rendering from the core AST definition.
  • Introduce a shared expression test fixtures module with structured valid and error cases to simplify and consolidate parser tests.

Tests:

  • Rewrite expression parser tests to consume structured fixtures for literals, control flow, postfix operations, and error conditions, improving reuse and coverage organization.

- Extract rule-body term classification into a dedicated module `rule/classification.rs`.
- Move S-expression formatting for Expr into a separate `expr/sexpr.rs` module.
- Split Pratt parser postfix parsing, delay-postfix, and diff-marker handling into separate files under `expression/pratt/`.
- Remove inline implementations and validations, organizing parser logic into coherent units.
- Revamp expression parser tests to use fixture modules, improving maintainability.

This refactor improves code organization, readability, and test structure without changing external behavior.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

Review Change Stack

Refactor large parser modules into smaller components under 400 lines

This PR completes the planned refactor to split oversized parser modules to satisfy the 400-line local maintainability guideline (closes issue #223). Large parser sources were decomposed into focused submodules to improve readability, single-responsibility separation, and testability while preserving public parsing behaviour.

Key file size reductions (approx.)

  • src/parser/ast/expr.rs: −145 lines (moved S-expression formatting)
  • src/parser/ast/rule.rs: −272 lines (moved rule-body classification)
  • src/parser/expression/pratt.rs: −235 lines (postfix logic extracted)
  • src/parser/tests/expression.rs: −349 lines (refactored to fixtures)

Core refactor details

  • Expression S-expression formatting

    • Extracted Expr::to_sexpr into src/parser/ast/expr/sexpr.rs (with two insta snapshot tests).
    • Removed the inline to_sexpr implementation and its helpers from expr.rs.
  • Rule-body classification

    • Added src/parser/ast/rule/classification.rs to parse/classify rule-body literals (assignment splitting with trimming, for-loop sequencing, aggregation detection for new-style group_by and legacy Aggregate, arity and duplicate-aggregation diagnostics).
    • RuleBodyExpression::parse_term delegates to parse_rule_body_term.
    • Includes unit tests for assignment parsing and duplicate-aggregation reporting; added whitespace-only assignment diagnostic test in src/parser/tests/rules/body_terms.rs.
  • Pratt parser postfix decomposition

    • Split postfix handling into dedicated modules:
      • src/parser/expression/pratt/postfix.rs — dispatcher for (...), [...], ., atom-diff (') and atom-delay (-); argument parsing and exact trailing-comma diagnostics; coordinates pending-diff state across postfix chains.
      • src/parser/expression/pratt/diff.rs — pending diff-marker tracking, application, and validation/error helpers.
      • src/parser/expression/pratt/delay.rs — atom-delay (-) parsing with numeric validation and diagnostics (including u32 bounds checks).
    • Consolidated struct-literal scoped-guard logic into a single with_struct_literal_scope helper used by prior guard methods.
  • Tests and test helpers

    • Replaced rstest inline case tables with fixture-driven tests under src/parser/tests/expression/fixtures (fixtures.rs plus valid/ and errors/ submodules) to improve structure and reuse.
    • Added test helpers atom_diff() and atom_delay() in src/test_util/expressions.rs and re-exported atom_delay via src/test_util/mod.rs.
    • Extended unit and integration tests to cover diff and delay postfix forms, trailing-comma diagnostics/location updates, pending-diff error paths and duplicate-diff diagnostics, and delay numeric-edge cases (including maximum u32 and overflow rejection).

Supporting changes

  • Makefile: detect cargo via command -v with fallback to $(HOME)/.cargo/bin/cargo; markdownlint updated to lint only changed Markdown files relative to origin/main.
  • Cargo.toml: added insta = "1.47.2" (dev-dependency) for snapshot tests.
  • Documentation:
    • Added docs/developers-guide.md documenting parser module boundaries and responsibilities introduced by this refactor (recommended reference for future parser work).
    • Updated docs/roadmap.md, docs/contents.md and docs/parser-implementation-notes.md to reflect the new layout and responsibilities.

Behaviour and API preservation

  • All changes are internal refactors; public parsing APIs and runtime semantics are preserved.
  • Tests were updated/extended to ensure parity: expression parsing, S-expression output, and postfix diff/delay behaviours are exercised.

Review items and follow-ups

  • In-branch reviewer-suggested fixes were applied: classification .trim() fix and whitespace test, atom_diff/atom_delay helpers and fixtures, Pratt scoped-guard consolidation, module docstrings, and added diff/delay test coverage.
  • Out-of-scope follow-ups were opened as issues for later work: developer guide expansion and snapshot/inline-unit-test hygiene (#260, #261, #262).

Reference to design/execplan

  • The PR adds a developer guide (docs/developers-guide.md) documenting the new module boundaries and responsibilities; consult this document for implementation intent and ownership details introduced by the refactor.

Testing guidance

  • Run cargo test to validate expression parsing tests and S-expression snapshot expectations; the new postfix/diff/delay fixtures and helpers are included to exercise the refactored code paths.

Walkthrough

Extract parser responsibilities into focused modules: move S-expression rendering to sexpr.rs, move rule-body term classification to classification.rs, split Pratt postfix parsing into postfix.rs/diff.rs/delay.rs, migrate expression tests into fixture modules, add atom-postfix test helpers, and update Makefile/Cargo/docs.

Changes

Parser refactor cohort

Layer / File(s) Summary
S-expression extraction
src/parser/ast/expr.rs, src/parser/ast/expr/sexpr.rs
Extracted Expr::to_sexpr and all S-expression formatting helpers into sexpr.rs, removed the previous in-file implementation.
Rule-body classification
src/parser/ast/rule.rs, src/parser/ast/rule/classification.rs
Moved rule-body literal parsing/classification into classification.rs; RuleBodyExpression::parse_term now delegates to parse_rule_body_term and aggregation/for-loop/assignment classification moved out of rule.rs.
Pratt postfix, diff and delay
src/parser/expression/pratt.rs, src/parser/expression/pratt/postfix.rs, src/parser/expression/pratt/diff.rs, src/parser/expression/pratt/delay.rs
Split Pratt postfix handling into postfix.rs and helpers diff.rs/delay.rs; implemented pending diff-marker tracking, -<N> delay parsing, and parenthesised-args/bit-slice/dot-access postfix logic; centralised struct-literal guard scope handling.
Tests — fixtures and refactor
src/parser/tests/expression.rs, src/parser/tests/expression/fixtures/*, src/parser/tests/expression/fixtures/valid/*, src/parser/tests/expression/fixtures/errors.rs
Refactored tests to iterate fixture case generators instead of rstest matrices; added many valid/error/postfix fixture modules and aggregator accessors.
Utilities, Makefile, docs & integration tests
src/test_util/*, tests/*, Makefile, Cargo.toml, docs/*
Added atom_diff/atom_delay test helpers and exported atom_delay; adjusted integration test error spans; Makefile now resolves CARGO via command -v with a HOME fallback and restricts markdownlint to changed MD files; added insta dev-dependency and developer guide/roadmap docs.

Sequence Diagram

sequenceDiagram
  participant Pratt as Pratt parser
  participant Postfix as postfix.rs
  participant Diff as diff.rs
  participant Delay as delay.rs
  Pratt->>Postfix: parse_postfix(lhs)
  Postfix->>Diff: handle_diff_marker()
  Postfix->>Delay: parse_delay_postfix()
  Postfix-->>Pratt: final Expr (AtomDiff/AtomDelay applied)
Loading

Possibly related issues

Possibly related PRs

  • leynos/ddlint#197: Overlaps on S-expression rendering of maps and related tests.
  • leynos/netsuke#288: Shares Makefile cargo-resolution changes (command -v + $HOME fallback).
  • leynos/ddlint#262: Related to adding tests and helpers for sexpr/classification/postfix modules.

Suggested labels

Issue

Suggested reviewers

  • codescene-delta-analysis

  • Possibly link leynos/ddlint#262 for test and helper alignment (implements related unit tests and helpers).

  • Possibly link leynos/ddlint#260 for documentation/guide alignment.

Poem

"Split the parser, crisp and bright,
sexprs, diffs and delays alight.
Fixtures march in tidy rows,
Makefile, docs and tests compose.
Ship the change and keep builds light."

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor-parser-modules-d2nyz5

codescene-delta-analysis[bot]

This comment was marked as outdated.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 23, 2026

Reviewer's Guide

Refactors parser internals by extracting S-expression formatting, rule-body classification, and Pratt postfix parsing into dedicated modules, and reworks expression tests around a reusable fixtures system without changing observable parsing behavior.

Sequence diagram for the new rule body term parsing pipeline

sequenceDiagram
    participant RuleBodyExpression
    participant RuleClassificationModule as classification
    participant PatternParser as parse_pattern
    participant ExpressionParser as parse_expression
    participant AggregationLogic as aggregation_tracking
    participant Errors as errors_vec

    RuleBodyExpression->>RuleClassificationModule: parse_rule_body_term(raw, literal_span, first_aggregation_span, errors)
    alt raw contains_assignment
        RuleClassificationModule->>PatternParser: parse_pattern(parts.pattern)
        PatternParser-->>RuleClassificationModule: Result_Pattern_or_errors
        alt pattern_ok
            RuleClassificationModule->>ExpressionParser: parse_expression(parts.value)
            ExpressionParser-->>RuleClassificationModule: Result_Expr_or_errors
            alt value_ok
                RuleClassificationModule-->>RuleBodyExpression: Some_RuleBodyTerm_Assignment
            else value_errors
                RuleClassificationModule->>Errors: append(shifted_errors)
                RuleClassificationModule-->>RuleBodyExpression: None
            end
        else pattern_errors
            RuleClassificationModule->>Errors: append(shifted_errors)
            RuleClassificationModule-->>RuleBodyExpression: None
        end
    else raw_is_expression
        RuleClassificationModule->>ExpressionParser: parse_expression(trimmed_raw)
        ExpressionParser-->>RuleClassificationModule: Result_Expr_or_errors
        alt expr_ok
            RuleClassificationModule->>AggregationLogic: classify_expression(expr, ctx)
            AggregationLogic-->>RuleClassificationModule: Option_RuleBodyTerm
            RuleClassificationModule-->>RuleBodyExpression: Option_RuleBodyTerm
        else expr_errors
            RuleClassificationModule->>Errors: append(errors)
            RuleClassificationModule-->>RuleBodyExpression: None
        end
    end
Loading

Class diagram for rule body classification and Expr S-expression formatting

classDiagram
    class Expr {
        +to_sexpr() String
    }

    class Literal {
    }

    class Pattern {
        +to_source() String
    }

    class MatchArm {
        pattern Pattern
        body Expr
    }

    class RuleBodyTerm {
    }

    class RuleAssignment {
        pattern Pattern
        value Expr
    }

    class RuleAggregation {
        project Expr
        key Expr
        source AggregationSource
    }

    class RuleForLoop {
        pattern Pattern
        iterable Expr
        guard Expr
        body_terms Vec_RuleBodyTerm_
    }

    class AggregationSource {
        <<enum>>
        GroupBy
        LegacyAggregate
    }

    class ClassificationContext {
        -literal_span Span
        -first_aggregation_span Option_Span_
        -errors Vec_SimpleSyntaxKind__
    }

    class ForLoopComponents {
        pattern Pattern
        iterable Expr
        guard Option_Expr_
        body Expr
    }

    class RuleClassifier {
        +parse_rule_body_term(raw String, literal_span Span, first_aggregation_span Option_Span_, errors Vec_SimpleSyntaxKind__) Option_RuleBodyTerm_
        -parse_assignment(parts AssignmentParts, literal_span Span) Result_Option_RuleBodyTerm__Vec_SimpleSyntaxKind___
        -classify_expression(expr Expr, ctx ClassificationContext) Option_RuleBodyTerm_
        -classify_aggregation_with_tracking(args Vec_Expr_, source AggregationSource, ctx ClassificationContext) Option_RuleBodyTerm_
        -classify_for_loop(components ForLoopComponents, ctx ClassificationContext) RuleBodyTerm
        -classify_for_body_with_aggregation_tracking(body Expr, ctx ClassificationContext) Vec_RuleBodyTerm_
        -aggregation_source_for(name String) Option_AggregationSource_
        -invocation_aggregation_source(callee Expr) Option_AggregationSource_
        -validate_aggregation(term RuleBodyTerm, literal_span Span, first_aggregation_span Option_Span_, errors Vec_SimpleSyntaxKind__) bool
        -aggregation_arity_error(literal_span Span, source AggregationSource) Vec_SimpleSyntaxKind__
        -multiple_aggregations_error(first_span Span, second_span Span) SimpleSyntaxKind
    }

    Expr --> Literal
    Expr --> Pattern
    Expr --> MatchArm

    RuleBodyTerm <.. RuleAssignment
    RuleBodyTerm <.. RuleAggregation
    RuleBodyTerm <.. RuleForLoop

    RuleForLoop "*" o-- "body_terms" RuleBodyTerm
    RuleAggregation --> AggregationSource

    RuleClassifier ..> ClassificationContext
    RuleClassifier ..> ForLoopComponents
    RuleClassifier ..> RuleBodyTerm
    RuleClassifier ..> RuleAggregation
    RuleClassifier ..> RuleAssignment

    ClassificationContext --> Span
    ClassificationContext --> AggregationSource

    ForLoopComponents --> Pattern
    ForLoopComponents --> Expr
Loading

File-Level Changes

Change Details Files
Extracted Expr S-expression rendering into a dedicated module and updated call sites.
  • Moved Expr::to_sexpr implementation and helpers from expr.rs into a new expr/sexpr.rs module.
  • Reimplemented to_sexpr and helper functions (format_nary, format_match, etc.) with largely identical behavior but localized to expr/sexpr.rs.
  • Adjusted imports and module wiring so tests and other code now use the new sexpr module rather than inline methods in the main Expr definition.
src/parser/ast/expr.rs
src/parser/ast/expr/sexpr.rs
Isolated rule-body term classification and assignment parsing into a dedicated classification module.
  • Introduced src/parser/ast/rule/classification.rs containing parse_rule_body_term, assignment parsing, aggregation classification, for-loop body classification, and aggregation validation helpers.
  • Replaced inlined classification logic in RuleBodyExpression::classify in rule.rs with a call to classification::parse_rule_body_term, passing through spans and error tracking.
  • Relocated helper structs and functions (ClassificationContext, ForLoopComponents, aggregation_* helpers, multiple_aggregations_error, validate_aggregation) from rule.rs into the new module while preserving behavior.
src/parser/ast/rule.rs
src/parser/ast/rule/classification.rs
Split Pratt parser postfix handling into specialized submodules and rewired the main Pratt implementation.
  • Created new modules delay.rs, diff.rs, and postfix.rs under src/parser/expression/pratt/ to house delay, diff marker, and general postfix parsing logic.
  • Removed inline postfix-related methods (parse_postfix, delay/diff helpers, function call/bit-slice/dot-access parsing, parse_args) from pratt.rs and delegated to the new modules instead.
  • Updated pratt.rs module declarations to include the new submodules and adjusted imports (e.g., parse_u32_decimal, qualified callee helpers) into the appropriate new files.
src/parser/expression/pratt.rs
src/parser/expression/pratt/delay.rs
src/parser/expression/pratt/diff.rs
src/parser/expression/pratt/postfix.rs
Reworked expression parser tests to use a structured fixtures system rather than inline rstest cases.
  • Introduced src/parser/tests/expression/fixtures.rs plus submodules for valid and error fixtures (valid/basic.rs, valid/collections.rs, valid/control_flow.rs, valid/postfix.rs, valid/structured.rs, errors.rs).
  • Defined small case structs (ExpressionCase, CountedErrorCase, PostfixErrorCase, SpannedErrorCase) and helper functions (expression_cases, literal_cases, invalid_for_loop_sources, error_cases, postfix_error_cases, match_pattern_error_cases) to centralize test data.
  • Simplified src/parser/tests/expression.rs to iterate over fixture providers in plain #[test] functions instead of many #[rstest] parameterized cases, while preserving the same coverage and assertions.
src/parser/tests/expression.rs
src/parser/tests/expression/fixtures.rs
src/parser/tests/expression/fixtures/errors.rs
src/parser/tests/expression/fixtures/valid.rs
src/parser/tests/expression/fixtures/valid/basic.rs
src/parser/tests/expression/fixtures/valid/collections.rs
src/parser/tests/expression/fixtures/valid/control_flow.rs
src/parser/tests/expression/fixtures/valid/postfix.rs
src/parser/tests/expression/fixtures/valid/structured.rs
Performed minor parser and test infrastructure cleanups to align with the new module structure.
  • Adjusted imports in expression tests to use fixture functions and removed direct dependencies on low-level test_util AST constructors where not needed.
  • Ensured aggregation tracking and error spans continue to use literal_span consistently after refactor by threading spans into the classification helpers.
  • Documented new modules with brief comments clarifying their responsibility (rule classification, Expr S-expressions, test fixtures).
src/parser/tests/expression.rs
src/parser/ast/rule/classification.rs
src/parser/ast/expr/sexpr.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#223 Refactor src/parser/ast/rule.rs by moving rule-body term classification and aggregation tracking logic into a separate dedicated module so that rule.rs is smaller and focused on the public AST surface.
#223 Refactor src/parser/ast/expr.rs by extracting Expr S-expression formatting (to_sexpr and helpers) into its own module, keeping expr.rs focused on the core Expr definition.
#223 Refactor parser Pratt expression and tests by (a) splitting postfix/diff/delay handling code out of src/parser/expression/pratt.rs into focused submodules, and (b) moving the large inline test case tables from src/parser/tests/expression.rs into reusable fixtures modules.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 1, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

src/parser/tests/expression/fixtures/errors.rs

Comment on lines +217 to +232

fn collection_error_cases() -> Vec<CountedErrorCase> {
    vec![
        CountedErrorCase {
            src: "[1, 2",
            min_errs: 1,
        },
        CountedErrorCase {
            src: "{a: 1",
            min_errs: 1,
        },
        CountedErrorCase {
            src: "{a, b}",
            min_errs: 1,
        },
    ]
}

❌ New issue: Code Duplication
The module contains 4 functions with similar structure: collection_error_cases,control_flow_error_cases,operator_error_cases,postfix_counted_error_cases

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 1, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

src/parser/expression/pratt.rs

Comment on file

use chumsky::error::Simple;

use crate::parser::ast::{Expr, StringLiteral};
use crate::parser::span_utils::parse_u32_decimal;

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: Pratt.with_struct_literal_activation,Pratt.with_struct_literals_suspended

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

Share the setup and teardown flow used by the Pratt parser's struct
literal activation and suspension helpers. Keep the existing public helper
signatures and delegate their state changes through one private scope
method.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Default `CARGO` to the executable found on `PATH`, with a fallback to the
standard Rustup installation path under `HOME`. This lets hook environments
that omit the Cargo bin directory still run the repository Makefile targets.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Add a private helper for expression parser error cases that all expect a
single minimum error. Keep the existing case order and fixture function
signatures while removing repeated `CountedErrorCase` construction.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 1, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

Code Duplication

src/parser/tests/expression/fixtures/errors.rs:

What lead to degradation?

The module contains 4 functions with similar structure: collection_error_cases,control_flow_error_cases,operator_error_cases,postfix_counted_error_cases

Why does this problem occur?

Duplicated code often leads to code that's harder to change since the same logical change has to be done in multiple functions. More duplication gives lower code health.

How to fix it?

A certain degree of duplicated code might be acceptable. The problems start when it is the same behavior that is duplicated across the functions in the module, ie. a violation of the Don't Repeat Yourself (DRY) principle. DRY violations lead to code that is changed together in predictable patterns, which is both expensive and risky. DRY violations can be identified using CodeScene's X-Ray analysis to detect clusters of change coupled functions with high code similarity. Read More
Once you have identified the similarities across functions, look to extract and encapsulate the concept that varies into its own function(s). These shared abstractions can then be re-used, which minimizes the amount of duplication and simplifies change.

@coderabbitai

This comment was marked as resolved.

@leynos leynos marked this pull request as ready for review May 2, 2026 09:11
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai coderabbitai Bot added the Issue label May 2, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/parser/ast/rule/classification.rs`:
- Line 61: The check that treats missing assignment values uses
parts.value.is_empty(), which misses whitespace-only values like "x =   ";
update the logic to trim the string before checking emptiness (e.g., use
parts.value.trim().is_empty()) so that the code path in the classification logic
(where parts.value is inspected) treats whitespace-only assignments as missing
expressions and triggers the targeted diagnostic instead of falling through to a
generic parse error.

In `@src/parser/tests/expression/fixtures/valid/postfix.rs`:
- Around line 9-67: Add two happy-path fixtures to the
postfix_expression_cases() vec: one for the apostrophe diff postfix (e.g., src
"e'") and one for the delay postfix (e.g., src "f-<1>"), each as an
ExpressionCase entry; set their expected AST using the same test helper pattern
used elsewhere (e.g., postfix_diff(var("e")) and postfix_delay(var("f"),
lit_num("1")) or the equivalent helper names in the tests) so the postfix parser
branches exercised by src/parser/expression/pratt/postfix.rs (apostrophe diff
handling and -<...> delay handling) are asserted to succeed and cannot regress
silently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0ae55951-bb4d-44a2-a93e-b1901d4665ef

📥 Commits

Reviewing files that changed from the base of the PR and between 02e67a4 and 6d8c068.

📒 Files selected for processing (18)
  • Makefile
  • src/parser/ast/expr.rs
  • src/parser/ast/expr/sexpr.rs
  • src/parser/ast/rule.rs
  • src/parser/ast/rule/classification.rs
  • src/parser/expression/pratt.rs
  • src/parser/expression/pratt/delay.rs
  • src/parser/expression/pratt/diff.rs
  • src/parser/expression/pratt/postfix.rs
  • src/parser/tests/expression.rs
  • src/parser/tests/expression/fixtures.rs
  • src/parser/tests/expression/fixtures/errors.rs
  • src/parser/tests/expression/fixtures/valid.rs
  • src/parser/tests/expression/fixtures/valid/basic.rs
  • src/parser/tests/expression/fixtures/valid/collections.rs
  • src/parser/tests/expression/fixtures/valid/control_flow.rs
  • src/parser/tests/expression/fixtures/valid/postfix.rs
  • src/parser/tests/expression/fixtures/valid/structured.rs

Comment thread src/parser/ast/rule/classification.rs Outdated
Comment thread src/parser/tests/expression/fixtures/valid/postfix.rs Outdated
@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 3, 2026

@coderabbitai please create new GitHub issues for the following:

Out-of-scope: GitHub issues required

Docstring Coverage (⚠️ Warning)

Issue #229 ("Documentation gaps: missing module comments and inconsistent API doc sections") already tracks this. No new issue is needed — link the CodeScene warning to #229.

Developer Documentation (⚠️ Warning) and Snapshot Testing (⚠️ Warning)

These two are out of scope for this refactoring PR. Shall I open GitHub issues for:

  1. Create docs/developers-guide.md documenting the new module structure, responsibilities, and architectural boundaries introduced by this PR.
  2. Introduce snapshot testing for sexpr.rs (e.g. using insta) to guard the S-expression rendering output against regression.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Create issue 1: Developer documentation
gh issue create \
  --repo leynos/ddlint \
  --title "Create docs/developers-guide.md documenting refactored parser module structure" \
  --assignee leynos \
  --body "## Background

PR `#259` refactored several internal parser modules below the 400-line maintainability guideline, introducing new modules with distinct responsibilities:

- \`src/parser/ast/expr/sexpr.rs\` — S-expression formatting for \`Expr\`
- \`src/parser/ast/rule/classification.rs\` — rule-body term classification
- \`src/parser/expression/pratt/delay.rs\` — delay-postfix parsing
- \`src/parser/expression/pratt/diff.rs\` — diff-marker postfix helpers
- \`src/parser/expression/pratt/postfix.rs\` — postfix-operator dispatch
- \`src/parser/tests/expression/fixtures/\` — structured test fixture hierarchy

No developer guide documents these modules, their responsibilities, or the architectural boundaries between them.

## Required work

Create \`docs/developers-guide.md\` covering:

1. The overall parser module layout and the 400-line size guideline.
2. Each new module: its responsibility, what it owns, and what it delegates.
3. Architectural boundaries (e.g. why sexpr formatting is separate from the AST definition; why classification is separate from rule parsing).
4. How to navigate the test fixture hierarchy when adding new expression parser tests.

## References

- PR `#259`: https://github.com/leynos/ddlint/pull/259
- Raised as out-of-scope in review comment: https://github.com/leynos/ddlint/pull/259
- Requested by `@leynos`"

# Create issue 2: Snapshot testing for sexpr.rs
gh issue create \
  --repo leynos/ddlint \
  --title "Introduce snapshot testing for Expr::to_sexpr() in sexpr.rs" \
  --assignee leynos \
  --body "## Background

PR `#259` extracted \`Expr::to_sexpr()\` into \`src/parser/ast/expr/sexpr.rs\`. The output is a text-based S-expression representation used in parser tests. Currently this output is validated only by inline string assertions; there are no snapshot tests to guard the rendering against regression.

## Required work

Introduce snapshot testing for \`src/parser/ast/expr/sexpr.rs\` using the [\`insta\`](https://insta.rs/) crate:

1. Add \`insta\` as a dev-dependency in \`Cargo.toml\`.
2. Write snapshot tests covering each \`Expr\` variant rendered by \`to_sexpr()\`, using \`insta::assert_snapshot!\`.
3. Commit the generated \`.snap\` files under \`src/parser/ast/expr/snapshots/\` (or the default \`insta\` snapshot directory).
4. Confirm \`cargo test\` and \`cargo insta review\` pass cleanly.

## Rationale

Snapshot tests make regressions in S-expression output immediately visible as diff noise in review, rather than requiring manual comparison of string literals scattered across test functions.

## References

- PR `#259`: https://github.com/leynos/ddlint/pull/259
- Raised as out-of-scope in review comment: https://github.com/leynos/ddlint/pull/259
- Requested by `@leynos`"

Length of output: 88


@leynos — both issues have been opened and assigned to you:

Both include backlinks to PR #259. The Docstring Coverage warning remains linked to the existing #229.

…ule docs

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the Roadmap label May 19, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/parser/expression/pratt/postfix.rs`:
- Around line 171-188: The new tests miss exercising the diff and delay branches
in parse_postfix, so add unit tests that call parse_postfix (via
parse_expression) to cover the "'" (diff) postfix and the "-<" (delay) postfix,
including a test that sets up a pending diff and then ensures a delay is
rejected (verifying the guard that rejects delay while a diff is pending);
specifically add tests that assert the parsed AST or error messages for the "'"
and "-<" cases and one that confirms parse_postfix returns the expected error
when a delay is attempted while a diff is pending, referencing parse_postfix,
diff postfix, and delay postfix in your assertions.
- Around line 163-166: The module-wide Clippy suppression on the tests module is
too broad; remove the inner attribute `#![expect(clippy::expect_used, ...)]`
from the `mod tests` declaration and instead add item-level
`#[expect(clippy::expect_used, reason = "...")]` attributes to each test
function that calls `expect()`/`expect_err()` (for example
`qualified_callee_uses_call_postfix` and `trailing_argument_comma_is_rejected`)
so the lint is narrowly scoped to only those test items.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 79925021-05af-4cec-8d42-9af29b36a9d4

📥 Commits

Reviewing files that changed from the base of the PR and between 841ef5f and a0508e5.

📒 Files selected for processing (1)
  • src/parser/expression/pratt/postfix.rs

Comment thread src/parser/expression/pratt/postfix.rs Outdated
Comment thread src/parser/expression/pratt/postfix.rs
Add focused `parse_expression` tests for the Pratt postfix diff and delay
paths, including the pending-diff guard before delay parsing.

Narrow the `expect_used` Clippy expectations to the individual test cases
that need them instead of suppressing the whole test module.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot added Issue and removed Roadmap labels May 19, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/parser/expression/pratt/postfix.rs`:
- Around line 151-155: Capture the separator token's span before calling
self.ts.next_tok() and use that span when calling self.ts.push_error so the
diagnostic points at the comma instead of `)`/EOF; specifically, in the postfix
parsing code around the trailing-comma check, call something like let sep_span =
self.ts.peek_span().unwrap_or_else(|| self.ts.eof_span()) (or an equivalent that
inspects the separator) before invoking self.ts.next_tok(), then pass sep_span
into self.ts.push_error(sep_span, "unexpected trailing comma in argument list")
instead of using the later peek_span()/eof_span.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5d60a935-9967-447d-8e3e-02cc15596718

📥 Commits

Reviewing files that changed from the base of the PR and between a0508e5 and 1a6f9b8.

📒 Files selected for processing (1)
  • src/parser/expression/pratt/postfix.rs

Comment thread src/parser/expression/pratt/postfix.rs Outdated
Capture the comma span before consuming it in Pratt postfix argument
parsing, then use that span for the trailing-comma diagnostic.

Update the call parsing regression expectation so it verifies the diagnostic
now points at the comma rather than the closing parenthesis.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Capture consumed postfix separator spans explicitly and report trailing
argument commas at the comma token. Remove the defensive diff-marker EOF
fallback so the helper exposes the fallible token consume directly.

Strengthen parser tests by checking the wrapped diff expression,
assignment pattern and value details, and S-expression rendering beside
snapshots.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added Roadmap and removed Issue labels May 26, 2026
Assert the trailing-comma diagnostic span, unwrap the diff postfix AST to
check the completed call it wraps, and add a direct expected rendering beside
the collection S-expression snapshot.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/parser/ast/rule/classification.rs (1)

281-281: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Move the Clippy expectation to individual test items.

The #![expect(clippy::expect_used, ...)] inner attribute applies to the entire mod tests block, which violates the coding guideline requiring narrowly scoped lint suppressions. Apply #[expect(clippy::expect_used, reason = "...")] to each test function that uses .expect() instead.

Proposed fix
 #[cfg(test)]
 mod tests {
-    #![expect(clippy::expect_used, reason = "tests assert exact parser output")]
-
     use super::*;
     use chumsky::error::SimpleReason;

     fn span_for(src: &str) -> Span {
         0..src.len()
     }

     #[test]
+    #[expect(clippy::expect_used, reason = "test asserts exact parser output")]
     fn assignment_literal_becomes_assignment_term() {
         // ...
     }

     #[test]
+    #[expect(clippy::expect_used, reason = "test asserts exact parser output")]
     fn second_aggregation_reports_error() {
         // ...
     }
 }

As per coding guidelines: "Only narrowly scoped #[expect(lint, reason = "...")] is allowed. No lint groups, no blanket or file-wide suppression."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/ast/rule/classification.rs` at line 281, The file currently places
the inner attribute #![expect(clippy::expect_used, reason = "...")] at the top
of the tests module; change this to apply the expect lint to each test function
that actually calls .expect() instead: remove the module-level #![expect(...)]
and add #[expect(clippy::expect_used, reason = "...")] directly above every
#[test] fn (inside mod tests) that uses .expect() so the suppression is narrowly
scoped to those test items only.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/parser/ast/rule/classification.rs`:
- Line 281: The file currently places the inner attribute
#![expect(clippy::expect_used, reason = "...")] at the top of the tests module;
change this to apply the expect lint to each test function that actually calls
.expect() instead: remove the module-level #![expect(...)] and add
#[expect(clippy::expect_used, reason = "...")] directly above every #[test] fn
(inside mod tests) that uses .expect() so the suppression is narrowly scoped to
those test items only.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 301a4613-1ca0-4596-843e-4ad65d9c268b

📥 Commits

Reviewing files that changed from the base of the PR and between 1a6f9b8 and 324810e.

📒 Files selected for processing (5)
  • src/parser/ast/expr/sexpr.rs
  • src/parser/ast/rule/classification.rs
  • src/parser/expression/pratt/diff.rs
  • src/parser/expression/pratt/postfix.rs
  • tests/expression_var_and_call.rs

codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot added Issue and removed Roadmap labels May 26, 2026
Move the `clippy::expect_used` expectation from the whole classification
test module to the individual tests that call `expect`. Keep the lint
suppression scoped to the exact assertions that need it.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot added Roadmap and removed Issue labels May 26, 2026
Expand expression fixture module documentation so each fixture group states
its role in the parser test suite and how it relates to the shared fixture
aggregators.

Add direct Pratt helper coverage for diff-marker error paths and delay postfix
boundary parsing, including the maximum `u32` delay and invalid delay values.
@coderabbitai coderabbitai Bot added Issue and removed Roadmap labels May 26, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
src/parser/tests/expression/fixtures/valid.rs (1)

14-29: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add Rustdoc to exported fixture entrypoints.

Document each pub(super) function with /// so the fixture contract is explicit in generated docs and module navigation.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid.rs` around lines 14 - 29, The
three exported fixture entrypoints (pub(super) functions expression_cases,
invalid_for_loop_sources, and literal_cases) lack Rustdoc; add concise ///
comments above each function describing its purpose and returned value (e.g.,
that expression_cases returns combined ExpressionCase fixtures,
invalid_for_loop_sources returns the array of invalid for-loop source strings,
literal_cases returns literal ExpressionCase fixtures) so the fixture contract
is explicit in generated docs and module navigation.
src/parser/tests/expression/fixtures/valid/basic.rs (1)

10-83: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add Rustdoc to exported basic fixture functions.

Document basic_expression_cases, invalid_for_loop_sources, and literal_cases with /// comments that define intent and return expectations.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid/basic.rs` around lines 10 - 83,
Add Rustdoc comments (///) above the three fixture functions
basic_expression_cases, invalid_for_loop_sources, and literal_cases describing
their purpose and what they return (e.g., "Returns test cases for basic
expressions as Vec<ExpressionCase>", "Returns invalid for-loop source strings as
[&'static str; 4]", "Returns literal expression cases as Vec<ExpressionCase>").
Use concise intent sentences and a brief `# Returns` line for each function so
cargo doc can generate accurate documentation.
src/parser/tests/expression/fixtures/valid/structured.rs (1)

11-69: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document the exported fixture builder with Rustdoc.

Add a /// comment above struct_and_closure_cases that states the covered syntax groups and return contract.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid/structured.rs` around lines 11 -
69, Add a Rustdoc comment above the pub(super) function struct_and_closure_cases
describing what syntax the fixture covers (struct expressions, tuple
structs/fields, closures, tuples, nested expressions) and the return contract
(returns Vec<ExpressionCase> of valid expression fixtures used by tests).
Mention any important semantics callers should know (e.g., each ExpressionCase
contains src and expected AST). Place the comment immediately above the
struct_and_closure_cases declaration so it appears in generated docs.
src/parser/tests/expression/fixtures/valid/control_flow.rs (1)

13-17: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document the exported control-flow fixture entrypoint.

Add a /// comment describing the fixture groups included and ordering behaviour.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid/control_flow.rs` around lines 13 -
17, Add a Rustdoc comment above the exported function
control_flow_expression_cases describing that it returns a Vec<ExpressionCase>
composed by first including all if_expression_cases() and then appending
match_and_for_expression_cases(), and note that ordering is significant
(if-cases first, then match/for cases). Mention the fixture groups included (if,
match, for) and the ordering behaviour so cargo doc will show the intent for
consumers.
src/parser/tests/expression/fixtures/valid/collections.rs (1)

11-75: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document the exported collection fixture API.

Add a /// doc comment to collection_expression_cases that states covered literal forms and expected usage.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid/collections.rs` around lines 11 -
75, Add a Rustdoc comment (///) immediately above the pub(super) fn
collection_expression_cases() describing the fixture's API: list the literal
forms covered (empty and numeric vectors like "[]", "[1]", "[1, 2]",
trailing-comma variants like "[1,]" and "[1, 2,]", element expressions like "[x,
y + 1]"; and map literals "{}", "{a: 1}", "{a: 1,}", "{x: y, z: w}"), state that
it returns Vec<ExpressionCase> for use in parser tests, and give a short example
or note on how tests should consume the function (e.g., call to populate
parameterized test cases). Ensure the comment is a /// Rustdoc placed
immediately above collection_expression_cases so it appears in generated docs.
src/parser/tests/expression/fixtures.rs (1)

12-58: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add Rustdoc for exported fixture types and accessors.

Document each pub(super) struct and function with /// so callers can rely on explicit field and behaviour contracts.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures.rs` around lines 12 - 58, Add Rustdoc
comments for each exported fixture type and accessor: document the structs
ExpressionCase, CountedErrorCase, SpannedErrorCase, and PostfixErrorCase
(including brief descriptions of each public field: src, expected, min_errs,
msg, start, end, unclosed) and document the accessor functions expression_cases,
invalid_for_loop_sources, literal_cases, error_cases, match_pattern_error_cases,
and postfix_error_cases to state their return types and that they delegate to
valid:: or errors:: helpers. Ensure each doc comment uses /// and clearly states
the contract/intent (what callers can expect from the returned values and
when/why to use each fixture).
♻️ Duplicate comments (1)
src/parser/tests/expression/fixtures/valid/postfix.rs (1)

117-123: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add Rustdoc to postfix_expression_cases.

Document this exported fixture entrypoint with /// to define its scope and ordering guarantees.

As per coding guidelines: "Document public APIs in Rust using Rustdoc comments (///), so documentation can be generated with cargo doc."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/tests/expression/fixtures/valid/postfix.rs` around lines 117 -
123, Add a Rustdoc comment for the exported fixture entrypoint function
postfix_expression_cases to describe its purpose, scope and any ordering
guarantees for the returned cases; update the function signature area (the
pub(super) fn postfix_expression_cases() -> Vec<ExpressionCase> declaration) to
be preceded by a /// doc comment that briefly explains this fixture, what
categories it composes (field_and_method_call_cases, call_and_slice_cases,
diff_marker_cases, delay_cases), and that callers can rely on the returned Vec
ordering as defined by the appended extensions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/parser/expression/pratt/delay.rs`:
- Around line 54-56: Add a module-level doc comment for the test module named
`mod tests` in this file: insert a `//!` comment immediately inside the `mod
tests {` block that briefly explains the module's purpose and what aspects of
`delay` parsing it covers (e.g., unit tests for Pratt parser delay expression
handling, edge cases, and expected error conditions) so the module complies with
the guideline requiring a module-level comment.

---

Outside diff comments:
In `@src/parser/tests/expression/fixtures.rs`:
- Around line 12-58: Add Rustdoc comments for each exported fixture type and
accessor: document the structs ExpressionCase, CountedErrorCase,
SpannedErrorCase, and PostfixErrorCase (including brief descriptions of each
public field: src, expected, min_errs, msg, start, end, unclosed) and document
the accessor functions expression_cases, invalid_for_loop_sources,
literal_cases, error_cases, match_pattern_error_cases, and postfix_error_cases
to state their return types and that they delegate to valid:: or errors::
helpers. Ensure each doc comment uses /// and clearly states the contract/intent
(what callers can expect from the returned values and when/why to use each
fixture).

In `@src/parser/tests/expression/fixtures/valid.rs`:
- Around line 14-29: The three exported fixture entrypoints (pub(super)
functions expression_cases, invalid_for_loop_sources, and literal_cases) lack
Rustdoc; add concise /// comments above each function describing its purpose and
returned value (e.g., that expression_cases returns combined ExpressionCase
fixtures, invalid_for_loop_sources returns the array of invalid for-loop source
strings, literal_cases returns literal ExpressionCase fixtures) so the fixture
contract is explicit in generated docs and module navigation.

In `@src/parser/tests/expression/fixtures/valid/basic.rs`:
- Around line 10-83: Add Rustdoc comments (///) above the three fixture
functions basic_expression_cases, invalid_for_loop_sources, and literal_cases
describing their purpose and what they return (e.g., "Returns test cases for
basic expressions as Vec<ExpressionCase>", "Returns invalid for-loop source
strings as [&'static str; 4]", "Returns literal expression cases as
Vec<ExpressionCase>"). Use concise intent sentences and a brief `# Returns` line
for each function so cargo doc can generate accurate documentation.

In `@src/parser/tests/expression/fixtures/valid/collections.rs`:
- Around line 11-75: Add a Rustdoc comment (///) immediately above the
pub(super) fn collection_expression_cases() describing the fixture's API: list
the literal forms covered (empty and numeric vectors like "[]", "[1]", "[1, 2]",
trailing-comma variants like "[1,]" and "[1, 2,]", element expressions like "[x,
y + 1]"; and map literals "{}", "{a: 1}", "{a: 1,}", "{x: y, z: w}"), state that
it returns Vec<ExpressionCase> for use in parser tests, and give a short example
or note on how tests should consume the function (e.g., call to populate
parameterized test cases). Ensure the comment is a /// Rustdoc placed
immediately above collection_expression_cases so it appears in generated docs.

In `@src/parser/tests/expression/fixtures/valid/control_flow.rs`:
- Around line 13-17: Add a Rustdoc comment above the exported function
control_flow_expression_cases describing that it returns a Vec<ExpressionCase>
composed by first including all if_expression_cases() and then appending
match_and_for_expression_cases(), and note that ordering is significant
(if-cases first, then match/for cases). Mention the fixture groups included (if,
match, for) and the ordering behaviour so cargo doc will show the intent for
consumers.

In `@src/parser/tests/expression/fixtures/valid/structured.rs`:
- Around line 11-69: Add a Rustdoc comment above the pub(super) function
struct_and_closure_cases describing what syntax the fixture covers (struct
expressions, tuple structs/fields, closures, tuples, nested expressions) and the
return contract (returns Vec<ExpressionCase> of valid expression fixtures used
by tests). Mention any important semantics callers should know (e.g., each
ExpressionCase contains src and expected AST). Place the comment immediately
above the struct_and_closure_cases declaration so it appears in generated docs.

---

Duplicate comments:
In `@src/parser/tests/expression/fixtures/valid/postfix.rs`:
- Around line 117-123: Add a Rustdoc comment for the exported fixture entrypoint
function postfix_expression_cases to describe its purpose, scope and any
ordering guarantees for the returned cases; update the function signature area
(the pub(super) fn postfix_expression_cases() -> Vec<ExpressionCase>
declaration) to be preceded by a /// doc comment that briefly explains this
fixture, what categories it composes (field_and_method_call_cases,
call_and_slice_cases, diff_marker_cases, delay_cases), and that callers can rely
on the returned Vec ordering as defined by the appended extensions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a86368a6-ab3f-44bd-91f7-6303232343d5

📥 Commits

Reviewing files that changed from the base of the PR and between de3e89f and 81c28f5.

📒 Files selected for processing (10)
  • src/parser/expression/pratt/delay.rs
  • src/parser/expression/pratt/diff.rs
  • src/parser/tests/expression/fixtures.rs
  • src/parser/tests/expression/fixtures/errors.rs
  • src/parser/tests/expression/fixtures/valid.rs
  • src/parser/tests/expression/fixtures/valid/basic.rs
  • src/parser/tests/expression/fixtures/valid/collections.rs
  • src/parser/tests/expression/fixtures/valid/control_flow.rs
  • src/parser/tests/expression/fixtures/valid/postfix.rs
  • src/parser/tests/expression/fixtures/valid/structured.rs

Comment on lines +54 to +56
#[cfg(test)]
mod tests {
use chumsky::error::SimpleReason;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add a module doc comment to the tests module.

Start the test module with a //! comment describing its purpose and coverage focus.

As per coding guidelines: "Every Rust module must begin with a module level (//!) comment explaining the module's purpose and utility."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/parser/expression/pratt/delay.rs` around lines 54 - 56, Add a
module-level doc comment for the test module named `mod tests` in this file:
insert a `//!` comment immediately inside the `mod tests {` block that briefly
explains the module's purpose and what aspects of `delay` parsing it covers
(e.g., unit tests for Pratt parser delay expression handling, edge cases, and
expected error conditions) so the module complies with the guideline requiring a
module-level comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[High] Oversized modules violate local maintainability guideline (400-line cap)

1 participant