cognitive_complexity 2.0.0
cognitive_complexity: ^2.0.0 copied to clipboard
Algorithmic Cognitive Complexity calculation and Data-Flow analysis library and CLI tools for Dart and Flutter.
2.0.0 #
- Breaking:
ShallowClassification(which gainssiblingStep, below),SplitTier, andControlFlowEscapeTypeare nowfinalclasses withstatic constvalues instead of enums, so new values can be added in minor releases. There is no exhaustiveness guarantee:switchstatements and expressions over them need a default (_) arm..indexis removed;name,values,toString(),label(where it existed), and==on the constants behave as before. shallow: a helper is now classifiedSIBLING_STEPwhen it is one step of a sequence: another callee of the same caller, declared in the same file and enclosing type, shares>= 2leading camelCase name tokens with it (_readProcEnviron/_readProcCwd), two or more share its leading verb (_filterIgnored/_filterWorkspace/_filterOutdated), or one shares its verb and arity (_reportStaleShim/_reportUnknownSubcommand). The verb-and-arity test needs both helpers to span more than one line. Calls on another receiver (other.parse()) are not siblings.SIBLING_STEPtakes precedence over the score-based classifications, so a step that would cost the caller its headroom is still reported with its siblings. LikeZERO_HEADROOM,SIBLING_STEPhelpers are not absorbed into the caller's cumulative score and do not count toward--fail-on-safe-inlineor--only-safe, so the gate only gets looser. AddsShallowFinding.siblingSteps(sibling_stepsin JSON),ShallowReport.siblingStepCount(sibling_step_count), a header count, and aFacts: siblings=[...] stay extractedline.file_split: name cuts by their type cluster, keep sibling types together, and flag inherited import cycles (#182):- A cut whose public type declarations (class, enum, extension type, typedef,
mixin; at least two) make up
>= 50%of its naming lines is named<stem>_models.dartinstead of after its longest declaration, unless a single type holds more than half of the type lines. - After planning, public leaf enums and same-representation extension types
left in the source file are pulled into a cut that moves a sibling, when
that stays within
--target-linesand adds no boundary crossings. Siblings no cut can take get onesibling type(s) … left in …note. - A cut whose copied imports include a barrel that re-exports the source file (directly or through any one re-export hop) gets a warning suggesting moving the declarations the cut uses out of the barrel, and its rationale notes that "0 circular imports" holds only within the plan.
- A copied import whose library merely imports the source file (an existing
cycle the cut carries over) is informational: listed under
inherited_cyclesin JSON. - Text output adds one
Note: N inherited barrel cycle warning(s), M existing import cycle(s) carried over (informational)line under the plan header; the header's0 circular depscovers the plan's own files. - New
SplitCluster.notes/SplitCluster.warnings/SplitCluster.inheritedCycles(JSONnotes/warnings/inherited_cycles, emitted when non-empty) andDeclarationUnit.representationType(JSONrepresentation_type).
- A cut whose public type declarations (class, enum, extension type, typedef,
mixin; at least two) make up
- JSON reports (
ShallowReport.toJson,FileSplitReport.toJson,DataFlowResult.toJson,DeltaSummary.toJson, andcognitive_complexity--max-file-lines --format json) now include'schema_version': 1at the top level.
1.0.0 #
- Breaking: Pruned legacy backward-compatibility aliases, re-export shims,
and internal helper leaks from the public library surface (
api.txt):- Removed
ShallowFinding.callerScoreand the'caller_score'JSON alias (usecallerCumulativeBefore/'caller_cumulative_before'). - Removed the
GitDiffServiceandisExcludedPathre-exports frompackage:cognitive_complexity/cognitive_complexity.dart, and removed thegitServiceparameter from the publicDeltaAnalyzerconstructor (sopackage:analyticais no longer leaked inapi.txt). - Removed dead or internal symbols (
GitHubReporter,SignatureSynthesizer,DataFlowAnalyzer.synthesizer,SplitCluster.writeText,VariableUsage.copyWith,VariableUsage.declarationOffset,DeltaStatus.label,FileSplitAnalyzer.analyzeResolvedUnit,compareBySignificance, andkAskUserPartsPreferenceDirective) from the public entrypoints.
- Removed
- Breaking: Standardized
data_flow --format json(DataFlowResult.toJsonandVariableUsage.toJson) keys to 1-to-1snake_casefield names (start_line,end_line,enclosing_declaration,is_cleanly_extractable,enclosing_score,slice_score_in_place,slice_score_at_root,estimated_enclosing_score_after,extraction_warnings,suggested_signature,is_mutated,declaration_line, andfirst_mutation_line, retaining'file') to matchcognitive_complexity,file_split, andshallow. file_split: Eliminated super-linear cone-merge overhead on dense many-declaration files, guarded against plans that extract 100% of top-level declarations, skips Tier-3partfallback cuts that would leave less than 25% of the file behind, addslargestResultingFileLines,meetsTarget, andhasSurvivingCoupledScc(largest_resulting_file_lines,meets_target, andhas_surviving_coupled_sccin--format json) toFileSplitReport, prints oversized-declaration notes on extracted cuts as well as surviving declarations, and merges top-level getter/setter pairs without losing spans or reference edges.shallow: Weights multi-armswitchexpressions andswitchstatements bymax(0, armCount - 1)when computingstatement_countso lookup-table helpers with 3+ arms are no longer flagged asMICRO_HELPER, excludes mutually recursive call cycles from single-caller candidates, treats unnamedextension on Tdeclarations as library-private (<extension on T>), and counts empty record()parameters as at least 1 effective parameter.data_flow: Preserves transitive generic type parameter bounds in synthesized signatures, marksinputsentries as mutated when reassigned via Dart 3 pattern assignments ((a, b) = ...), detects collectionawait forelements, and ignoresawait/yieldinside nested function closures.
0.4.0 #
- Breaking:
FunctionComplexitygains a requiredcomposition(ComplexityCompositionrecord:branches,nesting,booleanOps,maxDepth) and anisTestEntrypointgetter. cognitive_complexity:--format jsondeclarations now carrycomposition(branches,nesting,boolean_ops,max_depth; the first three sum toscore) andis_test_entrypoint(top-levelmainof a_test.dartfile). New--verbose/-vflag adds aBreakdowncolumn and a[test entrypoint]tag to the text table so a flat score-15 function is distinguishable from a five-deep pyramid. Scores are unchanged.- Breaking:
ShallowFindingalso gainssharedParamSignatureWith,sharedParamCount,paramsSubsetOfExistingType, andsimulationIndex. shallow: findings carry two descriptive parameter facts that point at a remedy other than inlining:shared_param_signature_with/shared_param_count(a same-file declaration sharing>= 4parameter names, suggesting a shared parameter record) andparams_subset_of_existing_type(a same-file type whose instance fields cover>= 4of the parameters, preferring the enclosing type, suggesting that object be passed directly). Text output adds aFacts:line when either is present.shallow: report ordering is now classification, then caller groups ranked by their most significant finding (HIGH_ARITY/SIG_HEAVYbefore helpers that change the caller's score, before+0micro-predicates), then the caller, then simulation order (simulation_index). Within one caller the printed order matches the inline simulation, so aCaller CC: N (base B)line never precedes the sibling that producedN. Previously findings were ordered by estimated lines saved.- Breaking:
ShallowFindinggains five required constructor parameters:effectiveParameterCount,statementCount,callerZone,inlinedCallerScoreIsolated, andheadroomAfterInline. Code that only reads findings fromShallowAnalyzeris unaffected. shallow:MICRO_HELPERnow also fires for helpers with<= 2statements spanning up to 15 body lines, so formatter-wrapped one-liners no longer evade it. The reason text includes the statement count.shallow:HIGH_ARITYis evaluated against the effective parameter count, where record-typed parameters expand to their field count; the reason text reports both (HIGH_ARITY(4 params, 6 effective)). Only inline record type annotations expand, one level deep. A recordtypedefis a type declaration like a class and counts as one parameter, so a domain record passed through a helper is not reported as packing.shallow:CROSS_FILE_SINGLE_CALLERis no longer reported forlib/declarations whose single caller lives inbin/,tool/,example/,web/, orbenchmark/(package layering, not shallow extraction). Other reasons still apply to such helpers. Helpers with atest/caller are, as before, not single-caller candidates at all.shallow: JSON findings gaineffective_parameter_count,statement_count,caller_zone,inlined_caller_score_isolated(caller base score plus this helper's delta, independent of sibling simulation order), andheadroom_after_inline(max_caller_cc - inlined_caller_score). Text output appends[isolated B -> I, headroom H]when sibling absorption made the cumulative score differ from the isolated one.file_split: the extraction planner now measures its remaining budget against the physical file length (imports, comments, and blank lines included) instead of the sum of declaration lines, matching theestimated_remaining_linesit reports. Files that were previously left over--target-lineswith "No clean extraction cuts recommended" now receive cuts.file_split: suggested filenames derive from the largest public declaration in the cut rather than the first one in source order.file_split: a dominator-cone cut whose root declaration(s) merely bridge two or more otherwise-disconnected groups of>= --min-cluster-lineseach is now emitted as one cut per group. Each root joins the group it has the most edges into and undersized groups follow their callers; the bundled cut is kept when the groups would import each other cyclically or would need more@internalwidenings than the bundle. A root that bridges several groups only names its group when it holds at least a third of the group's lines. Rationale readsSub-component of the <root> cone.file_split: the oversized-class note for a surviving declaration now reports its declared supertype and override ratio, e.g.implements StorageAdapter (32/51 members are @override), and when at least half of the members are@overrideit states that the class size is bound by the interface surface instead of advising that static methods be promoted.extends Xis reported the same way; mixins are not.DeclarationUnitgainsmemberCount,overrideMemberCount,supertypeLabel, and anisInterfaceBoundgetter (member_count,override_member_count,supertypein JSON).- Breaking:
file_split --format jsonalways emits a JSON array with one report per analyzed file. Previously a single matching file produced a bare object and zero or several files produced an array. - Breaking:
shallowclassifies a helper whose inlining lands the caller exactly on--max-caller-ccasZERO_HEADROOMinstead ofSAFE_INLINE(ShallowClassification.zeroHeadroom, ranked betweenSAFE_INLINEandFLATTEN_AND_INLINE).SAFE_INLINEnow requires the caller to stay strictly below the ceiling.ZERO_HEADROOMhelpers are not absorbed into the caller's cumulative score for later siblings and do not count toward--fail-on-safe-inlineor--only-safe. Reports gainzero_headroom_countand the text header lists the count.
0.3.0 #
- Breaking:
ShallowFindinggains two required constructor parameters,callerBaseScoreandcallerCumulativeBefore. Code that only reads findings fromShallowAnalyzeris unaffected; code constructingShallowFindingdirectly must pass both. shallow: when several single-caller helpers share one caller, the caller's score was reported as a running cumulative total with no way to recover the caller's real static score. Each finding now reportscaller_base_score(the caller's static score) alongsidecaller_cumulative_before(the simulated score after earlierSAFE_INLINEsiblings were absorbed).caller_scoreis retained as an alias ofcaller_cumulative_before. Text output rendersCaller CC: 6 (base 3) -> 9 after inline (+3)whenever the two differ.cognitive_complexity: with--max-function-lines, the text table and the--git-difftext table now include aLinescolumn, and every violation marker names its trigger, e.g.[VIOLATION: score > 15],[VIOLATION: lines > 60],[VIOLATION: score > 15, lines > 60], or[VIOLATION: increased]under--fail-on-increase. Consumers matching the bare[VIOLATION]token on stdout should match the[VIOLATIONprefix instead. JSON output is unchanged.
0.2.6 #
- Auto-discover default targets when no positional paths are given: Pub
workspace members (
<member>/lib), single-packagelib/, orpackages/*/lib/pkgs/*/libmonorepo layouts. The GitHub Actiontargetsinput now defaults to auto-discovery, so workspace and monorepo callers no longer need a hardcoded target list (#137). - Order
--git-diffdelta tables by review significance in every format (step summary, PR comment,text,json): violations first, then new score descending, then delta descending, then location.DeltaAnalyzer.computeDeltasgainsfailThreshold,maxFunctionLines, andfailOnIncreaseparameters and the comparator is exposed ascompareBySignificance(#53).
0.2.5 #
- Omit zero-complexity (
delta == 0,score == 0) added and removed declarations from--git-diffMarkdown, CLI, and JSON delta tables (unless they trigger--max-function-lines), addDeltaSummary.countRemoved(🗑️), and format added/removedScorecells as_new_ -> **N**andN -> _deleted_. - Add
shallowCLI (dart run cognitive_complexity:shallow) andShallowAnalyzer(ShallowReport,ShallowFinding,ShallowClassification) to detect single-caller shallow helpers (HIGH_ARITY,MICRO_HELPER,SIG_HEAVY,CROSS_FILE_SINGLE_CALLER) and simulate exact nesting-aware caller Cognitive Complexity after re-inlining (SAFE_INLINE,FLATTEN_AND_INLINE,LOAD_BEARING). - Enhance
DataFlowAnalyzerandDataFlowResult(cognitive_complexity:data_flow) with nesting-aware complexity impact metrics (enclosingScore,sliceScoreInPlace,sliceScoreAtRoot,estimatedEnclosingScoreAfter) andextractionWarningswhen a proposed slice requires>= 5input parameters or provides low complexity payoff. - Add opt-in
--max-file-linesand--max-function-linesCLI flags and GitHub Action inputs (max-file-lines,max-function-lines) with--git-diffpragmatic ratchet support (FileLineMetric,FileLineDelta). Disabled (null) by default to preserve full backward compatibility. - Support
// cognitive_complexity:ignore(per-declaration) and// cognitive_complexity:ignore_for_file(file-wide) suppression comment directives viaCommentDirectiveParser. - Add
file_splitCLI (dart run cognitive_complexity:file_split) andFileSplitAnalyzer(analyzeFile/analyzeFiles) to compute acyclic file decomposition cuts targeting coarse<= 800-line subsystems using Tarjan's SCC condensation, immediate dominator cone absorption, dynamic shared-tail diamond re-evaluation, one-shot sufficiency & surplus small-cut re-absorption, zero-crossing sibling cone coalescing,staticmethod promotion and embedded string/asset literal (>75%) detection for oversized classes, multi-file and directory batch execution,--[no-]use-partssupport, and zero-churnexport ... showbarrel generation. - Skip writing the
--comment-outputfile entirely when a run has zero violations and zero complexity increases, so the GitHub Action stays quiet on the PR thread instead of posting an all-zeroes summary comment. The full report still lands in$GITHUB_STEP_SUMMARY. A diff that only improves complexity now also stays quiet. - Add
DeltaSummary.isClean(), the predicate behind that decision. - GitHub Action: when a previously reported PR gets clean, the existing sticky
comment is updated in place to a resolved status (never deleted), and only
a successful run is treated as clean, so a crashed scan can no longer mark
stale findings resolved.
--comment-outputis only requested when the scanner runs ingithubformat against a diff base. - Support
--excludeand--[no-]ignore-generatedCLI options to configure file exclusion and generated code filtering viaPathFilter. - Add
pathFilterparameter toComplexityAnalyzerandDeltaAnalyzer. - Remove noisy GitHub workflow
::warningannotations on non-violating complexity increases, keeping inline annotations reserved for violations (::error) while full deltas remain tracked in step summaries and PR comment tables. - Add
ensure_cli_readme_test.dartto verify CLI--helpdocumentation inREADME.md. - Update GitHub Action documentation in
README.mdto reference modular subdirectory path (packages/cognitive_complexity) and add rendered Action Inputs Reference table.
0.2.4 #
- Fix
action.ymlmonorepo auto-detection to evaluate defaultlibvspackagesexistence against the caller's$GITHUB_WORKSPACEinstead of$ACTION_PATH(#76). - Fix
action.ymlto run the scanner from the caller's$GITHUB_WORKSPACErather than$ACTION_PATH, so relativetargetsand--git-diffresolve against the repository under audit when the action is used from another repository (#76). - Add
--comment-outputand--max-comment-rowsCLI options: with--format=github, write a second report capped to the most significant rows (violations, then increases, then additions) for posting as a PR comment, while the step summary keeps the full table (#49). - Add
commentFileandmaxCommentRowsparameters toGitHubReporter. - Add
max-comment-rowsinput to the GitHub Action (default0= unlimited) to keep sticky comments under GitHub's 65536-character body limit. - Anchor GitHub annotations to the declaration line only, so they render under the function signature instead of after the closing brace (#55).
- Move package into pub workspace monorepo layout under
packages/cognitive_complexity. - Restore root
action.ymlandskills/structure for monorepo workspace.
0.2.3 #
- Replace table truncation notice with inline summary comment linking to step summary.
0.2.2 #
- Fix column wrapping and alignment formatting in markdown report tables.
0.2.1 #
- Add support for GitHub Actions step summary and comment outputs.
0.2.0 #
- Add Data-Flow analysis and helper extraction engine.
0.1.0 #
- Initial release of Cognitive Complexity calculation engine and CLI tool.