dartrics 1.6.1
dartrics: ^1.6.1 copied to clipboard
Citation-anchored Dart code-quality metrics (CK, Halstead, McCabe, Martin, Cognitive) plus Periphery-style unused public-API detection, shaped for AI refactor loops.
Changelog #
1.6.1 #
CLI stream hygiene: log records no longer reach stdout, and an unhandled error prints its stack trace only under --verbose. The version string is now generated from pubspec.yaml. No metric, threshold, report-schema, exit-code, or public-API change.
- CLI: logger records at every level go to stderr. INFO-and-below records used to go to stdout, where they would mix into
--output -report payload. - CLI: an unhandled error prints
Unhandled error: <error>on stderr and exits 70 as before; the stack trace is printed only with-v/--verbose, and in terse form (package:stack_trace). - CLI: options are read through
ArgResults.flag/option/multiOptioninstead of castingArgResults[]. No behaviour change. - Build:
lib/src/version.dartis generated frompubspec.yamlbypackage:build_version(dart run build_runner build). The publicdartricsVersionconstant is unchanged.
1.6.0 #
Unused-detector false positives from --filter, from generated files under analyzer.exclude, and from E.values; two new annotations on unused entries (writeOnly, chainRoots); multi-symbol inspect; and documentation of how the analysed file set is chosen. Findings can disappear on unchanged code. Report schema 1.3 → 1.4, additive. No metric, threshold, or exit-code change.
- Unused detector:
--filteronunused/analyzedropped the configuredunused.roots, so a declaration reached only from a configured root — and everything only it reached — came out as unused as soon as--filterwas passed.--filternow narrows the output only, never what is reachable. - Unused detector: a generated file listed under the root package's
analyzer.exclude:(the common**/*.g.dart/**/*.mocks.dartentries) was silently dropped from the reachability graph, because the analyzer refuses a context for excluded paths. Every edge it carried went with it — an enum constant referenced only from json_serializable's_$XEnumMap, a mock interface'scallused only from.mocks.dart— and those declarations came out as unused. Such files are now resolved through the package that owns them. Generated files inside a nested package keep being skipped. - Unused detector: declarations inside generated files (
.g.dart,.freezed.dart,.mocks.dart,.gen.dart, …) no longer appear in the output. They still contribute edges. flutter_gen'sassets.gen.dart/fonts.gen.dartaccessors, for instance, used to arrive as findings under--snapshot noneand vanish under a cache snapshot, since the snapshot's changed-file set never included generated paths. - Unused detector: reading
E.values(includingE.values.byName(…)) keeps every constant ofEalive. The read reached only the enum type, so constants that are enumerated but never named — an alphabetical index, a picker over every option — came out as unused one by one. unused/analyzewarn on stderr when a run finds no unused declarations whileunused.exclude-exportedistrueand the rootpubspec.yamlsetspublish_to: none. In an app that default roots everything underlib/, so the empty report said nothing about the code. The exit code is unchanged.- Unused detector: an unused field that a constructor assigns through
this.<name>but nothing reads carrieswriteOnly: true(JSON / ai;_write-only_in md,[write-only]on the console, its own SARIF message). Removing one also means removing that parameter and the argument at every call site, unlike a declaration nothing references. Report schema1.3→1.4, additive. - Unused detector: every unused entry carries
chainRoots— the<path>::<scope>of each dead-subgraph root whose deletion cascades to it (JSON / ai; appended in md and on the console). Entries that share a root form one deletion unit, so a chain of twenty files that dies with one widget reads off the report instead of being traced by hand. A declaration nothing dead references names itself; a root can be a private declaration, which has no entry of its own. Report schema1.4, additive. dartrics inspectaccepts several symbols (inspect A.b C.d E) and resolves the project once for all of them. Probing symbols one invocation at a time re-ran the full analysis each time. With more than one symbol,--reporter jsonemits an array of the per-symbol objects and--reporter aiseparates the per-symbol documents with---; a single symbol's output is unchanged.- Documentation:
doc/manual.mdgains "Which files are analysed". The analysed file set comes from the walked paths,dartrics.exclude, and theanalyzer.excludeof the package under analysis;--configsupplies thedartrics:block only, itsanalyzer:block is not read andinclude:is not followed. None of this was written down, so ananalyzer.excludeplaced in a--configfile looked like a silent no-op. - Documentation:
README.mdstates that dartrics needs Dart 3.13 or newer to run and can analyse projects that target an older SDK.
1.5.0 #
Unused-detector false positives, two silent no-ops in the dismiss channel, and a --fatal-warnings gate that disagreed with the report it was reading. Findings can disappear on unchanged code, exit codes flip in both directions, and every MetricViolation.id changes once. Also raises the analyzer toolchain floor and corrects an analyzer-plugin install snippet that never worked. No metric, threshold, or report-schema change.
- Unused detector: invoking a callable object (
obj()where the class declarescall) now creates an edge to thatcallmethod. Previously the method — and every declaration only it read — was reported as unreachable.response-for-classstill excludes callable-object invocations from its invoked-method set, as documented. - Unused detector: an override group travels as one unit. A base declaration overridden by every subclass is no longer reported when the call sites are typed as the subclass; deleting it on that verdict broke the subclass's
@overrideannotations (override_on_non_overriding_member), and--applydid delete it. - New
dartrics: { unused: { roots: ["<path>::<scope>"] } }pins a reachability root to one file, for declarations a framework invokes by naming convention.test/flutter_test_config.dart::testExecutableships pre-seeded. A malformed entry is a usage error (exit 64) rather than a silently-ignored line. See "Keeping a declaration reachable" indoc/manual.md. - Dismissals: a sidecar
file:written relative to the analysis root — the formdoc/manual.mddocuments — matched nothing, for every metric, and was not reported as stale either. Relative paths are now resolved against--rootbefore matching. Absolute entries are unaffected. - Dismissals: an entry naming an id outside the metric catalogue was accepted and silently did nothing. It is now rejected on stderr and dropped, and
dartrics doctorexits 1 on a sidecar entry that names one. In particularunusedis not a dismissable id — it is a reachability verdict; the rejection points atunused: { roots / entry-points / ignore-annotations }instead.dartrics doctorgains--rootto resolve the sidecar path. schemas/dartrics-config.schema.jsongained theunused.rootsandunused.filterkeys.filterwas already honoured by the loader but absent from the schema, so a config using it failed schema validation while dartrics accepted it.- Documentation:
doc/manual.mddocuments theunusedreachability config (exclude-exported,entry-points,ignore-annotations,roots), which had no coverage outside the JSON schema; theunused --applyflag-map row said top-level declarations only, but--applyalso deletes class members. - Documentation: the analyzer-plugin install snippet in
README.mdwasplugins:/dartrics:with no value, which the analysis server rejects asinvalid_section_format— the plugin never loaded for anyone who copied it. It now readsdartrics: ^1.0.0, and says that the constraint is required and that nopubspec.yamldependency is needed. - Dependency floors raised:
analyzer ^14.3.0,analyzer_testing ^0.4.1(dev),analysis_server_plugin ^0.3.22.analyzer_testing0.4.0 renamed its experiment-configuration APIs; dartrics uses onlyAnalysisRuleTest, so no test changed.
Exit-code changes. --fatal-warnings now gates on the findings the report actually shows. CI runs can flip in both directions — re-read the run before adjusting a pipeline.
--fatal-warningsno longer blocks on a dismissed violation. A dismissed entry stays in the report for audit, but it is an accepted, reasoned decision and was still forcing exit 1, which made--strict-dismiss(the documented audit pairing) change nothing about the gate. Runs that were red only because of dismissals turn green; add--strict-dismissto keep blocking on everything.analyze --fatal-warningsnow blocks on unused declarations too. It read only the violation list, so a run that printed dead code still exited 0 whileunused --fatal-warningsexited 1 on the same finding — the same flag meant two things. Runs with unused findings turn red; keep a framework-invoked declaration withunused: { roots: [...] }, or delete it.unused --fatal-warningsgates on the filtered report rather than the pre-filter list. Under--sinceor a snapshot diff it was blocking on findings that never appeared in its own output.MetricViolation.idis computed from the--root-relative path instead of the absolute one. The same violation now carries the same id across checkouts (developer machine vs. CI), andRegressionRow.idfinally matches theMetricViolation.idit documents itself as cross-referencing — the regression side already relativised its paths, so the two hashed different strings and could never agree. Ids change once with this release; loops that track an id across runs re-anchor on the next pass.
1.4.0 #
Toolchain alignment release: tracks Dart 3.13. No metric, threshold, exit-code, or schema change.
- Dependency floor raised: Dart SDK
^3.13.0. Nothing below 3.13 resolves any more; theanalyzer ^14.0.0floor is unchanged. - Dart 3.13 primary constructors are covered by a class-scope regression test:
number-of-methods,weighted-methods-per-class,lcom4,coupling-between-objects, andresponse-for-classreadclass C(final Dep a, final Dep b) { ... }exactly as they read the long form it replaces, so rewriting to the new syntax does not move a score.class-lengthstill reflects the shorter header, which is what that lens measures.
1.3.1 #
dartrics --version and the exported dartricsVersion constant identified 1.3.0 as 1.2.0. No metric, threshold, exit-code, or schema change.
dartricsVersionmatchespubspec.yamlagain. Tooling that gates on the reported version string — not on the resolved pub constraint — read 1.3.0 as 1.2.0 and needs no change beyond upgrading.
1.3.0 #
Cyclomatic and cognitive complexity cover modern Dart 3 syntax, closures become their own records, and unused-detector / regression false positives are fixed. Scores and findings can change on unchanged code; dismissals left without a live finding surface in staleDismissals:. Report schema 1.2 → 1.3, additive; tracks analyzer 14.
dartrics doctorwarns on unknown keys underdartrics:, with a did-you-mean hint.dartrics regression: library scopes match between--beforeand--after, the--beforerevision resolvespackage:imports (no more phantom diffs on identical code), and leftoverdartrics_worktree_*registrations are reclaimed at startup.- Unused detector: operators called only via compound assignment (
acc += v) are no longer flagged;dartrics analyzeruns the unused pass over generated files, matchingdartrics unused(metric records and counts still exclude them); underexclude-exported(the default), public members an exported class inherits from project-internal supertypes count as reachable. - Cyclomatic complexity counts switch-expression arms (the bare
_ =>arm, likedefault:, is not counted),??, and??=; the exhaustive-switch discount now covers enums. Seedoc/calibration.md. - Cognitive complexity scores if-case
whenguards. - Closures are measured as separate function records: scope kind
closure, scope name<enclosing scope>.closure#NwithNthe source-order ordinal — inserting an earlier closure shifts later siblings, so ids and dismissals on closure scopes need re-anchoring. - Report schema
1.2→1.3:ScopeRef.typegainsclosure. Additive. - Dependency floors raised: Dart SDK
^3.11.0,analyzer ^14.0.0,analysis_server_plugin ^0.3.19,analyzer_testing ^0.3.3(dev).
1.2.0 #
Toolchain alignment release: tracks analyzer 13.1.0. No metric, threshold, exit-code, or schema change.
- Dependency floors raised:
analyzer ^13.1.0,analysis_server_plugin ^0.3.16,analyzer_testing ^0.3.0(dev). The deprecatedExtensionTypeDeclaration.primaryConstructorAST getter is replaced with its successornamePart; behaviour is unchanged.
1.1.0 #
An AI-loop fidelity release: the ai report announces per-section totals, --since narrows to the scopes the diff touched, and cognitive complexity stops taxing declarative test registration. Report schema 1.1 → 1.2, additive. No threshold, exit-code, or wire-format-breaking change.
--reporter aiemits acounts:block (violations / unused / staleDismissals / signals) ahead of the sections. All four sections share the- file:entry shape, so agents that grepped to count findings over-counted; totals now read fromcounts:plustruncated:for dropped tails.--limitis documented as what it always was — a per-section cap, not a global one.--since <ref>filters violations to the scopes the diff touched. The filter was file-granular: an untouched function re-surfaced whenever a sibling in the same file changed. Violations now intersectgit diff -U0hunk ranges with the scope span;unused/signalsstay file-granular because they are call-graph-relational — a change elsewhere in the file can legitimately flip them on an untouched declaration. Pure renames (100% similarity, no hunks) no longer surface.- Cognitive complexity applies a test-DSL discount. On
*_test.dartfiles undertest//integration_test/, closures passed as invocation arguments (group()/test()registration callbacks) no longer accrue to the enclosing function — declarative test mains were firing purely on the closure-nesting tax. The function's own control flow and named helpers stay scored. Gate withdartrics: { test: false }; applies to both the CLI engine and the analyzer-plugin rule. Stale-dismissal note:// dartrics:dismiss cognitive-complexitycomments that suppressed the closure-nesting tax on test mains may now be reported as stale — remove them. - Report schema
1.1→1.2:ScopeRefgains an optionalendLine(last line of the declaration, inclusive) — the span--sinceintersects. Additive; pre-1.2 reports re-emit throughdartrics reportunchanged.
1.0.0 #
First stable release. The metric battery, the --reporter ai wire format (# dartrics ai-report v1), the JSON and SARIF schemas, and the embeddable Dart API (FunctionMetric family + dartricsVersion) commit to semver — non-breaking until 2.0.0. No metric, threshold, exit-code, or wire-format change from 0.8.0. The metric catalogue is dartrics rules; the operator reference is doc/manual.md and dartrics manual; the wire formats are in schemas/.
- One-time editorial pass over the 0.x CHANGELOG entries. Verbose originals remain at
pub.dev/packages/dartrics/versions/<version>and ingit log.
0.8.0 #
Correctness release. Several lenses, the coverage reader, the regression diff, and the report writers had edge-case defects; dartrics unused --apply is also narrowed to the deletions it can make safely. No metric default or schema change.
dartrics unused --applynow performs only whole-node deletions. A variable that shares anint x, y, z;declaration with siblings, and enum constants, are reported asunsupportedand left in place for you to remove —--applyno longer rebalances the surrounding commas (which could leave invalid Dart). dartrics surfaces those decisions rather than guessing at them; the unused detector still lists the declaration.- Cyclomatic complexity no longer folds a nested closure into the enclosing function. A lambda's
if/&&/casedecision points were leaking into the value of the function that contained it; nested closures are measured separately, as documented. - lcov branch coverage keys on
(line, block, branch). Two distinct branches that share a line and branch number across different blocks (e.g. an&&that lowers to two blocks) no longer collapse last-write-wins, so the branch-coverage fraction behindcomplexityJustifiedis correct. dartrics regression --root <sub-dir>compares the matching sub-tree on both sides.git worktree addchecks out the whole repository, so the historical side previously analysed the entire repo and normalised paths against the repo root — every scope reported as added + removed. It is now scoped to the sub-directory.- Report output escapes special characters. A free-text field such as a dismiss reason starting with
-or[no longer breaks the re-parsedai/rulesYAML, and a|in a scope name (e.g.operator |) no longer splits the Markdown signals table. - A non-numeric metric threshold raises a config error. A quoted or otherwise non-numeric value (
error: "15", which YAML reads as a string) was silently dropped, so a gate without a built-in default never fired; it is now reported instead of dropped or coerced.
0.7.3 #
Detection-fidelity and discoverability release driven by external agent feedback. No metric, threshold, or schema change.
- Unused detector now follows operator-method calls through
IndexExpression,BinaryExpression, and the operator element onPrefixExpression/PostfixExpression. User-definedoperator [], binary operators (including custom+/==), unary-, and the+reached viac++/c--were previously flagged as unused when their only caller was the textual operator form.==overrides were already kept alive by theObjectdunder auto-root, but theirsignals:fan-in / fan-out (anddartrics inspect ==upstream walk) now reflect the actual call sites. Stale-dismissal note: projects with// dartrics:dismiss unusedcomments suppressing the prior false-positives on those operators may now see those dismissals reported as stale — remove them. dartrics ai-looprepositioned as the operational entry point. Its--helpone-liner now reads "Operational playbook: commands, prompts, dismiss syntax (start here for AI agents).";dartrics --helpgains a footer pointing at it;doc/manual.mdopens with a cross-ref banner; and the README "AI agents — start here" admonition, Quick start block, Subcommands table, and Documentation list all lead withai-loopand reframemanualas the conceptual reference (lens design, decision tree, flag catalogue). Driven by an agent who skippedai-loopbecause the prior blurb read as a recap of the manual.
0.7.2 #
AI-consumer ergonomics release driven by a real dartrics session report from another agent. No metric, threshold, or schema change.
looksCosmetic→cosmeticSplitDetectedindartrics regression. The old name read as a verdict; the detector is a narrow opt-in signal (the cosmetic-split signature) parallel toanalyze'ssignals:block, not a refactor-quality verdict. All reporters now emit# narrow heuristic, not a global verdictalongside the boolean, and the manual reframes the block as a signal rather than a pass/fail.- Stray
// dartrics:dismisscomments no longer silently no-op. WhencommentSourceis off (the default — thedismissals:block is not yet authored) and the run is not--strict-dismiss,analyzescans for dismiss-shaped comments and emits a stderr WARN naming the affected files and the opt-in needed. - Operational protocol step 5 documents
--snapshot none. The snapshot cache rewrites itself every run, so two consecutiveanalyzeruns always reportchangedFiles: 0. The manual now flags this on the verify step. - README directs AI agents to
dartrics manualfirst. The subcommand was hidden behind--help; the README banner makes it the explicit entrypoint for AI consumers. - ACCEPT becomes a first-class decision in the loop diagram and manual. Borderline values on healthy code are now explicitly "no edit, no
// dartrics:dismiss, no punt — move to the next violation," distinct from dismiss (which is a tracked, recurring-reason commitment).
0.7.1 #
Documentation-only release. The 0.7.0 surface — dartrics inspect, the signals: reference block — shipped without matching updates to dartrics manual and dartrics ai-loop. 0.7.1 catches the in-binary walkthroughs up to the released CLI surface. No code, schema, or threshold change.
dartrics ai-loopsample report now carriessignals:andsnapshot:; documents what the agent reads out of it and clarifies thatviolations:/explain:go absent on a clean run whilesignals:keeps emitting. New "The unused-detector loop" section covers theread → inspect → --applyflow.dartrics manualgains a "Signals — reference information, not verdicts" section, an inlinedartrics inspectsubsection, and aninspectentry in the operational protocol flag map.
0.7.0 #
A call-graph release. The element-resolved reachability pass already powering dartrics unused now also surfaces per-declaration fan-in / fan-out reference signals and backs a new dartrics inspect <symbol> subcommand. Signals carry no threshold and no severity — they are reference information, not violations.
- Report schema bumps from
1.0to1.1. Three new top-level fields land in the JSON output:signals,explanations(previously AI / MD only), andstaleDismissals(previously AI only). All additive;additionalProperties: falseis now consistent withtoJsonagain. Seeschemas/dartrics-report.schema.json. - New
dartrics inspect <symbol> [--depth N] [--direction up|down|both]subcommand. Walks upstream callers and / or downstream callees within--depthhops; emits JSON or the YAML-ish AI shape. Homonym methods on different classes stay disambiguated as separate matches. - MD reporter gains
## Signals (reference)and## Stale Dismissalssections. The AI reporter'sunused:block is reframed in-output: entries may be leftover code OR unwired implementations — the framing comments instruct the loop to confirm against intent before acting.
0.6.6 #
A dartrics unused correctness fix. Detection now sees references that live inside machine-generated files. Output changes for any project whose source declarations are reached only from generated code (.g.dart, .freezed.dart, etc.). No CLI flag, exit code, schema, or threshold change.
dartrics unusedreachability now includes references from machine-generated files; previously edges like ariverpod_generatorprovider's reference back to its source function were missing and the source was reported unused. Snapshots and the analyzed-file count still track the handwritten subset only.dartrics analyze's unused output retains the same defect. Surfaced by dogfooding on a multi-moduleriverpod_generatorproject.
0.6.5 #
A README narrative simplification. No metric, threshold, exit-code, or wire-format change.
- Drops the wager and lens paragraphs from
## What it does(duplicateddoc/manual.md's## The premise); the## Documentationentry fordartrics manualnow signposts the design premise.
0.6.4 #
A dead-code cleanup surfaced by dogfooding dartrics on its own source. No metric, threshold, exit-code, or wire-format change.
SourceLocation.toJsonremoved — every serializer that holds aSourceLocationbuilds its own field set inline, so the method had no caller inlib/. Detected by runningdartrics analyzeon dartrics itself.
0.6.3 #
A dartrics unused --apply correctness fix plus two documentation additions. No metric, threshold, exit-code, or wire-format change.
unused --apply --filter fieldnow refuses fields whose name appears as athis.<field>initializing formal on the enclosing class's constructor; previous behaviour broke compilation. NewApplyOutcome.coupledConstructorFormalmarks each refused entry.unused --applyno longer leaks the leading whitespace of a deleted declaration into the next line.doc/manual.md— "Punt" section now names the output channel (natural-language between AI and operator; no comment directive or YAML key); new## Reporters — pick by audiencesection.
0.6.2 #
A documentation-only patch on top of 0.6.1. No metric, threshold, exit-code, or wire-format change.
- Per-file Martin lenses (
efferent-coupling/afferent-coupling/instability) reframed frompolarity: downtopolarity: neutralin docs to match theLibraryMetricdefault; rationale indoc/calibration.md's new "Per-file Martin granularity" section. - README metric tables gain a
Default warningcolumn in place ofNotes; the library-level table tagsinstabilityas informational;## Limitationssurfaces "Per-file Martin granularity".
0.6.1 #
A small documentation-correctness patch on top of 0.6.0. No metric, threshold, exit-code, or wire-format change.
unused --applysummary message rewritten — the previous text claimed methods, fields, and enum values were "not yet auto-deletable" (stale since 0.5.x). Only "removing the last constant of an enum" remains an unsupportedApplyOutcome.unsupportedKindoutcome.
0.6.0 #
A calibration release. Four metrics drop after a citation re-audit, four citations corrected, and the Dart-specific deviations from cited sources consolidate into doc/calibration.md.
Breaking changes #
maximum-nesting-levelremoved — the cited NIST SP 500-235 §4 attribution was incorrect and no peer-reviewed alternative establishes a defect-correlated threshold. The calculator, plugin rule, lint id, config key, and public-API export are gone. Schema'spropertyNames.enumno longer accepts the id.boolean-trapremoved — the McConnell / Bloch attributions were wrong;dart-lang/linter'savoid_positional_boolean_parametersalready covers the ground with a stricter binary threshold.abstractnessanddistance-from-main-sequenceremoved — Martin's "package = release unit" framing has no equivalent in Dart's language model. Rationale indoc/calibration.md.
Citation corrections #
cognitive-complexity— SonarSource 2017 (not 2018); rationale now flags the source as an industry white paper.halstead-volume— Alfadel et al. 2017, 9th IEEE-GCC Conference, not the previously-cited 2018 venue.lcom4— Hitz & Montazeri (1995) introduced the connected-components variant; the "LCOM4" label is a later community convention.martin 1994— full bibliographic citation; the C++ Report attribution that some sources use is incorrect.
Other #
doc/calibration.md— new audit page for selection principles, counting-rule deviations, and off-by-default rationales.- README trimmed by ~58 % (437 → 184 lines); content redistributed to
dartrics manual/dartrics ai-loop/schemas/.
0.5.1 #
A maintenance release. No metric, threshold, exit-code, or wire-format change. Internals modernised against Dart 3.10 idiom, plus a self-application CI gate and a coverage-data docs fix.
- New CI job runs
dartrics analyzeon dartrics itself on every push/PR and fails on warning-level violations. - Coverage-data docs in README /
dartrics manual/dartrics ai-loopnow spell out how to generatecoverage/lcov.info(previously assumed users already had it).
0.5.0 #
A pruning release. Five pieces of dead-or-deferred CLI / model surface come off, plus one payload addition on the regression side.
Breaking changes #
dartrics explain <id>subcommand removed — auto-explain has been default-on since 0.1.0; lookup against a saved JSON report is a directMap<id, violation>build.--no-auto-explainflag removed — auto-explain unconditional. Token-budget control is--limit <n>.--fatal-styleflag removed from every subcommand —Severity.infowas never emitted by any built-in lens.- Per-subcommand option scoping —
--rootand analysis-time flags no longer accepted bydartrics report(drop them from CI scripts). Severity.inforemoved from the public enum — embedder metrics that synthesised it will fail to compile; treat aswarning.
Other #
MetricChange.idfield added — samesha256("<file>|<scope>|<metric>")[..16]asMetricViolation.id, emitted unconditionally so AI loops can correlate sub-threshold drift across runs.
0.4.0 #
Breaking changes #
- Three Dart-shape metrics removed:
widget-tree-depth,null-aware-chain-depth,async-chain-depth. All three were tool-originated lenses without academic anchor; schema'spropertyNames.enumno longer accepts the ids. FunctionMetric.referencesandClassMetric.referencesare now abstract — embedders implementing custom metrics must declareList<String> get references => const [];explicitly when there is no primary citation.
Other #
number-of-methodscites Lorenz & Kidd (1994) and CK (1994);class-lengthcites Beck (1996), Fowler (1999), and Lippert & Roock (2006).
0.3.0 #
Breaking changes #
--explain <metric-id>removed fromdartrics analyzeanddartrics unused— auto-explain is default; for post-hoc lookup usedartrics explain <id> --input report.json.MetricPolarity.upremoved from the enum — no built-in metric used it. Custom embedder metrics that registeredMetricPolarity.upwill fail to compile; treat asneutral.dartrics: { unused: { presets: [...] } }removed — was a no-op since 0.1.0. Schema rejects the key.
Other #
dartrics ai-loopsubcommand added — prints the AI-loop walkthrough; byte-mirrored fromdoc/ai-loop.md.referencesfield added to every built-in metric, surfacing throughdartrics rules, AI / md / SARIF reporters, and the explain blocks.- README rewritten and trimmed (545 → 429 lines).
0.2.2 #
Bugfixes #
maximum-nesting-levelno longer counts named-argument closures (Widget builders, event handlers) as a nesting level.- Summary tables surface snapshot mode and the diff filter so the cache-mode default doesn't render as a regression.
snapshotModeandchangedFileCountadded at the JSON report root (field additions only; AI/JSON header version unchanged).
0.2.1 #
Bugfix #
.pubignore'scoverage/pattern (no leading slash) matched at any depth, so the0.1.0and0.2.0archives shipped withoutlib/src/coverage/coverage_loader.dartandlib/src/coverage/lcov_reader.dart. Anyone who installed from pub.dev hit unresolved-import errors. Pattern is now/coverage/; reinstall to recover.
0.2.0 #
- Public-API unused-code detection switched from a simple-name reference graph to the analyzer's resolved element graph — keyed on canonical
Element.ids. Member granularity added (instance methods, fields, getters / setters, enum values). - New
--filter <kinds>CLI flag and matchingunused: { filter: [...] }YAML key. Seedartrics analyze --help. - Auto-rooting for
@overridemembers, Object dunder names, and members of classes carrying a keep-alive annotation. LibraryElement.exportNamespacenow drives theexcludeExportedroot set.
0.1.0 #
First public release. Ships the function / class / library metric battery (see dartrics rules), the public-API unused detector, the analyzer plugin (function-level rules), the --reporter ai AI-integration surface, and the embeddable Dart API (FunctionMetric family + dartricsVersion). Operator reference in doc/manual.md and dartrics manual; AI-loop walkthrough in doc/ai-loop.md and dartrics ai-loop; wire formats in schemas/. Exit codes sysexits-aligned.