Skip to content

refactor(packages): reduce cognitive complexity of check licenses - #1757

Open
marcossevilla wants to merge 1 commit into
refactor/cc-test-runnerfrom
refactor/cc-packages
Open

marcossevilla wants to merge 1 commit into
refactor/cc-test-runnerfrom
refactor/cc-packages

Conversation

@marcossevilla

@marcossevilla marcossevilla commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Status

READY

Description

  • PackagesCheckLicensesCommand.run reads as early-return steps: validate options, load the lock file, select dependencies, collect licenses, report. Fetching one dependency's licenses lives in _retrieveLicenses, which throws a private _LicenseRetrievalFailure carrying the message and exit code, caught in one place by run and in one place by _collectLicenses when --ignore-retrieval-failures is set.
  • The four-clause dependency type check becomes an exhaustive switch from PubspecDependencyType to its option name.
  • _composeReport hands the per-package listing to _composeLicenseListing. Counts and their first-seen order are unchanged.
  • resolveWorkspaceDependencies moves its nested visit closure into a private _WorkspaceDependencyCollector with one method each for visiting a package, expanding a workspace entry, parsing a member and ranking dependency types. The walk is still depth-first and the warnings fire under the same conditions.

Found by the full cognitive complexity scan in #1755, which tests VeryGoodOpenSource/very_good_workflows#520. Every function in the touched files now scores 15 or under. Behavior, log output, exit codes and public APIs are unchanged, and no tests were needed because the existing ones already reach every new branch.

Function Before After
PackagesCheckLicensesCommand.run 53 9
_composeReport 21 6
resolveWorkspaceDependencies 24 4

Part of a three-PR cleanup. Once all three merge, the full scan on #1755 passes:

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

🤖 Generated with Claude Code

Comment on lines +402 to +411
class _LicenseRetrievalFailure implements Exception {
/// {@macro license_retrieval_failure}
const new(this.message, this.exitCode);

/// A human friendly description of the failure.
final String message;

/// The exit code to return when the failure is not ignored.
final ExitCode exitCode;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Suggested change
class _LicenseRetrievalFailure implements Exception {
/// {@macro license_retrieval_failure}
const new(this.message, this.exitCode);
/// A human friendly description of the failure.
final String message;
/// The exit code to return when the failure is not ignored.
final ExitCode exitCode;
}
class _LicenseRetrievalFailure(final String message, final ExitCode exitCode) implements Exception;

if (!visited.add(directory.resolveSymbolicLinksSync())) return;
/// Walks a Pub workspace depth-first and collects the dependency names each
/// visited package declares, grouped by declaration kind.
class _WorkspaceDependencyCollector {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

we can extract this into another file

Comment on lines +699 to +707
extension on PubspecDependencyType {
/// The `--dependency-type` option value that selects this dependency type.
String get optionName => switch (this) {
PubspecDependencyType.directMain => 'direct-main',
PubspecDependencyType.directDev => 'direct-dev',
PubspecDependencyType.transitive => 'transitive',
PubspecDependencyType.directOverridden => 'direct-overridden',
};
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this could be a property inside the PubspecDependencyType

Comment on lines +102 to +105
final _visited = <String>{};
final _directMain = <String>{};
final _directDev = <String>{};
final _directOverridden = <String>{};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

could be declared as part of a primary constructor

final directDev = <String>{};
final directMain = <String>{};
final directOverridden = <String>{};
final collector = _WorkspaceDependencyCollector(logger: logger)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this should be injected for testability

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@marcossevilla
marcossevilla changed the base branch from main to refactor/cc-test-runner October 1, 2026 13:41
@marcossevilla
marcossevilla added this pull request to stack #1759 October 1, 2026 13:41
@marcossevilla

Copy link
Copy Markdown
Member Author

@vgvbot /review-pr

@unicoderbot

unicoderbot Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

I'll review the code and share my feedback shortly.

  • Preparing environment
    • Cloning repository
    • Setting up dev environment
  • Reviewing code
  • Posting review

Code review submitted — PR approved.

@unicoderbot unicoderbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a well-executed refactor that reduces cognitive complexity in the check licenses command and workspace dependency resolver while preserving behavior. The decomposition into focused helpers (_validateLicenseOptions, _dependenciesToCheck, _collectLicenses, _retrieveLicenses, _bannedDependenciesFor, _composeLicenseListing) and the _WorkspaceDependencyCollector class is clean, and the private _LicenseRetrievalFailure exception elegantly consolidates the error-handling paths.

I verified behavior preservation on the subtle points:

  • _argResults.rest.firstOrNull ?? '.' matches the earlier length-guarded ternary because the > 1 check throws before this line.
  • The exhaustive switch on PubspecDependencyType to optionName is equivalent to the old four-clause || chain (and will fail to compile if the enum ever gains a case, which is a reasonable tradeoff for exhaustiveness).
  • First-seen ordering in _composeReport is preserved because licenseCount.entries iterates insertion order, matching the previous licenseTypes.toSet() LinkedHashSet behavior.
  • totalLicenseCount = licenseTypes.length equals the previous sum-of-counts since each occurrence contributes one to both.
  • Default bannedLicenseTypes to const <String>{} safely replaces the old != null && contains guard.
  • _WorkspaceDependencyCollector.classify() preserves the directMain > directDev > directOverridden precedence (first iteration with putIfAbsent on an empty map is equivalent to the old unconditional assignment).
  • Progress message format and the \n prefix on ignored-failure logs are both maintained.

No correctness issues found. The three complexity reductions in the PR description are real and the touched test surface should be unchanged.

This branch has not been deployed

No deployments
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.

1 participant