Skip to content

Rename DataClassResolver to ClassResolver and support multiple constructors #46

Description

@MessiasLima

Description

Refactor DataClassResolver into ClassResolver so it can resolve any class with a constructor — not just data classes with a primary constructor. Currently, the resolver fails when a class lacks a primary constructor even if it has secondary constructors that could be used instead.

  • Scope and constraints

    • In scope: Renaming DataClassResolver to ClassResolver, iterating over all constructors, updating SomeConfig, AGENTS.md, imports, KDocs, and adding dedicated unit tests
    • Out of scope: Changing how constructor parameters are resolved (property factories, default values, generic mapping remain unchanged)
    • ClassResolver should remain the last resolver in the chain
    • Must preserve backward-compatible behavior for classes that already work today (primary constructor success path)
  • References

    • Current implementation: src/main/kotlin/dev/appoutlet/some/resolver/DataClassResolver.kt
    • Registration: src/main/kotlin/dev/appoutlet/some/config/SomeConfig.kt (line 134)
    • Integration tests in src/test/kotlin/dev/appoutlet/some/integration/

Scope

  • Rename file DataClassResolver.kt to ClassResolver.kt
  • Rename class DataClassResolver to ClassResolver
  • Update all imports, KDoc references, and instantiations in SomeConfig.kt
  • Update AGENTS.md registration-order list
  • Update any integration test KDocs or comments that name DataClassResolver

Acceptance criteria

  • ClassResolver.canResolve() returns true for classes with at least one accessible constructor (primary or secondary)
  • ClassResolver.canResolve() returns false for types without any constructors (abstract classes, interfaces, etc.)
  • ClassResolver.resolve() iterates over all declared constructors in order, attempting to generate arguments and call callBy() for each
  • If a constructor succeeds, its result is returned immediately
  • Classes with empty constructors (no parameters) are resolved successfully
  • If all constructors fail, a new custom exception SomeInstantiationException is thrown with the class name and a summary of failures
  • The existing primary-constructor success path is preserved (no regression for data classes)
  • Existing integration tests (DataClassIntegrationTest, CircularReferenceIntegrationTest, DefaultValueStrategyIntegrationTest, PropertyFactoryIntegrationTest, GenericsIntegrationTest) continue to pass
  • New unit tests for ClassResolver cover: (a) resolution via primary constructor, (b) resolution via secondary constructor when primary is absent, (c) fallback to secondary constructor when primary fails, (d) exception when all constructors fail, (e) canResolve rejects non-class types, (f) resolution of class with empty constructor
  • Investigate: Can ClassResolver instantiate classes with only private constructors? Document the behavior (success via reflection, failure with specific exception, or canResolve returns false) and add a test that asserts the determined behavior
  • ./gradlew test passes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions