Skip to content

Conversation

@christerswahn
Copy link
Collaborator

@christerswahn christerswahn commented Nov 9, 2025

The class OptionResolution was internal, yet used in a public and overridable method OptionGroup.validateValues.

This PR breaks out a public interface now called OptionResolution and exported from the package. The internal implementation has been moved to OptionResolutionImpl.

Closes [config] OptionResolution is not exported #72

Summary by CodeRabbit

  • Documentation

    • Added documentation comments for option value source types.
  • Refactor

    • Reworked option-resolution internals: introduced an abstract resolution interface plus a concrete implementation and updated exported resolution types for consistent, immutable value/error/source handling; no user-visible behavioral changes.

@coderabbitai
Copy link

coderabbitai bot commented Nov 9, 2025

📝 Walkthrough

Walkthrough

Refactors option resolution by making OptionResolution an abstract interface and adding OptionResolutionImpl as its concrete implementation; updates configuration and option code to use the Impl type and re-exports the abstract option_resolution.dart from the package barrel.

Changes

Cohort / File(s) Summary
Core abstraction
packages/config/lib/src/config/option_resolution.dart, packages/config/lib/src/config/option_resolution_impl.dart
Converted OptionResolution<V> from a concrete final class to an abstract class (getters: value, error, source, plus computed props). Added concrete OptionResolutionImpl<V> with stored fields, constructors (.noValue(), .error()), private ctor and copyWith* helpers.
Configuration implementation
packages/config/lib/src/config/configuration.dart
Replaced all uses, types, returns, and initializations of OptionResolution with OptionResolutionImpl. Updated imports, _config map type, error/preset construction, group aggregation, _getOptionResolution signature, and validation paths to use the Impl type.
Option resolution flow
packages/config/lib/src/config/options.dart
Switched resolution return types and internal helpers to OptionResolutionImpl (e.g., resolveValue, _doResolve, _resolveNamedArg, _resolvePosArg, _resolveEnvVar, _resolveConfigValue, _resolveCustomValue, _resolveDefaultValue). Updated constructors and no-value/error returns to use OptionResolutionImpl.
Barrel & enums
packages/config/lib/src/config/config.dart, packages/config/lib/src/config/source_type.dart, pubspec.yaml
Exported option_resolution.dart from the package barrel. Added documentation comments to ValueSourceType enum values. pubspec.yaml listed in manifest (no content changes described).

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Caller
  participant Configuration as Configuration
  participant Options as Option implementations
  participant Impl as OptionResolutionImpl
  Note over Options,Configuration: Resolution values are produced as OptionResolutionImpl
  Caller->>Configuration: resolve(...)
  Configuration->>Options: option.resolveValue(...)
  Options->>Impl: instantiate OptionResolutionImpl(value / noValue / error)
  Impl-->>Configuration: OptionResolutionImpl
  Configuration-->>Caller: Map<Option, OptionResolutionImpl>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • packages/config/lib/src/config/configuration.dart — ensure all type substitutions, error/preset propagation, and group validation align with the new abstract/impl split.
    • packages/config/lib/src/config/options.dart — verify each resolution branch (arg/env/config/default/custom) constructs/copies OptionResolutionImpl correctly and nullable flows remain safe.
    • packages/config/lib/src/config/option_resolution.dart / option_resolution_impl.dart — confirm the abstract API covers all required getters/computed props and impl matches semantics.

Possibly related PRs

Suggested reviewers

  • nielsenko
  • SandPod

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: creating a public OptionResolution interface, which is the core objective of this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ces-dev

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c2a27f and 44913d5.

📒 Files selected for processing (1)
  • packages/config/lib/src/config/options.dart (9 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: indraneel12
Repo: serverpod/cli_tools PR: 0
File: :0-0
Timestamp: 2025-10-10T08:50:09.902Z
Learning: PR #71 in serverpod/cli_tools adds support for displaying OptionGroup names in CLI usage output. The implementation does NOT include fallback group names or numbered defaults for anonymous groups - it only displays the group.name when present and shows groupless options first without any header.
📚 Learning: 2025-06-12T14:55:38.006Z
Learnt from: christerswahn
Repo: serverpod/cli_tools PR: 47
File: lib/src/config/options.dart:552-567
Timestamp: 2025-06-12T14:55:38.006Z
Learning: The codebase relies on a recent version of `package:args` where `ArgParser.addFlag` accepts the `hideNegatedUsage` parameter.

Applied to files:

  • packages/config/lib/src/config/options.dart
🔇 Additional comments (1)
packages/config/lib/src/config/options.dart (1)

10-10: LGTM! Clean interface-implementation separation.

The refactoring consistently introduces OptionResolutionImpl as the concrete implementation type throughout all internal methods while preserving the abstract OptionResolution interface in the public API (line 68 in OptionGroup.validateValues). Key improvements:

  • All internal resolution methods now explicitly return/use OptionResolutionImpl<V>
  • Proper @internal annotations added to methods exposing the implementation type
  • Subclass overrides in FlagOption and MultiOption correctly updated
  • No breaking changes to the public API surface

This establishes a clean contract: external consumers interact with the OptionResolution interface while internal code operates on the concrete implementation.

Also applies to: 329-330, 337-337, 347-347, 376-376, 383-383, 403-403, 406-480, 485-485, 573-582, 676-689


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.

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 (2)
packages/config/lib/src/config/configuration.dart (1)

7-372: Use OptionResolution when aggregating group values.

We still build the group resolution map with OptionResolutionImpl, which means OptionGroup.validateValues can’t actually switch to the new public OptionResolution interface without hitting generic invariance issues. Please import the interface and type the map (and helper) accordingly so overrides only depend on the exported contract.

-import 'option_resolution_impl.dart';
+import 'option_resolution.dart';
+import 'option_resolution_impl.dart';
@@
-    final optionGroups = <OptionGroup, Map<O, OptionResolutionImpl>>{};
+    final optionGroups = <OptionGroup, Map<O, OptionResolution>>{};
@@
-  void _validateGroups(
-    final Map<OptionGroup, Map<O, OptionResolutionImpl>> optionGroups,
+  void _validateGroups(
+    final Map<OptionGroup, Map<O, OptionResolution>> optionGroups,
   ) {
packages/config/lib/src/config/options.dart (1)

329-373: Return the public interface, not the internal impl.

resolveValue is part of the exported API, so switching its return type to OptionResolutionImpl<V> leaks the internal implementation class you’re trying to keep hidden. Consumers still can’t rely solely on the new OptionResolution interface, and any overrides are now forced to depend on the internal impl, which defeats the goal of this PR. Keep the public signature on the interface and use OptionResolutionImpl only inside the method body.

-  OptionResolutionImpl<V> resolveValue(
+  OptionResolution<V> resolveValue(
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c78b60 and 62bcb5b.

📒 Files selected for processing (6)
  • packages/config/lib/src/config/config.dart (1 hunks)
  • packages/config/lib/src/config/configuration.dart (9 hunks)
  • packages/config/lib/src/config/option_resolution.dart (1 hunks)
  • packages/config/lib/src/config/option_resolution_impl.dart (1 hunks)
  • packages/config/lib/src/config/options.dart (8 hunks)
  • packages/config/lib/src/config/source_type.dart (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: indraneel12
Repo: serverpod/cli_tools PR: 0
File: :0-0
Timestamp: 2025-10-10T08:50:09.902Z
Learning: PR #71 in serverpod/cli_tools adds support for displaying OptionGroup names in CLI usage output. The implementation does NOT include fallback group names or numbered defaults for anonymous groups - it only displays the group.name when present and shows groupless options first without any header.
📚 Learning: 2025-08-07T07:55:17.269Z
Learnt from: christerswahn
Repo: serverpod/cli_tools PR: 57
File: packages/config/test/better_command_runner/default_flags_test.dart:1-1
Timestamp: 2025-08-07T07:55:17.269Z
Learning: In the `config` package, `better_command_runner.dart` is intentionally kept as a separate import (`package:config/better_command_runner.dart`) rather than being re-exported through the main `packages/config/lib/config.dart` barrel file. This separation is by design according to the package maintainer christerswahn.

Applied to files:

  • packages/config/lib/src/config/config.dart
  • packages/config/lib/src/config/configuration.dart
📚 Learning: 2025-06-12T14:55:38.006Z
Learnt from: christerswahn
Repo: serverpod/cli_tools PR: 47
File: lib/src/config/options.dart:552-567
Timestamp: 2025-06-12T14:55:38.006Z
Learning: The codebase relies on a recent version of `package:args` where `ArgParser.addFlag` accepts the `hideNegatedUsage` parameter.

Applied to files:

  • packages/config/lib/src/config/options.dart

Copy link

@nielsenko nielsenko left a comment

Choose a reason for hiding this comment

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

LGTM 👍

I would also have been okay with just making the existing OptionResolution class public.

@christerswahn christerswahn merged commit ed5c5f2 into main Nov 10, 2025
11 checks passed
@christerswahn christerswahn deleted the ces-dev branch November 10, 2025 07:55
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.

3 participants