Skip to content

[checks] Collapse clauses for described conditions - #2794

Merged
natebosch merged 2 commits into
masterfrom
collapse-condition-clauses
Oct 29, 2026
Merged

natebosch merged 2 commits into
masterfrom
collapse-condition-clauses

Conversation

@natebosch

@natebosch natebosch commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

IterableChecks.any, IterableChecks.every,
MapChecks.containsKeyThat, and MapChecks.containsValueThat embed the
description of a condition. They collapse to a single line at the root,
through a predicate noun such as an iterable containing a value that is greater than <7>, but their clause always used the multi-line form of a
label followed by the indented description. Where the clause itself is
shown, such as when one of these expectations is nested inside the
condition of another, the description never collapsed, while the same
check reached through has did. Reported in
#2784 (comment):

check([[1]]).any(.it()..any(.it()..isGreaterThan(1)));

Expected: a List<List<int>> that:
  contains a value that:
    contains a value that:
      is greater than <1>

Add an internal describedClause helper next to
describedPredicateNoun. It joins the label to the description of the
condition on a single line when the condition describes in a single line
and the result fits within 80 columns, and otherwise keeps the label
followed by the indented description. Both helpers share the logic for
joining and the length limit. Use it for the clauses of all four
expectations. The inner any above now describes itself as a single
line, so the outer any collapses to a single Expected: line at the
root:

an iterable containing a value that contains a value that is
greater than <1>

Joining the label of every, only has values that, to a description
such as is less than <10> reads as only has values that is less than <10>. Describe the condition as only has elements where each instead,
which reads as only has elements where each is less than <10> on one
line, and only has elements where each: followed by the description
otherwise. The label is a predicate over the iterable ending with a
singular noun, so it also reads as a sentence when every is nested in
another condition, such as an iterable where every element only has elements where each is less than <10>. Change the predicate noun to
match the wording: an iterable where every element is less than <10>.

`IterableChecks.any`, `IterableChecks.every`, `MapChecks.containsKeyThat`,
and `MapChecks.containsValueThat` embed the description of a condition.
They collapse to a single line at the root, through a predicate noun such as
`an iterable containing a value that is greater than <7>`, but their clause
always used the multi-line form of a label followed by the indented
description. Where the clause itself is shown, such as when one of these
expectations is nested inside the condition of another, the description
never collapsed, while the same check reached through `has` did. Reported in
#2784 (comment):

    check([[1]]).any(.it()..any(.it()..isGreaterThan(1)));

    Expected: a List<List<int>> that:
      contains a value that:
        contains a value that:
          is greater than <1>

Add an internal `describedClause` helper next to `describedPredicateNoun`.
It joins the label to the description of the condition on a single line when
the condition describes in a single line and the result fits within 80
columns, and otherwise keeps the label followed by the indented description.
Both helpers share the logic for joining and the length limit. Use it for
the clauses of all four expectations. The inner `any` above now describes
itself as a single line, so the outer `any` collapses to a single
`Expected:` line at the root:

    an iterable containing a value that contains a value that is
    greater than <1>

Joining the label of `every`, `only has values that`, to a description such
as `is less than <10>` reads as `only has values that is less than <10>`.
Describe the condition as `every element` instead, which reads as
`every element is less than <10>` on one line, and `every element:` followed
by the description otherwise. Change the predicate noun to match:
`an iterable where every element is less than <10>`.
@natebosch
natebosch requested a review from a team as a code owner October 14, 2026 02:10
@github-actions github-actions Bot added the package:checks Issues related to pkg:checks label Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

PR Health

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check (for example, for non-user-visible changes when the package version is already at -wip).

@natebosch
natebosch requested a review from davidmorgan October 14, 2026 02:11

@davidmorgan davidmorgan 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.

Requesting changes for one composition problem in the new every clause, see the inline comment. Everything else checked out: the describedClause and _joinSingleLine thresholds at 79, 80 and 81 columns, any, containsKeyThat, containsValueThat, and the updated examples. The pkgs/checks suite passes on base, 450 tests, and on head, 453 tests. Three independent probes found the same issue.

The clause for `IterableChecks.every` was `every element`, which is a
subject noun phrase. The other clauses passed to `context.expect` are
predicates over the checked value, such as `contains a value that ...` and
`is less than ...`. When `every` was nested inside another condition, its
description no longer read as a sentence:

    an iterable where every element every element is less than <10>
    an iterable containing a value that every element is less than <10>
    a map containing a key that every element is less than <10>

To compose, the label has to start as a predicate over the outer iterable
and end with a singular noun, since the descriptions of the inner condition
start with singular verbs such as "is less than" and "equals". Use
`only has elements where each`:

    an iterable where every element only has elements where each is less
    than <10>

The longer label leaves less room for the inner description before a
nested `every` falls back to the multi-line form at 80 columns.

Add tests nesting `every` inside `every`, `any`, and `containsKeyThat`.
@natebosch
natebosch merged commit 50c9f45 into master Oct 29, 2026
71 checks passed
@natebosch
natebosch deleted the collapse-condition-clauses branch October 29, 2026 22:11
copybara-service Bot pushed a commit to dart-lang/sdk that referenced this pull request Nov 3, 2026
Revisions updated by `dart tools/rev_sdk_deps.dart`.

core (https://github.com/dart-lang/core/compare/d7bd45c..24e09c4):
  24e09c4c  Sun Nov 1 21:12:19 2026 +0000  dependabot[bot]  Bump the github-actions group with 4 updates (dart-lang/core#1037)
  87ac1b4c  Fri Oct 30 16:02:43 2026 +0100  Michael Thomsen  [os_detect] Deprecate package:os_detect in favor of package:platform (dart-lang/core#1003)
  8debf335  Fri Oct 30 01:57:36 2026 +0530  Sahaja Pallapothula  Clarify Characters equality and Unicode normalization (dart-lang/core#1031)

ecosystem (https://github.com/dart-lang/ecosystem/compare/24b9ba8..f8faabf):
  f8faabf  Sun Nov 1 18:16:20 2026 +0000  dependabot[bot]  Bump the github-actions group with 2 updates (dart-lang/ecosystem#481)
  27c2fc8  Sat Oct 31 12:36:53 2026 +0100  Moritz  Fix publish workflow pins, add tag_prefix to health, and update docs (dart-lang/ecosystem#480)
  05641a9  Sat Oct 31 09:56:42 2026 +0100  Moritz  Restore deprecated publish.yaml workflow and firehose CLI entrypoint (dart-lang/ecosystem#479)
  78abf72  Fri Oct 30 08:24:07 2026 -0700  Kevin Moore  fix(repo_manage): use pub_semver for changelog -wip transitions (dart-lang/ecosystem#475)
  0bfa654  Fri Oct 30 09:33:57 2026 +0100  Moritz  Move publish check to health workflow and use individual package publishing workflows from `setup-dart` (dart-lang/ecosystem#454)
  adf7979  Thu Oct 29 23:46:49 2026 -0700  Kevin Moore  test(firehose): use hasLength, containsPair, and isFalse (dart-lang/ecosystem#477)

http (https://github.com/dart-lang/http/compare/c76dfb3..8c0d66a):
  8c0d66a  Fri Oct 30 09:54:41 2026 -0700  Brian Quinlan  chore(cupertino_http): check ffigen generation (dart-lang/http#2044)
  c8737d1  Fri Oct 30 09:11:46 2026 +0100  Moritz  chore(http): run Firefox tests with -headless instead of xvfb-run (dart-lang/http#2033)
  05d0b18  Fri Oct 30 07:08:19 2026 +0100  Moritz  fix(http2): make StreamException a StreamTransportException and forward ALPN errors to onError (dart-lang/http#2009)

i18n (https://github.com/dart-lang/i18n/compare/4c7b4ad..7475ce6):
  7475ce64  Sat Oct 31 02:49:28 2026 +0100  Moritz  [intl4x] Fix NumberFormat.percent ignoring digits (dart-lang/i18n#1115)

shelf (https://github.com/dart-lang/shelf/compare/62d3e4e..9946de5):
  9946de5  Sun Nov 1 12:27:59 2026 +0000  dependabot[bot]  build(deps): bump the github-actions group with 3 updates (dart-lang/shelf#554)

test (https://github.com/dart-lang/test/compare/6d74720..2a9e017):
  2a9e0175  Sun Nov 1 03:47:24 2026 +0000  dependabot[bot]  Bump the github-actions group with 6 updates (dart-lang/test#2813)
  55cd5cd5  Fri Oct 30 13:43:47 2026 -0700  Nate Bosch  Migrate publishing workflows from firehose to setup-dart (dart-lang/test#2812)
  10dc78c0  Fri Oct 30 11:21:53 2026 -0700  Nate Bosch  [checks] Describe what the stream did in failures (dart-lang/test#2811)
  c11ad06d  Fri Oct 30 08:59:57 2026 -0700  Nate Bosch  [checks] Add CheckFailure.describeNested (dart-lang/test#2793)
  0137b43e  Fri Oct 30 05:40:43 2026 +0530  Shriraj Jadhav  [checks] Use the Iterable.last member for the last expectation (dart-lang/test#2807)
  50c9f454  Thu Oct 29 15:11:39 2026 -0700  Nate Bosch  [checks] Collapse clauses for described conditions (dart-lang/test#2794)

tools (https://github.com/dart-lang/tools/compare/3980dca..1579f8d):
  1579f8d69  Mon Nov 2 02:44:58 2026 +0530  Joshua  fix(coverage): reject package: and dart: URIs outside known roots in Resolver (dart-lang/tools#2764)
  f869fdca4  Sun Nov 1 10:26:34 2026 +0100  dart-ecosystem-bot[bot]  [boring] Update BoringSSL to ed9209cf (dart-lang/tools#2774)
  d10e2b87f  Sun Nov 1 10:26:11 2026 +0100  dart-ecosystem-bot[bot]  [boring] Pin the prebuilt binaries of boring-binaries-20261101-33e9e69722af (dart-lang/tools#2777)
  33e9e6972  Sun Nov 1 05:56:30 2026 +0000  dependabot[bot]  build(deps): bump the github-actions group with 4 updates (dart-lang/tools#2775)
  f84d0d0d2  Sun Nov 1 05:36:12 2026 +0000  dependabot[bot]  build(deps): bump ffigen from 22.0.0 to 23.0.0 in /pkgs/boring (dart-lang/tools#2776)
  14ad5e515  Fri Oct 30 10:48:58 2026 -0700  Kevin Moore  [mime] Harden BoundMultipartStream error routing, headers, and epilogue (dart-lang/tools#2629)
  7a780d48c  Fri Oct 30 12:57:03 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid rescanning failed plain-text runs in InlineParser (dart-lang/tools#2757)
  3671d33a9  Fri Oct 30 12:56:48 2026 +0100  Jonas Finnemann Jensen  [markdown] Index footnote definitions and labels on Document for O(1) lookup (dart-lang/tools#2760)
  6f38e9fda  Fri Oct 30 12:56:09 2026 +0100  Jonas Finnemann Jensen  [markdown] Bound the domain of extended URL autolinks to DNS limits (dart-lang/tools#2759)
  aa0c38544  Fri Oct 30 12:20:40 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid quadratic removeRange in _combineAdjacentText (dart-lang/tools#2758)
  f425baf46  Fri Oct 30 11:16:28 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid rescanning failed space runs in LineBreakSyntax (dart-lang/tools#2756)
  c7eafbec3  Fri Oct 30 11:09:45 2026 +0100  Jonas Finnemann Jensen  [markdown] Reject '<' in AutolinkSyntax (dart-lang/tools#2755)
  86ed0f902  Fri Oct 30 11:08:25 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid quadratic backtracking in headerPattern (dart-lang/tools#2754)
  8ea07517f  Fri Oct 30 07:45:42 2026 +0100  Moritz  [boring] Regenerate the x509-limbo expected failures in the refresh job (dart-lang/tools#2712)
  40235c365  Thu Oct 29 14:46:17 2026 +0100  Jonas Finnemann Jensen  [markdown] Make HtmlBlockSyntax.parseChildLines iterative (dart-lang/tools#2749)
  0ff03f643  Thu Oct 29 14:41:33 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid re-escaping nested image alt text in ImageSyntax.createNode (dart-lang/tools#2752)
  784654d01  Thu Oct 29 14:37:11 2026 +0100  Jonas Finnemann Jensen  [markdown] Add test cases covering parser and renderer edge cases (dart-lang/tools#2753)
  4f2718ad8  Thu Oct 29 14:36:52 2026 +0100  Jonas Finnemann Jensen  [markdown] Make Document._parseInlineContent iterative (dart-lang/tools#2750)
  cac1421d5  Thu Oct 29 14:17:06 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid quadratic duplicate heading ID probing in HtmlRenderer (dart-lang/tools#2748)
  66880bcd3  Thu Oct 29 14:11:27 2026 +0100  Jonas Finnemann Jensen  [markdown] Check footnote label and empty map before scanning footnote keys (dart-lang/tools#2751)
  7f8696523  Thu Oct 29 14:07:06 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid quadratic blank-line lookahead in CodeBlockSyntax (dart-lang/tools#2747)
  9da6bb291  Thu Oct 29 14:03:04 2026 +0100  Jonas Finnemann Jensen  [markdown] Avoid exponential and quadratic backtracking in tablePattern (dart-lang/tools#2746)

dartdoc is held back at db94437, before dart-lang/dartdoc#4312, because its
mock SDK version changes conflict in the google3 3-way merge with the hotfix
in cl/1005963642.

native is held back at e0ca7c6, before dart-lang/native#3742, because
deprecating `MacOSCodeConfig(targetVersion: ...)` causes a fatal
`deprecated_member_use` diagnostic in `pkg/dartdev/lib/src/native_assets.dart`.

web is held back at 4e60e61, before dart-lang/web#596, because it changes
`package:web` signatures (e.g. `innerHTML=`, `parseFromString`, `Worker()`)
from `JSAny` to `String` in ways that break callers in google3.

Change-Id: I53d2cbde741c45b8fd33bca42742549819dd332b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/572780
Reviewed-by: Brian Quinlan <[email protected]>
Commit-Queue: Nate Bosch <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package:checks Issues related to pkg:checks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants