WG013: flag catching Throwable or Error in workflow code#75
Conversation
New forbidden-catch-type declarative rule type, alongside forbidden-method and mutable-side-effect-equality: flags catch (Throwable ...)/catch (Error ...) reachable from a workflow entry point, including a multi-catch's individual component types. The SDK uses unchecked Error subclasses internally for cancellation and workflow-task-failure control flow; a bare Throwable/Error catch swallows those signals along with everything else, so there's no legitimate reason for workflow code to catch either directly. A catch clause's caught type is neither a method call nor a constructor call, so no existing CallTarget can match it. CallGraphAnalyzer gains findCaughtTypeMatches, reusing the same path/visiting/context bookkeeping findCallPaths already has (recordMatch, effectiveContext, resolveToSource) without touching search() itself. TemporalRuleSupport.findViolations is refactored to split its filter-and-convert step into a reusable toViolations(List<CallGraphMatch>, ...), so ForbiddenCatchTypeRule shares the same suppressedContexts/requiredContexts handling ForbiddenMethodRule uses instead of a third copy of that logic. Adds docs/rules/WG013.md and CatchThrowableOrErrorRuleTest, covering direct catch, the Error variant, one-hop-through-a-helper, multi-catch component matching, still-firing inside Workflow.sideEffect() (unlike WG001's suppression), not flagging specific checked exceptions, and not flagging inside Activity implementations. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds declarative WG013 support for detecting workflow-reachable ChangesWG013 workflow catch analysis
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant TemporalWorkflowValidator
participant ForbiddenCatchTypeRule
participant CallGraphAnalyzer
participant TemporalRuleSupport
TemporalWorkflowValidator->>ForbiddenCatchTypeRule: Evaluate workflow classes
ForbiddenCatchTypeRule->>CallGraphAnalyzer: Find matching caught types
CallGraphAnalyzer-->>ForbiddenCatchTypeRule: Return reachable matches
ForbiddenCatchTypeRule->>TemporalRuleSupport: Convert matches to violations
TemporalRuleSupport-->>TemporalWorkflowValidator: Return filtered violations
Possibly related issues
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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
`@wogu-temporal/src/test/java/dev/wogu/temporal/CatchThrowableOrErrorRuleTest.java`:
- Around line 170-200: Update flagsTheThrowableComponentOfAMultiCatch to use the
valid multi-catch alternatives IOException | Error instead of IOException |
Throwable, then change the expected call-path frame from catch (Throwable) to
catch (Error). Preserve the test’s single-violation assertion and surrounding
workflow setup.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 54c5ec26-0d57-496f-80cf-5bf6a86be9a6
📒 Files selected for processing (15)
CHANGELOG.mddocs/rules/WG013.mdwogu-temporal/src/main/java/dev/wogu/temporal/ForbiddenCatchTypeRule.javawogu-temporal/src/main/java/dev/wogu/temporal/RuleDefinition.javawogu-temporal/src/main/java/dev/wogu/temporal/RuleDefinitionLoader.javawogu-temporal/src/main/java/dev/wogu/temporal/RuleRegistry.javawogu-temporal/src/main/java/dev/wogu/temporal/TemporalRuleSupport.javawogu-temporal/src/main/java/dev/wogu/temporal/callgraph/CallGraphAnalyzer.javawogu-temporal/src/main/resources/rules/wg013.yamlwogu-temporal/src/test/java/dev/wogu/temporal/CatchThrowableOrErrorRuleTest.javawogu-temporal/src/test/java/dev/wogu/temporal/MutableSideEffectEqualityRuleTest.javawogu-temporal/src/test/java/dev/wogu/temporal/RuleDefinitionLoaderTest.javawogu-temporal/src/test/java/dev/wogu/temporal/RuleDefinitionTest.javawogu-temporal/src/test/java/dev/wogu/temporal/RuleRegistryTest.javawogu-temporal/src/test/java/dev/wogu/temporal/TemporalWorkflowValidatorTest.java
catch (IOException | Throwable t) would never compile: JLS 14.20 forbids a multi-catch alternative that is a subclass of another alternative in the same clause, and IOException is a subclass of Throwable. JavaParser's grammar-level parser doesn't enforce that semantic rule, so the test still passed mechanically despite exercising code no real project could contain. Swapped to IOException | Error (siblings under Throwable, a valid disjoint multi-catch) and updated the expected call-path frame and test name to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New forbidden-catch-type declarative rule type, alongside forbidden-method and mutable-side-effect-equality: flags catch (Throwable ...)/catch (Error ...) reachable from a workflow entry point, including a multi-catch's individual component types. The SDK uses unchecked Error subclasses internally for cancellation and workflow-task-failure control flow; a bare Throwable/Error catch swallows those signals along with everything else, so there's no legitimate reason for workflow code to catch either directly.
A catch clause's caught type is neither a method call nor a constructor call, so no existing CallTarget can match it. CallGraphAnalyzer gains findCaughtTypeMatches, reusing the same path/visiting/context bookkeeping findCallPaths already has (recordMatch, effectiveContext, resolveToSource) without touching search() itself. TemporalRuleSupport.findViolations is refactored to split its filter-and-convert step into a reusable
toViolations(List, ...), so ForbiddenCatchTypeRule shares the same suppressedContexts/requiredContexts handling ForbiddenMethodRule uses instead of a third copy of that logic.
Adds docs/rules/WG013.md and CatchThrowableOrErrorRuleTest, covering direct catch, the Error variant, one-hop-through-a-helper, multi-catch component matching, still-firing inside Workflow.sideEffect() (unlike WG001's suppression), not flagging specific checked exceptions, and not flagging inside Activity implementations.
Summary by CodeRabbit
ThrowableorError(including withinsideEffect/mutableSideEffectcallbacks).catchTypesparameter to configure which caught types are forbidden.wg013rule configuration.