Skip to content

Enable implicit non-top-level conditions (#1160)#2250

Open
Vampire wants to merge 1 commit intomasterfrom
vampire/implicit-non-top-level-conditions
Open

Enable implicit non-top-level conditions (#1160)#2250
Vampire wants to merge 1 commit intomasterfrom
vampire/implicit-non-top-level-conditions

Conversation

@Vampire
Copy link
Member

@Vampire Vampire commented Oct 29, 2025

Fixes #1160

Summary by CodeRabbit

  • Breaking Changes

    • Expression statements in then/expect blocks (including some first-level interaction closures) are now treated as implicit conditions by default; existing code may need adjustments. An opt-out prefix operator is provided to mark expressions as non-conditions.
  • Tests

    • Added and updated tests covering non-top-level condition evaluation and related edge cases.
  • Documentation

    • Clarified implicit-condition rules, exceptions for unknown closures, and updated release notes and primer wording.

Copy link
Member Author

Vampire commented Oct 29, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Vampire
Copy link
Member Author

Vampire commented Oct 29, 2025

While fixing the verify methods also stumbled over the sole line that needs to be changed to enable non-top-level implicit conditions.
Turns out this was more an arbitrary restriction that was very easy to change and also only one of our tests needed adaption because it relied on impicit condition being non-effective inside an if. :-)

@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch from 007a5a9 to 70fb92e Compare October 29, 2025 13:45
Copy link
Member Author

Vampire commented Oct 29, 2025

Ok, two tests.
Good that we have the !! available now. :-)

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.17%. Comparing base (9c6342c) to head (4abd191).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #2250   +/-   ##
=========================================
  Coverage     82.16%   82.17%           
- Complexity     4822     4825    +3     
=========================================
  Files           472      472           
  Lines         15036    15037    +1     
  Branches       1905     1905           
=========================================
+ Hits          12355    12356    +1     
  Misses         1989     1989           
  Partials        692      692           
Files with missing lines Coverage Δ
...kframework/compiler/AbstractDeepBlockRewriter.java 96.34% <100.00%> (ø)
...org/spockframework/compiler/DeepBlockRewriter.java 98.24% <100.00%> (ø)
...g/spockframework/compiler/NoSpecialMethodCall.java 54.16% <100.00%> (+1.99%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@AndreasTu
Copy link
Member

Very nice, but should we maybe wait for or plan a Spock 3 version?
I think this change in 2.4 will hinder the adoption of the new version. And the 2.3 is quite old by now.

So I would be for delaying that PR until we released 2.4 finally and then we plan a 3.0 as next version.

@leonard84
Copy link
Member

While I also want to get rid of this confusing behavior, I think we should postpone it until Spock 3.0, as the breaking change is quite significant.

@leonard84 leonard84 added this to the 3.0 milestone Nov 2, 2025
@Vampire
Copy link
Member Author

Vampire commented Nov 9, 2025

Up to @leonard84 I'd say.
I don't care when it comes, I just stumbled over the line and thought I'll create a PR right away before I forget the details again, as I know Leonard wants to have this change.

In my personal opinion I think the change is not that much breaking.
I'd expect that most cases where this is breaking existing code is, where it should always better failed because someone checked a condition on non-top-level and thought the test is green while it is actually red.

And the cases where this is not the case, but the behavior used like in the two cases we had in the codebase, you can easily use !! to disable the implicit assertion.

We were seldomly shy to do breaking changes, why become shy now? :-)

If you really think it is too breaking to bring it in 2.4 now, no problem, just delay it until later.
It just then needs another 3 years until it reaches the users.
(I consider "normal" users here that do not use an M-release but only final releases).
🤷‍♂️

As I said, I just thought I'll do the changes now that I have the details and easy solution in mind. and did it in a way it could still make it into 2.4 (regarding the release notes changes).

@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch 2 times, most recently from 5633a59 to 34517fe Compare November 14, 2025 01:39
@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch from 34517fe to b38799d Compare November 18, 2025 22:51
@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch from b38799d to 00ed347 Compare March 13, 2026 04:12
@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

This change expands which expression statements are treated as implicit conditions in then/expect/filter blocks (including some first-level interaction closures), adds a closure-specific sentinel, updates rewriter logic, and adjusts documentation and tests to reflect the new implicit-condition semantics. No public API signatures were removed or altered.

Changes

Cohort / File(s) Summary
Documentation
docs/release_notes.adoc, docs/spock_primer.adoc
Add breaking-change note and primer updates: expression statements (including interaction-classified expressions) are implicitly conditions except inside unknown/closure contexts; documents opt-out prefix and potential compile errors.
Compiler Rewriter
spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java, spock-core/src/main/java/org/spockframework/compiler/AbstractDeepBlockRewriter.java
Adjust closure sentinel handling and broaden implicit-condition eligibility to include NoSpecialMethodCall contexts in Then/Expect/Filter and depth‑1 interaction closures.
Sentinel Constant
spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java
Introduce new public CLOSURE_INSTANCE sentinel alongside existing INSTANCE to distinguish closure scopes.
Tests — runtime/style adjustments
spock-junit4/src/test/groovy/org/spockframework/junit4/junit/JUnitFixtureMethods.groovy, spock-specs/src/test/groovy/org/spockframework/smoke/extension/TempDirExtensionSpec.groovy
Coerce several assignment expressions with !!(...) and adjust assertion forms so they behave correctly under the new implicit-condition rules.
Condition Specs
spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy
Add tests covering a failing non-top-level condition and a non-top-level non-condition to validate the changed condition evaluation behavior.
Snapshots / AST outputs
spock-specs/src/test/resources/snapshots/.../transforms_conditions_in_private_methods.groovy
Replace direct private-method condition invocations with try/catch/finally wrappers around SpockRuntime.verifyMethodCondition to capture failures and preserve finally blocks in rewritten AST snapshots.

Sequence Diagram(s)

sequenceDiagram
    participant Parser as Parser/AST
    participant Rewriter as DeepBlockRewriter
    participant Sentinel as NoSpecialMethodCall
    participant AssertGen as ConditionGenerator

    Parser->>Rewriter: emit ExpressionStatement node
    Note right of Rewriter: determine current block (Then/Expect/Filter)\nand current special-method-call state / interaction depth
    Rewriter->>Sentinel: consult currSpecialMethodCall (INSTANCE / CLOSURE_INSTANCE / other ISpecialMethodCall)
    alt eligible for implicit condition
        Rewriter->>AssertGen: rewrite ExpressionStatement -> Condition node
        AssertGen->>Parser: produce assertion/verification AST
    else not eligible
        Rewriter->>Parser: leave ExpressionStatement unchanged
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • AndreasTu

Poem

I nibbled through nested lines and found the quiet bug,
Turned whispers into signals with a tiny cheerful tug,
I left a new sentinel, I shaped a clearer rule—
Now tests will sing when they fail, hooray from this small fool! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: enabling implicit conditions for non-top-level constructs, which is the core objective of this PR addressing issue #1160.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #1160 by modifying compiler logic to recognize implicit conditions inside non-top-level contexts like if-statements, adding test coverage, and supporting opt-out via the !! operator.
Out of Scope Changes check ✅ Passed All changes are directly related to enabling implicit non-top-level conditions: compiler modifications, test additions, documentation updates, and test file adjustments for the new behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch vampire/implicit-non-top-level-conditions
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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 (2)
spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java (2)

204-208: ⚠️ Potential issue | 🟠 Major

Make the new interaction guard exception-safe.

This branch now depends on insideInteraction and interactionClosureDepth being restored perfectly, but both are still mutated without finally in the surrounding traversal. If rewriting throws while visiting an interaction, leaked state can make later statements look like implicit conditions.

Possible hardening
 private InteractionRewriter visitInteractionAwareExpressionStatement(ExpressionStatement stat) {
   InteractionRewriter rewriter = new InteractionRewriter(resources, getCurrentWithOrMockClosure());
   if (isInteractionExpression(rewriter, stat)) {
     insideInteraction = true;
-    super.doVisitExpressionStatement(stat);
-    insideInteraction = false;
+    try {
+      super.doVisitExpressionStatement(stat);
+    } finally {
+      insideInteraction = false;
+    }
   } else {
     super.doVisitExpressionStatement(stat);
   }
   return rewriter;
 }

 `@Override`
 protected void doVisitClosureExpression(ClosureExpression expr) {
-  if (insideInteraction) interactionClosureDepth++;
-  closureDepth++;
-  super.doVisitClosureExpression(expr);
-  defineRecorders(expr);
-  closureDepth--;
-  if (insideInteraction) interactionClosureDepth--;
+  boolean inInteraction = insideInteraction;
+  if (inInteraction) interactionClosureDepth++;
+  closureDepth++;
+  try {
+    super.doVisitClosureExpression(expr);
+    defineRecorders(expr);
+  } finally {
+    closureDepth--;
+    if (inInteraction) interactionClosureDepth--;
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java`
around lines 204 - 208, The new interaction guard relies on mutable fields
insideInteraction and interactionClosureDepth remaining correctly restored even
if rewriting throws; make this exception-safe by ensuring any mutations to
insideInteraction and interactionClosureDepth in DeepBlockRewriter (the
traversal/visit methods that enter interaction closures) are wrapped so the
previous values are always restored in a finally block (or use a try/finally
helper/RAII-like pattern) around the body that can throw; update the methods
that set these flags (the visit/enter methods handling interaction closures
referenced in the diff) to save the old values, set the new ones, execute the
traversal, and restore the saved values in finally.

204-208: ⚠️ Potential issue | 🟠 Major

interactionClosureDepth == 1 is too broad for interaction-condition detection.

This also matches arbitrary first-level closures inside an interaction argument, e.g. 1 * svc.call(items.every { it > 0 }). In that case it > 0 gets rewritten as a Spock condition even though it lives in an unknown closure, which breaks the promised .every { ... } safety and changes valid interaction code. Please narrow this branch to actual argument-constraint closures and add a regression around a collection-method closure inside an interaction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java`
around lines 204 - 208, The current check in DeepBlockRewriter that treats any
first-level closure inside an interaction as an interaction-condition (using
insideInteraction && interactionClosureDepth == 1) is too broad; update the
condition so it only treats closures that are actual argument-constraint
closures as interaction conditions — i.e., verify the closure node is a direct
argument of the interaction method call and represents a constraint-style
closure (instead of any first-level closure) before rewriting; modify the logic
around insideInteraction and interactionClosureDepth to inspect the parent AST
node (the method call / argument position) to confirm it's the interaction
argument-constraint, and add a regression test that ensures a collection-method
closure inside an interaction like `1 * svc.call(items.every { it > 0 })` is not
rewritten into a Spock condition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java`:
- Around line 204-208: The new interaction guard relies on mutable fields
insideInteraction and interactionClosureDepth remaining correctly restored even
if rewriting throws; make this exception-safe by ensuring any mutations to
insideInteraction and interactionClosureDepth in DeepBlockRewriter (the
traversal/visit methods that enter interaction closures) are wrapped so the
previous values are always restored in a finally block (or use a try/finally
helper/RAII-like pattern) around the body that can throw; update the methods
that set these flags (the visit/enter methods handling interaction closures
referenced in the diff) to save the old values, set the new ones, execute the
traversal, and restore the saved values in finally.
- Around line 204-208: The current check in DeepBlockRewriter that treats any
first-level closure inside an interaction as an interaction-condition (using
insideInteraction && interactionClosureDepth == 1) is too broad; update the
condition so it only treats closures that are actual argument-constraint
closures as interaction conditions — i.e., verify the closure node is a direct
argument of the interaction method call and represents a constraint-style
closure (instead of any first-level closure) before rewriting; modify the logic
around insideInteraction and interactionClosureDepth to inspect the parent AST
node (the method call / argument position) to confirm it's the interaction
argument-constraint, and add a regression test that ensures a collection-method
closure inside an interaction like `1 * svc.call(items.every { it > 0 })` is not
rewritten into a Spock condition.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7e4efe5c-ac53-4d5f-bf40-021d3c7e5cb9

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6342c and 00ed347.

📒 Files selected for processing (8)
  • docs/release_notes.adoc
  • docs/spock_primer.adoc
  • spock-core/src/main/java/org/spockframework/compiler/AbstractDeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java
  • spock-junit4/src/test/groovy/org/spockframework/junit4/junit/JUnitFixtureMethods.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/extension/TempDirExtensionSpec.groovy

@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch from 00ed347 to 789cc32 Compare March 13, 2026 15:37
Copy link

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

🧹 Nitpick comments (1)
spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java (1)

25-26: Consider adding documentation to clarify the distinction.

Both INSTANCE and CLOSURE_INSTANCE are functionally identical NoSpecialMethodCall objects—distinguished only by object identity. This identity distinction is critical for DeepBlockRewriter.handleImplicitCondition (line 204), which uses currSpecialMethodCall == NoSpecialMethodCall.INSTANCE to differentiate top-level blocks from closure scopes.

A brief Javadoc explaining this would help future maintainers understand the design intent.

📝 Suggested documentation
 public class NoSpecialMethodCall implements ISpecialMethodCall {
+  /**
+   * Sentinel instance used for top-level block scope.
+   * Distinguished from {`@link` `#CLOSURE_INSTANCE`} by identity check in
+   * {`@link` DeepBlockRewriter#handleImplicitCondition}.
+   */
   public static final ISpecialMethodCall INSTANCE = new NoSpecialMethodCall();
+  /**
+   * Sentinel instance used inside unrelated closures.
+   * Expressions in closures bound to this instance are not treated as implicit conditions.
+   */
   public static final ISpecialMethodCall CLOSURE_INSTANCE = new NoSpecialMethodCall();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java`
around lines 25 - 26, Add Javadoc to the NoSpecialMethodCall static fields
clarifying that INSTANCE and CLOSURE_INSTANCE are intentionally distinct by
object identity (even though they are functionally identical) so callers can
detect top-level vs closure scopes; specifically document that
DeepBlockRewriter.handleImplicitCondition uses identity comparison
(currSpecialMethodCall == NoSpecialMethodCall.INSTANCE) to recognize top-level
blocks, and that CLOSURE_INSTANCE is used for closure-scoped blocks to prevent
that match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java`:
- Around line 25-26: Add Javadoc to the NoSpecialMethodCall static fields
clarifying that INSTANCE and CLOSURE_INSTANCE are intentionally distinct by
object identity (even though they are functionally identical) so callers can
detect top-level vs closure scopes; specifically document that
DeepBlockRewriter.handleImplicitCondition uses identity comparison
(currSpecialMethodCall == NoSpecialMethodCall.INSTANCE) to recognize top-level
blocks, and that CLOSURE_INSTANCE is used for closure-scoped blocks to prevent
that match.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c814360e-e56e-4d8e-9bd3-53374ccd39d6

📥 Commits

Reviewing files that changed from the base of the PR and between 00ed347 and 789cc32.

📒 Files selected for processing (8)
  • docs/release_notes.adoc
  • docs/spock_primer.adoc
  • spock-core/src/main/java/org/spockframework/compiler/AbstractDeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java
  • spock-junit4/src/test/groovy/org/spockframework/junit4/junit/JUnitFixtureMethods.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/extension/TempDirExtensionSpec.groovy
🚧 Files skipped from review as they are similar to previous changes (2)
  • spock-specs/src/test/groovy/org/spockframework/smoke/extension/TempDirExtensionSpec.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy

@Vampire Vampire force-pushed the vampire/implicit-non-top-level-conditions branch from 789cc32 to 4abd191 Compare March 13, 2026 16:09
Copy link

@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 (1)
spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java (1)

204-208: 🛠️ Refactor suggestion | 🟠 Major

Decouple implicit-condition logic from singleton identity.

The gate at lines 204–208 restricts block-level implicit conditions using currSpecialMethodCall == NoSpecialMethodCall.INSTANCE, but NoSpecialMethodCall remains publicly instantiable. Since INSTANCE and CLOSURE_INSTANCE are behaviorally identical, any fresh new NoSpecialMethodCall() would silently fail the identity check and disable implicit-condition rewriting in then/expect/filter blocks.

Currently the codebase only uses the two static instances, but this design is fragile. Encode the "no special method call" state explicitly (e.g., a dedicated flag or method on ISpecialMethodCall) instead of inferring it from identity checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java`
around lines 204 - 208, The identity check against NoSpecialMethodCall.INSTANCE
is fragile; add an explicit predicate to ISpecialMethodCall (e.g., boolean
isNoSpecialMethodCall()) implemented to return true in NoSpecialMethodCall (both
INSTANCE and CLOSURE_INSTANCE) and false in all other implementations, then
replace the identity check in DeepBlockRewriter (the condition using
currSpecialMethodCall == NoSpecialMethodCall.INSTANCE together with
isThenOrExpectOrFilterBlock()) with
currSpecialMethodCall.isNoSpecialMethodCall() so implicit-condition logic no
longer depends on singleton identity; keep the other branches
(isConditionMethodCall(), isConditionBlock(), isGroupConditionBlock(),
insideInteraction && interactionClosureDepth == 1) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/release_notes.adoc`:
- Around line 11-14: The release note is too broad; change the wording to scope
the behavior to assertion/condition contexts only by clarifying that expression
statements are treated as implicit conditions only in assertion-related contexts
handled by DeepBlockRewriter.handleImplicitCondition — specifically in
then/expect/filter blocks, known condition blocks/methods (e.g.,
`@ConditionBlock`, verifyAll/with), and first-level interaction closures, and not
globally for all expression statements or unknown closures.

---

Outside diff comments:
In `@spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java`:
- Around line 204-208: The identity check against NoSpecialMethodCall.INSTANCE
is fragile; add an explicit predicate to ISpecialMethodCall (e.g., boolean
isNoSpecialMethodCall()) implemented to return true in NoSpecialMethodCall (both
INSTANCE and CLOSURE_INSTANCE) and false in all other implementations, then
replace the identity check in DeepBlockRewriter (the condition using
currSpecialMethodCall == NoSpecialMethodCall.INSTANCE together with
isThenOrExpectOrFilterBlock()) with
currSpecialMethodCall.isNoSpecialMethodCall() so implicit-condition logic no
longer depends on singleton identity; keep the other branches
(isConditionMethodCall(), isConditionBlock(), isGroupConditionBlock(),
insideInteraction && interactionClosureDepth == 1) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd1e7819-cc8f-4486-a5ea-8d4e70ef622f

📥 Commits

Reviewing files that changed from the base of the PR and between 789cc32 and 4abd191.

📒 Files selected for processing (10)
  • docs/release_notes.adoc
  • docs/spock_primer.adoc
  • spock-core/src/main/java/org/spockframework/compiler/AbstractDeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java
  • spock-core/src/main/java/org/spockframework/compiler/NoSpecialMethodCall.java
  • spock-junit4/src/test/groovy/org/spockframework/junit4/junit/JUnitFixtureMethods.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy
  • spock-specs/src/test/groovy/org/spockframework/smoke/extension/TempDirExtensionSpec.groovy
  • spock-specs/src/test/resources/snapshots/org/spockframework/smoke/ast/condition/VerifyAllMethodsAstSpec/transforms_conditions_in_private_methods.groovy
  • spock-specs/src/test/resources/snapshots/org/spockframework/smoke/ast/condition/VerifyMethodsAstSpec/transforms_conditions_in_private_methods.groovy
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/spock_primer.adoc
  • spock-specs/src/test/groovy/org/spockframework/smoke/condition/ConditionEvaluation.groovy

Comment on lines +11 to +14
* It is no longer true that only top-level expression statements are treated as implicit conditions.
Just like within `with { ... }`, `verifyAll { ... }`, `@ConditionBlock` methods, and other places,
each expression statement is now considered an implicit condition, except for statements in unknown
closures.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Scope this note to assertion contexts.

The implementation does not make expression statements implicit globally; DeepBlockRewriter.handleImplicitCondition() still limits this to then/expect/filter, known condition blocks/methods, and first-level interaction closures. As written, “each expression statement” reads broader than the compiler change actually is.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/release_notes.adoc` around lines 11 - 14, The release note is too broad;
change the wording to scope the behavior to assertion/condition contexts only by
clarifying that expression statements are treated as implicit conditions only in
assertion-related contexts handled by DeepBlockRewriter.handleImplicitCondition
— specifically in then/expect/filter blocks, known condition blocks/methods
(e.g., `@ConditionBlock`, verifyAll/with), and first-level interaction closures,
and not globally for all expression statements or unknown closures.

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.

Spock assertion inside if-statement doesn't work

3 participants