Skip to content

Add block-scalar-chomping rule#286

Merged
owenlamont merged 5 commits into
mainfrom
257-block-scalar-chomping
Jun 9, 2026
Merged

Add block-scalar-chomping rule#286
owenlamont merged 5 commits into
mainfrom
257-block-scalar-chomping

Conversation

@owenlamont

Copy link
Copy Markdown
Owner

Summary

  • add the opt-in, TOML-only block-scalar-chomping rule from New rule: block-scalar-chomping — require explicit chomping indicator #257
  • require an explicit strip (-) or keep (+) indicator on every literal or folded block scalar, including indentation-only, empty, and blank-only scalars
  • register the rule across lint dispatch, configuration/schema serialization, directives, per-file ignores, Markdown embedding, docs, and examples
  • extend property generation and CLI coverage for scanner/header-position edge cases, mixed newline styles, Unicode columns, and misleading header-like content

Why

A bare | or > silently selects YAML's clip chomping behavior. Requiring an explicit indicator makes the intended trailing-newline behavior visible and avoids accidental value changes.

During review, empty and blank-only scalars were found to be skipped even though #257 requires every block scalar to be checked. Header recovery now handles granit's different token positions for those scalars while avoiding false header matches when the first content line itself looks like | or >.

User impact

The rule is disabled by default and is configured only through TOML because yamllint has no equivalent rule. It has no safe automatic fix because YAML has no explicit clip indicator; choosing strip or keep changes the resolved value.

Validation

  • prek run --all-files
  • ./scripts/coverage-missing.sh (Coverage OK: no uncovered regions.)
  • PROPTEST_CASES=512000 cargo test --release --test property_check
  • uv run scripts/source_size.py --compare-to main

Closes #257
Part of #261

…ator (#257)

Off-by-default, ryl-only (TOML) rule flagging literal/folded block scalars that lack an explicit chomping indicator (`-`/`+`); `|2` (indentation-only) is flagged. Enumerates block scalars via granit scanner tokens and recovers the header as the nearest marker-bearing line above the content, splitting lines on granit's YAML 1.2 break set (`\r\n`/`\r`/`\n`) so it is CR-aware like the other parser-based rules. Empty/blank-only scalars are skipped (granit gives them no stable header position). No safe `--fix` (YAML has no explicit clip indicator).

Also tightens the `unicode-line-breaks` line-counting doc. Follow-up #284 tracks unifying the byte-scanning rules onto the same YAML 1.2 break set.
@owenlamont owenlamont self-assigned this Jun 9, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 9, 2026

Copy link
Copy Markdown

Deploying ryl-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: fc4a4be
Status: ✅  Deploy successful!
Preview URL: https://caee09c3.ryl-docs.pages.dev
Branch Preview URL: https://257-block-scalar-chomping.ryl-docs.pages.dev

View logs

@owenlamont owenlamont marked this pull request as ready for review June 9, 2026 10:48
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

Test Coverage (nextest + cargo-llvm-cov)

Filename                                Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cli_support.rs                               85                 0   100.00%           4                 0   100.00%          59                 0   100.00%           0                 0         -
conf/mod.rs                                  10                 0   100.00%           1                 0   100.00%           7                 0   100.00%           0                 0         -
config.rs                                  1527                 0   100.00%         144                 0   100.00%        1081                 0   100.00%           0                 0         -
config_schema.rs                            421                 0   100.00%          42                 0   100.00%         327                 0   100.00%           0                 0         -
config_schema/serialization.rs              555                 0   100.00%          31                 0   100.00%         340                 0   100.00%           0                 0         -
config_schema/validation.rs                 131                 0   100.00%          18                 0   100.00%         114                 0   100.00%           0                 0         -
decoder.rs                                  482                 0   100.00%          35                 0   100.00%         321                 0   100.00%           0                 0         -
directives.rs                               238                 0   100.00%          22                 0   100.00%         140                 0   100.00%           0                 0         -
discover.rs                                  36                 0   100.00%           3                 0   100.00%          23                 0   100.00%           0                 0         -
fix.rs                                      571                 0   100.00%          36                 0   100.00%         365                 0   100.00%           0                 0         -
lint.rs                                     276                 0   100.00%          17                 0   100.00%         169                 0   100.00%           0                 0         -
main.rs                                     921                 0   100.00%          39                 0   100.00%         618                 0   100.00%           0                 0         -
markdown_embed/lint.rs                       99                 0   100.00%           6                 0   100.00%          69                 0   100.00%           0                 0         -
markdown_embed/mod.rs                       169                 0   100.00%          11                 0   100.00%         114                 0   100.00%           0                 0         -
migrate.rs                                  214                 0   100.00%          17                 0   100.00%         157                 0   100.00%           0                 0         -
rules/anchors.rs                            182                 0   100.00%          11                 0   100.00%         155                 0   100.00%           0                 0         -
rules/block_scalar_chomping.rs              126                 0   100.00%          12                 0   100.00%          82                 0   100.00%           0                 0         -
rules/colons.rs                             299                 0   100.00%          20                 0   100.00%         228                 0   100.00%           0                 0         -
rules/commas.rs                             350                 0   100.00%          15                 0   100.00%         246                 0   100.00%           0                 0         -
rules/comments.rs                           194                 0   100.00%          12                 0   100.00%         125                 0   100.00%           0                 0         -
rules/comments_indentation.rs               299                 0   100.00%          13                 0   100.00%         163                 0   100.00%           0                 0         -
rules/document_end.rs                       195                 0   100.00%          13                 0   100.00%         141                 0   100.00%           0                 0         -
rules/document_start.rs                     124                 0   100.00%          11                 0   100.00%          86                 0   100.00%           0                 0         -
rules/empty_lines.rs                        219                 0   100.00%          10                 0   100.00%         145                 0   100.00%           0                 0         -
rules/empty_values.rs                       170                 0   100.00%          13                 0   100.00%         145                 0   100.00%           0                 0         -
rules/float_values.rs                       270                 0   100.00%          24                 0   100.00%         170                 0   100.00%           0                 0         -
rules/hyphens.rs                             78                 0   100.00%           4                 0   100.00%          60                 0   100.00%           0                 0         -
rules/indentation.rs                        689                 0   100.00%          45                 0   100.00%         588                 0   100.00%           0                 0         -
rules/key_duplicates.rs                     690                 0   100.00%          47                 0   100.00%         469                 0   100.00%           0                 0         -
rules/key_ordering.rs                       208                 0   100.00%          23                 0   100.00%         142                 0   100.00%           0                 0         -
rules/line_length.rs                        222                 0   100.00%          15                 0   100.00%         160                 0   100.00%           0                 0         -
rules/merge_keys.rs                          49                 0   100.00%           2                 0   100.00%          32                 0   100.00%           0                 0         -
rules/new_line_at_end_of_file.rs             27                 0   100.00%           3                 0   100.00%          15                 0   100.00%           0                 0         -
rules/new_lines.rs                          114                 0   100.00%           8                 0   100.00%          77                 0   100.00%           0                 0         -
rules/octal_values.rs                       104                 0   100.00%          11                 0   100.00%          70                 0   100.00%           0                 0         -
rules/quoted_strings.rs                    1208                 0   100.00%          94                 0   100.00%         861                 0   100.00%           0                 0         -
rules/support/comments_scan.rs               31                 0   100.00%           1                 0   100.00%          23                 0   100.00%           0                 0         -
rules/support/flow_collection.rs            613                 0   100.00%          36                 0   100.00%         501                 0   100.00%           0                 0         -
rules/support/line_syntax.rs                211                 0   100.00%          12                 0   100.00%         152                 0   100.00%           0                 0         -
rules/support/mapping_key_walker.rs          89                 0   100.00%          15                 0   100.00%          87                 0   100.00%           0                 0         -
rules/support/merge_key.rs                   14                 0   100.00%           2                 0   100.00%          12                 0   100.00%           0                 0         -
rules/support/punctuation.rs                157                 0   100.00%          16                 0   100.00%         106                 0   100.00%           0                 0         -
rules/support/span_utils.rs                  87                 0   100.00%          13                 0   100.00%          68                 0   100.00%           0                 0         -
rules/tags.rs                               115                 0   100.00%           9                 0   100.00%          88                 0   100.00%           0                 0         -
rules/trailing_spaces.rs                    112                 0   100.00%           4                 0   100.00%          68                 0   100.00%           0                 0         -
rules/truthy.rs                             318                 0   100.00%          19                 0   100.00%         224                 0   100.00%           0                 0         -
rules/unicode_line_breaks.rs                 34                 0   100.00%           2                 0   100.00%          30                 0   100.00%           0                 0         -
yaml_dom/loader.rs                          186                 0   100.00%           6                 0   100.00%         119                 0   100.00%           0                 0         -
yaml_dom/scalar.rs                          142                 0   100.00%          11                 0   100.00%          71                 0   100.00%           0                 0         -
yaml_dom/tag.rs                              12                 0   100.00%           2                 0   100.00%          10                 0   100.00%           0                 0         -
yaml_dom/yaml_owned.rs                       69                 0   100.00%          14                 0   100.00%          53                 0   100.00%           0                 0         -
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                     13742                 0   100.00%         994                 0   100.00%        9676                 0   100.00%           0                 0         -

Missed Lines (per file)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7fa60599ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/rules/block_scalar_chomping.rs Outdated
Comment on lines +153 to +154
let text = strip_trailing_comment_preserving_quotes(lines[line_no - 1]);
block_scalar_marker_index(text).map(|idx| (line_no, text, idx))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve non-comment hash characters while locating headers

When the enabled rule checks a valid block scalar whose header contains an unquoted # that is not preceded by whitespace, such as a#b: |\n body\n or a verbatim tag URI with a fragment, this helper truncates the header at the #. The reverse search then cannot find the actual marker and the .expect(...) below panics, crashing the CLI on valid YAML instead of reporting the missing chomping indicator. Only strip # when it begins a YAML comment, or avoid comment stripping while recovering scanner-confirmed headers.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7fa60599ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/rules/block_scalar_chomping.rs Outdated
Comment on lines +143 to +144
let text = strip_trailing_comment_preserving_quotes(line);
block_scalar_marker_index(text)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve # inside verbatim tags when locating headers

When this rule is enabled, a valid header such as value: !<tag:example.com,2000:app/foo#bar> | can panic the CLI. Verbatim tag URIs may contain #, but strip_trailing_comment_preserving_quotes treats every unquoted # as the start of a comment, truncating the line before the block-scalar marker; header_marker then finds no marker and reaches its expect. Only strip a # that is actually a YAML comment, or locate the header using scanner spans that preserve tag fragments.

Useful? React with 👍 / 👎.

@owenlamont

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 268780578b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

block_scalar_marker_index(text).map(|idx| (line_no, text, idx))
})
})
.expect("a block scalar has a marker-bearing header")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid panicking on plain keys containing ! or &

When this rule is enabled, valid YAML such as a !foo: |\n body\n crashes here instead of reporting the bare header. block_scalar_marker_index treats the whitespace-delimited !foo: token as a node property, walks past it, and rejects the actual header because the remaining prefix ends in a; the backward search therefore returns None and this expect panics. Plain-scalar keys may contain ! or & after their first character (the example is also accepted by yamllint), so header recovery must distinguish those key fragments from actual node properties.

Useful? React with 👍 / 👎.

@owenlamont

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@owenlamont

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@owenlamont owenlamont merged commit cd4119c into main Jun 9, 2026
2 checks passed
@owenlamont owenlamont deleted the 257-block-scalar-chomping branch June 9, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New rule: block-scalar-chomping — require explicit chomping indicator

1 participant