Skip to content

feat: add NullOnCircularReference strategy to NullableStrategy#38

Merged
MessiasLima merged 9 commits into
mainfrom
feat/null-on-circular-reference-5388625712608883014
May 8, 2026
Merged

feat: add NullOnCircularReference strategy to NullableStrategy#38
MessiasLima merged 9 commits into
mainfrom
feat/null-on-circular-reference-5388625712608883014

Conversation

@MessiasLima
Copy link
Copy Markdown
Owner

Implemented the NullOnCircularReference strategy to gracefully handle recursive data structures by resolving circular nullable fields to null. This is now the default behavior, replacing the previous Random strategy. Non-nullable circular references continue to throw SomeCircularReferenceException. Existing strategies' behavior regarding circular references remains unchanged.

Fixes #34


PR created automatically by Jules for task 5388625712608883014 started by @MessiasLima

- Added NullOnCircularReference to NullableStrategy
- Updated ResolverChain to break cycles for nullable fields when using this strategy
- Set NullOnCircularReference as the default strategy in SomeConfig
- Updated NullableResolver and Some.kt to support the new strategy
- Added CircularReferenceIntegrationTest and updated existing tests

Co-authored-by: MessiasLima <[email protected]>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the NullOnCircularReference strategy as the new default for handling nullable types in circular dependencies, enabling recursive data structures to resolve to null rather than throwing an exception. The implementation involves updates to ResolverChain, SomeConfig, and NullableResolver. Review feedback identifies a logic error where the circularity check should precede the exception-throwing match, suggests a performance optimization for type comparisons in isCircularIgnoringNullability, and points out potential consistency risks due to redundant strategy state and the mutability of the global configuration.

Comment thread src/main/kotlin/dev/appoutlet/some/core/ResolverChain.kt Outdated
Comment thread src/main/kotlin/dev/appoutlet/some/core/ResolverChain.kt Outdated
Comment thread src/main/kotlin/dev/appoutlet/some/core/ResolverChain.kt Outdated
*/
class NullableResolver(
private val nullableStrategy: NullableStrategy = NullableStrategy.Random(),
private val nullableStrategy: NullableStrategy = NullableStrategy.NullOnCircularReference,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

There is now a redundancy between the nullableStrategy stored in this resolver and the one passed to ResolverChain. If the global defaultConfig is mutated after defaultResolvers has been initialized, these two values will diverge, leading to inconsistent behavior. To ensure consistency, this resolver should ideally retrieve the strategy from the chain parameter during the resolve call.


val defaultResolvers: List<TypeResolver> by lazy { SomeConfig().buildResolvers() }
val defaultConfig: SomeConfig by lazy { SomeConfig() }
val defaultResolvers: List<TypeResolver> by lazy { defaultConfig.buildResolvers() }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Note that defaultResolvers is lazily initialized using the initial state of defaultConfig. Since SomeConfig properties (like nullableStrategy) are mutable, any changes made to defaultConfig after defaultResolvers has been accessed will not be reflected in the existing resolvers. This creates a mismatch where the ResolverChain uses the updated strategy but the resolvers continue using the old one. Consider making SomeConfig immutable or refactoring resolvers to access strategies dynamically from the session context.

google-labs-jules Bot and others added 7 commits May 7, 2026 19:15
- Added NullOnCircularReference to NullableStrategy
- Updated ResolverChain to break cycles for nullable fields when using this strategy
- Set NullOnCircularReference as the default strategy in SomeConfig
- Updated NullableResolver and Some.kt to support the new strategy
- Added CircularReferenceIntegrationTest with proper import ordering
- Updated existing tests for ResolverChain changes

Co-authored-by: MessiasLima <[email protected]>
@MessiasLima MessiasLima changed the title Add NullOnCircularReference strategy to NullableStrategy feat: add NullOnCircularReference strategy to NullableStrategy May 8, 2026
@MessiasLima MessiasLima merged commit 9cb73db into main May 8, 2026
1 check passed
@MessiasLima MessiasLima deleted the feat/null-on-circular-reference-5388625712608883014 branch May 8, 2026 16:45
@github-project-automation github-project-automation Bot moved this from Ready to Done in Some May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Add NullOnCircularReference strategy to NullableStrategy

1 participant