ciach 0.7.1
ciach: ^0.7.1 copied to clipboard
Dead code detector for Dart and Flutter. Finds unused classes, functions, methods, fields and enum values that nothing references, and removes them.
0.7.1 #
- Restructure the README. (#162)
- A generic class or mixin that only
withorimplementsclauses name is now reported and removed like any other. A type named only in the type arguments of such a class or mixin in a clause, likeTinwith M<T>, is reported in the same run, except with--no-transitive. (#153) - Report unused unnamed extensions and their members in an exported package
and with
--no-public, and label them(private). (#160) - Report unused
callmethods. Before, everycallmethod was skipped, also one that nothing calls. (#151) - With
exported-packages, a member used in unused code and in live code is no longer reported as unused or listed under "Recovered references". (#149) - Scans are faster: the check for uses that the reference search missed takes less time. On a large package, it went from about 110 to 30 seconds. (#139)
--removenow lists the files that it deleted and the declarations that it left empty one per line. Before, it listed them on one line, separated by commas. (#136)--helpand README.md no longer say that a declaration used only from files that--excludeskips is reported. The references in those files count, as they did before. (#136)
0.7.0 #
- Breaking:
--overrides,--operators,--report-tojsonand--unused-union-membersare now one option,--also, and--generated-suffixis replaced by--generated-glob.--fail-publicis gone. Using a removed option is an error that says what to use instead. See MIGRATION.md. (#105) - Breaking:
--transitiveis now on by default: a helper called only by dead code, and a dead cycle, are reported in the same run instead of after a removal and a second run. See MIGRATION.md. (#131) - With
--unused-translations, ciach reports only the unused messages of the gen-l10n template file. Before, it also reported the code gen-l10n writes around them, such as the delegate class, and said to remove it from the ARB file. (#134) - An unused mixin is reported as a
mixin, not aclass, and a member of a private class as private, not public. (#134) - With
-v, an error you can fix yourself, such as a package withoutpub get, no longer comes with a stack trace that reads like a crash. (#134) - ciach no longer runs your lint rules and analyzer plugins, which it doesn't
need. On a Flutter app with an analyzer plugin, a run now takes about a third
less time and much less memory. Your files and what
dart analyzereports stay the same. (#132) --removenow lists the//comments it leaves right above removed code, so you can check whether they still belong. It also deletes an// ignore:,// expect_lint:or// cspell:disable-next-linecomment above or at the end of a removed declaration, which before stayed and applied to the next line. (#129)- ciach now reports an unused class, mixin, extension, extension type or enum
once, instead of also listing each of its members. The same goes for a class
or mixin that only
withorimplementsclauses use. A used enum whose values are all unused is reported once and left in place. (#121) - ciach now reports a class or mixin whose members are all unused and that
only
withorimplementsclauses use, and--removedeletes it and removes it from those clauses. When other code still uses such a type,--removekeeps it empty and lists it in the summary; before, it left it empty without saying so. (#118) --removeno longer breaks a field or variable statement with a comment inside, such asint a = 1, /* note */ b = 2;. Before, it leftint ;behind, or kept a declarator it couldn't cut without saying so. (#128)- New
exported-packagesoption: list the packages that code outside the analysis imports, such as one published to pub.dev, and ciach doesn't report what other packages can import from them.--exportedis gone. (#105) - Unused translations are reported by default when an
l10n.yamlis present. (#105) - An analyzer plugin that
analysis_options.yamlloads by path, and the files thatflutterfire configurewrites, are no longer reported as unused. (#105) - With
-v, ciach suggests an--analysis-rootwhen another package in the repository uses the scanned one through apath:dependency. (#105) --helplists the options in groups. (#105)- If a class, enum, mixin or extension type is mentioned only in doc comments
and has unused members, ciach now reports the type once, and
--removeleaves it alone. Before, ciach reported each unused member, and--removedeleted them and left an empty type. (#116) - In
entry-points, you now write a constructor the way the report shows it:MyWidget.neworMyWidget.named. Before,MyWidget.newmatched nothing and named constructors could not be listed at all.MyWidget.MyWidgetis now an error. (#117) - An
entry-pointsrule for a class or extension type now also keeps its unnamed constructor. Before, ciach still reported that constructor as unused. Named constructors and other members are still checked. (#115) - Add
// ciach:ignorecomments that keep code from being reported or removed. Put one above a declaration or at the end of its line, put// ciach:ignore-startand// ciach:ignore-endaround a range, or keep a whole file with// ciach:ignore-file. (#104) - If a scanned package hasn't had
dart pub get, ciach now stops with exit code 2 and lists that package. Before, it reported code used by that package as unused. (#120) - Stop reporting test calls as declarations.
test(...),group(...)and calls to@isTestfunctions such astestWidgetswere listed as unused or doc-only, and--removecould delete them. (#119) - Add
--formatvaluesazureandteamcity, the default on their service asgithubis on GitHub Actions, andsarif,checkstyleandgitlab(Code Quality) reports for other tools to import. (#103) - On GitHub Actions, GitLab CI and Azure Pipelines, report paths start at the repository root wherever ciach runs from, not only when it runs there. (#103)
- On CI, detected from the environment,
--set-exit-if-changedand--verbosedefault to on, progress to off, and on GitHub Actions--formattogithub;--[no-]cioverrides the detection. (#101) - Report files with nothing but comments and
library,importorpart ofdirectives, in an "Empty files" section. They count toward--set-exit-if-changed, and--removedeletes them with the directives naming them. An empty conditional-import variant is reported for removal by hand. (#100) --transitivealso reports dead cycles: declarations that only reference each other. (#87)- A dead
StatefulWidgetwhoseStateis used elsewhere (say, by aGlobalKey) is report-only:--removedeleted the widget and leftState<Widget>naming a missing type. AStatein another file is now removed with its widget, instead of being left behind the same way. (#87) - Add
--no-exported(exported: false): skip only declarations other packages can import. (#85) - Resolve
package:URIs through.dart_tool/package_config.json, as Dart does, instead of the pubspecs under the root.--removeno longer keeps an emptied file because a path dependency outside the root has a file at the samelib/path. (#92) - Skip entry points and generated files without any configuration:
- Entry points: builder factories, Flutter plugin classes, dart_frog
handlers, Serverpod endpoints, analyzer and custom_lint plugins, and
@JSExportand@reflectiveTestmembers. - Generated files: build_runner and gen-l10n output, and more kinds of generated-code banners (protoc, Pigeon, …).
- New flags:
--no-project-configand--unused-translations. (#86)
- Entry points: builder factories, Flutter plugin classes, dart_frog
handlers, Serverpod endpoints, analyzer and custom_lint plugins, and
- A top-level getter named only in a
showorhidecombinator is no longer reported, so--removeno longer leaves the combinator naming nothing. (#93) - Namesakes in the variants of a conditional import are checked together.
Before, everything outside the default variant was reported, and
--removebroke the build on the other platforms. (#94)
0.6.0 #
- Breaking:
FinderOptions.onProgressis removed; ciach logs throughpackage:logging. (#78) - Recommend
dart install ciachoverdart pub global activatein the README and on the website. (#83) - A failed analysis server request no longer stops the run: the affected code is kept and listed under "Not analyzed". The result goes to stdout, the log to stderr, with more color. (#78)
- Require
glob2.2.0. On 2.1.x,**/flutter_test_config.dartdid not match aflutter_test_config.dartat the package root, so itstestExecutablewas reported as unused. (#75) - Add
--generated-glob <glob>(andgenerated-glob:inciach.yaml): treat matching files as generated, so their references count but nothing in them is reported or removed. For output a suffix can't pick out, likeflutter gen-l10n'slib/l10n/**, which has neither a suffix nor the banner. Unlike--exclude, the files are still opened. (#76) - A member used only through an override, from a file that doesn't import the
member's library, is no longer reported (nor deleted with
--remove). (#79) - Checking a dead member's overrides is much faster: they share its references, so they are no longer queried one by one. (#77)
- Add
--transitive(andtransitive:inciach.yaml): also report declarations referenced only from other findings, which used to take another run after--remove. Each one names the findings that reference it (onlyReferencedFromin-f json). Off by default. (#72) - A reference from inside a declaration's own span no longer keeps it alive, for every kind: a function or method called only by itself is now reported. Classes already worked this way. (#67)
FinderOptionsnormalizesrootPathandanalysisRootPath, and a run throws anArgumentErrorwhen the analysis root doesn't contain the scanned one, so a library caller gets the check the CLI already had. The constructor is no longerconst. (#64)--removedeletes a dead member's overrides along with it, so no@overrideis left overriding nothing. A member is reported but not removed when one of its overrides can't be deleted: a declaring parameter of a primary constructor, or one in a file the run didn't scan. (#63)- Read a field declarator's doc comment and annotations from the statement it
belongs to.
bin@override final int a, b;reported none of its own, so it was checked where an@overridemember is skipped. (#63) - Add
--analysis-root <path>(andanalysis-root:inciach.yaml): count references from a directory wider than the scanned package, so a sibling package that depends on it bypath:keeps what it calls alive. What is scanned, reported and removed is unchanged. A pub workspace needs no setting. (#61)
0.5.0 #
- Read declarations from the analysis server's outline instead of the source
text.
--removedeletes a declaration's doc comment and annotations as the analyzer delimits them: a multi-line annotation goes with it, a//comment above it stays.UnusedDeclarationgainsfullRange. (#53) - Read comments and annotations from the analysis server's semantic tokens.
Dartdoc links in
/** */comments count as doc-only references, and@overrideandvm:entry-pointare detected by annotation, not by text. (#54) - Read the syntax around a reference from the analysis server's selection ranges instead of a built-in lexer. (#55)
- Ask the analysis server about a class's superclass before blocking the
removal of its last constructor: a
StatelessWidgetsubclass is no longer blocked onsuper.key. The built-in Dart lexer is gone. (#56)
0.4.5 #
- Stop reporting (and removing)
testExecutablein aflutter_test_config.dart, which only theflutter testbootstrap calls. (#51) - Add
entry-pointstociach.yaml:{name, glob}rules for a project's own tool-called declarations. A member rule keeps its type;--verbosenames each skipped entry point. - Check
extensions andextension types, which were invisible before: a dead one is removed whole rather than having its members stripped and the shell left behind.-k extensionand-k extension-typeselect them, and members report asExtension.member. (#50) --removedeletes a file it leaves with onlylibrary/import/part oflines and drops the directives naming it;removeDeclarationsreturns aRemovalResult. (#50)
0.4.4 #
- Fix a compiled
ciach(dart install) spawning itself as the analysis server and failing every run. (#44) - Show the analysis server's exit code and stderr when it dies.
0.4.3 #
- Add
--version, and show the version in the--helpheader. The analysis server now sees the real version instead of1.0.0.
0.4.2 #
- Support Dart 3.13 primary constructors: a dead constructor or declaring
parameter in a class header is report-only, since
--removecannot delete part of a header. - Stop reporting a primary constructor's
this : …body part as aClass.thisfinding, and a dead class's declaring parameters separately from the class. - Count only what
--removeactually deletes in its summary.
0.4.1 #
- Fix a constructor reached only through a dot shorthand (
.new(…)), from a file that never names its class, being reported as unused.
0.4.0 #
- Add config file support: any option can be set in a
ciach.yamlin the package root, and the command line overrides it.--config <path>reads one from elsewhere,--no-configignores it. - Add
-v,--verboseto narrate a run on stderr: config used, every setting and the layer it came from, scan phases, what--removetouches. Supersedes--progress. - Fix a comment mentioning
@overrideorvm:entry-pointskipping the declaration below it. (#29) - Add a secondary
textDocument/definitioncheck for zero-reference declarations, so valid uses the reference search misses no longer produce false 'unused' reports. (#26) - Add
--[no-]fail-public(default on):--no-fail-publicstill reports unused public declarations but excludes them from--set-exit-if-changed, so CI fails only on unused private ones. (#23) - Document the
--unused-union-members,--report-tojson,--generated-suffix, and--helpoptions in the README, which existed in the CLI but were missing from the options table. (#22)
0.3.0 #
- Lower the minimum Dart SDK constraint from
^3.12.2to^3.10.0. (#20) - Never report a
toJson()as unused;jsonEncode(obj)calls it by dynamic dispatch, with no source-level reference for the search to see. Opt back in with--report-tojson. (#17) - Add
--generated-suffix(repeatable) to treat extra filename suffixes as generated, on top of the built-in set (*.g.dart,*.freezed.dart, …). (#13) - Open generated files during analysis so a declaration referenced only from generated code is no longer misreported as unused. (#13)
- Fix
--removecorrupting compact single-line enums (enum E { a, b, c }) when removing one or more values. (#11) - Fix
--removedeleting the leading doc/annotation comment and header when removing a value from a compact single-line enum. (#11) - Report a whole dead class as unused, not just its constructor, so
--removedeletes the class instead of stranding it. Detection is conservative: any reference from outside the class keeps it alive. (#10) - Remove a dead
StatefulWidgettogether with its paired privateStatesubclass, soState<DeletedWidget>never dangles. (#10) - Add remove-safety guards:
--removeskips (but still reports) any removal that wouldn't compile — emptying a still-referenced enum, dropping a sole constructor withfinalfields, or dropping a super-forwarding constructor. (#10) - Add opt-in
--unused-union-membersto report sealed types that are only pattern-matched and never constructed. Report-only:--removenever deletes them. (#10) - Skip
callmethods by default; implicit-call references (obj(...)) aren't resolvable, so they were always misreported as unused. (#14) - Report an unused private constructor like any other dead declaration (and
remove it with
--remove); a sole zero-parameterClassName._()also gets a hint suggestingabstract final classto keep a static-only class non-instantiable. (#14) - Fix enum values reached only through
.valuesiteration being reported as unused. (#15) - Fix unused enum values being reported under the
enumkind instead ofenum-value. (#12) - Don't report deserialized freezed union variants as unused; the generated
fromJsonbuilds the concrete subclass directly, bypassing the redirecting factory. (#16)
0.2.0 #
- Add
--removeto delete unused declarations from source after reporting them, with a confirmation prompt;--remove --forceskips the prompt. (#4) - Skip operator overloads (
operator +,operator ==, …) by default — the analysis server can't resolve infix operator syntax back to the declaration, so a used operator was always reported as unused. Pass--operatorsto include them anyway. (#4) - Report declarations referenced only from a dartdoc
[Xxx]comment link as a separate, informational "doc-only" category (intext,json, andgithuboutput) instead of hiding them entirely. Doc-only findings are never deleted by--remove. (#4) - Clarify installation instructions: global activation vs. adding
ciachas a dev dependency. (#4)