Repository navigation
Releases: isyll/dart_modernize
Releases · isyll/dart_modernize
Release list
v0.12.0
Fixes found by running the tool over eleven real projects, the Dart 3.13 syntax that was still missing, and a pipeline that can no longer leave code that does not compile. The minimum SDK stays at 3.13.0.
New passes
constructor-shorthands: declares constructors without repeating the class name,Point(...)becomesnew(...),Point.origin()becomesnew origin(),factory Point.fromJsonbecomesfactory fromJson, and enum constructors drop their redundantconst(Dart 3.13).empty-bodies: an empty class, mixin, extension type or extension body{}becomes;(Dart 3.13).future-pause: an awaitedFuture.delayed(d)with no callback becomesFuture.pause(d)(Dart 3.13).wildcard-parameters: unused__and___parameters become_, which can repeat since Dart 3.7.null-aware-calls:if (x != null) x.f();becomesx?.f();, andif (cb != null) cb!();becomescb?.call();.unmodifiable-of, off by default:List.unmodifiable(x)becomesList.unmodifiableOf(x), and the same forMap, when the result keeps its static type.
primary-constructors
- Fixed default values being dropped (
this.port = 8080becamefinal int port, and a nullable field silently lost its default) and optional positional parameters losing their[...]. - Fixed a constructor's doc comment, annotations and comments being deleted. Such a constructor is now left alone, and so is a field with a comment at the end of its line. A comment trailing the line above a member stays with the member it belongs to.
- Now promotes a constructor with
asserts (moved tothis : assert(...);), a field set from a plain parameter in the initializer list (moved onto the field), a named or private constructor (class Vec._(...)), fields declared together (final int x, y;), and enums (enum Planet(final double mass)). - New
super-parameterssetting, off by default, to also promote classes whose constructor forwardssuper.parameters, which covers nearly every Flutter widget. - A non-const class that is or extends an
@immutableclass and keeps an initialized or late field in its body is no longer promoted: the Dart 3.13 lintprefer_const_constructors_in_immutableswrongly asks forconston the result, anddart fixadded one that did not compile.
Other pass fixes
prefer-inferred-typesno longer emits<T>const [...], no longer turnsdouble x = -1(or(1)) into anint, and keeps the type of a field that overrides an inherited member, which would otherwise take the inherited member's type.final-localsnow sees pattern assignments ((a, b) = pair) andfor (x in xs)loops over an existing variable.destructure-for-inanddestructure-localsno longer write a type name the file does not import (and writeprefix.Typefor a prefixed import), and no longer destructure a nullable value or a?.read.super-parametersno longer folds a named parameter into a positional argument or the reverse, keeps the order of positional arguments, keeps: super.named()for a named super constructor, never mixessuper.positionals with positional arguments, and no longer folds an optional parameter whose super parameter has a default.dot-shorthandsno longer shortens a record field returned from anasyncfunction, or an element of a collection passed to a generic call without<...>such asISetConst({...}), where Dart gives no context type. Newconstructorssetting to keep constructor calls written out while still shortening enum values and static members.null-aware-conditionalsno longer breaks a member chain written over several lines.inline-returnno longer moves an initializer whose inferred type depends on its context into areturnwhere that context changes, such as a generic call in anasyncfunction.abstract-final-classesleaves the public API of a published package alone, and keeps the private constructor when the project enablesavoid_classes_with_only_static_members.sort-constructors-firstrespects// ignore: sort_constructors_firstandignore_for_file, and treats a primary constructor body as a constructor (so doessort-members).- A library pinned to an older language version (
// @dart = 2.12) is left alone by every pass.
Pipeline
- With
--verify(the default), every stage is now checked in memory before anything is written. A stage that adds an error has the edits behind it taken back, including when the error lands in another file, and a file several passes edited keeps the passes that are safe. - The final
dart analyzecheck now covers the whole project, not only the changed files, and repeats after each revert. An error it cannot trace reverts the rest of the run, so the tool never leaves an error it caused. - A run that reverts files now prints the normal summary, then the reverted files with the passes behind them and the
--no-<pass>switches to skip them, and exits with code 2 instead of 1. - New warnings and infos are listed at the end, without reverting anything.
- Copies of every file a run may rewrite are saved to
.dart_tool/dart_modernize/backupbefore the first write. A failure puts them back; after a crash, the new--restoredoes. dart formatnow only touches the files the tool changed. New--no-format(orformatunderdisabled:) and--line-length(orline_length:). When formatting breaks a line in a way a lint the project enables then flags (anifbody moving under its condition without braces),dart fixruns once more, so a second run of the tool finds nothing left to do.--checkand--dry-runnow take the finalize steps too (organize imports, sorting, anddart formaton a scratch copy), and list the filesdart fixwould change, so--checkno longer passes when a real run would still change files.- New
--upgrade-sdk, which raises a project's SDK constraint to^3.13.0, runspub get, and removes thefinalandvarthat Dart 3.13 no longer allows on ordinary parameters, before modernizing. - New
options:section in thedart_modernize:configuration to tune a pass, andlint_fixes:to apply chosen lints'dart fixcorrections even when the project does not enable them. - A library whose resolution overflows the stack is skipped and reported instead of crashing the run.
- Faster: a library is resolved once per stage with all its parts, the baseline
dart analyzeruns alongside the stages, and organize-imports reuses the stages' analyzer.--verboseprints how long each stage took. - A compiled executable now finds the Dart SDK (through
DART_SDK,FLUTTER_ROOTor thePATH) and runsdartsubcommands from it instead of relaunching itself. Every GitHub release now ships standalone executables for Linux, macOS and Windows.
Project
- Updated
analyzerto 14.6.0 andtestto 1.33.0. - Added
tool/campaign.dartand a manualReal-project campaignworkflow, which run the tool over pinned public projects and fail on any revert, new error, or non-idempotent second run.
v0.11.1
No behavior change. Dependency updates and a documentation pass.
- Updated
analyzerto 14.3.0,testto 1.32.0,globto 2.2.0,pub_semverto 2.2.1,yamlto 3.1.4, anddart-lang/setup-dartto 1.8.1. - Rewrote the README in plainer language, with many more real before and after examples taken from the test suite. It also fixes what it used to get wrong:
sort-memberswas called the only opt-in pass, whencollection-elementsis off by default too, and its--collection-elementsswitch was missing from the options table. - Fixed
doc/ORDERING.md:cascadesruns in stage 2, not stage 3, and the finalize section now listssort-constructors-firstand the real order of the steps. - Fixed
test/fixtures/README.md, which counted seventeen passes, listed CLI flags that no longer exist, and omitted five passes. It now lists all twenty-two with their--onlynames. - Brought
AGENTS.mdin line with the source tree, and pointed its format command and the pull request template at the same fixture-sparing command CI uses, since a baredart format .rewrites the deliberately unformatted golden fixtures. - Updated the
defaultOffTransformationsandFinalizeTransformationdoc comments, which predatedcollection-elementsandsort-constructors-first. - Added
test/cli/version_sync_test.dart, which fails when thepubspec.yamlversion, the--versionconstant inrunner.dart, and the topCHANGELOG.mdheading disagree. Nothing enforced that before.
v0.11.0
Breaking: the minimum Dart SDK is now 3.13.0, up from 3.12.0. The tool refuses to run on a project whose SDK constraint allows anything older. Primary constructors are stable in 3.13 and the promotion pass emits that syntax, so the floor moved with it rather than leaving one pass silently inert.
- Fixed three bugs in
primary-constructors, all found by running the tool over its own sources:- Promotion deleted a factory or redirecting constructor, because the retained-member loop skipped every constructor instead of only the one being promoted. This could remove public API from a class and still compile.
- A promoted field lost its doc comment, plain comment, and annotations, since only its type and name reach the header. Such a class is now left alone.
- Members left in the class body lost the blank lines between them, and any
//comment written above them.
- Fixed a convergence bug:
private-named-parametersrewrites a constructor into thethis._fieldform thatprimary-constructorspromotes, but promotion ran first, so the class only collapsed on a second run and the pipeline was not idempotent.primary-constructorsnow runs after it. The 3.12 floor had hidden this, because the pass was inert on the test projects. - Primary constructors went stable in Dart 3.13. The
primary-constructorspass now promotesconstclasses too, emitting the constant primary constructor form (class const Point(final int x, final int y)), where before it skipped every class with aconstconstructor. This is safe by construction: Dart already requires every instance field of a const-constructor class to be final, so the header never needsvar, and members left in the class body are copied over unchanged. - The pass still gates on the resolved language version as a second line of defence, even though the validator now rejects sub-3.13 projects up front.
- Added a semantic test that runs the pass over a 3.13 project and re-analyzes the result. Golden files are compared byte for byte but never compiled, and the semantic suite excluded this pass, so primary-constructor output had no compile check anywhere until now.
- Documented the Dart 3.13 lints that
fix-allpicks up from a target project, and whyuse_primary_constructorscannot fight theprimary-constructorspass. - Golden expectation files are now named
<case>.expected.dartinstead of<case>.expected. They were extensionless to keep Dart tooling away from syntax the package's own SDK could not parse; with the floor at 3.13 that no longer applies, and the analyzer and formatter already skiptest/fixtures/**by configuration. - Dropped the 3.12/3.13 dual-pubspec machinery in the test harness now that every fixture project is on 3.13.
- The
modern-syntaxrobustness suite now runs primary constructors too. It pins no bytes, only that the result still compiles and a second run is a no-op, so there was no reason to keep the pass out once its language version was the floor. - Swapped the deprecated
unnecessary_await_in_returnlint, which Dart 3.13 flags, for the newasync_return_with_no_await.
v0.10.0
- #15 Turn sort-members off by default
- #16 Read configuration from analysis_options.yaml
- #17 Explain which passes are cosmetic and which preserve behavior
- #19 Destructure intermediate variables with record/object patterns
- #20 Destructure for-in loop variables with patterns
- #21 Rewrite conditionals into null-aware operators
- #22 Build collections with if/for elements (opt-in, off by default)
- #23 Extend final_locals to for-in loop variables
- #30 Select transformations with --only instead of positional pass names
- #32 Final pre-release audit and cleanup for 0.10.0
v0.9.2
- prefer-inferred-types now removes a duplicated type annotation from a declaration whose initializer is a dot-shorthand constructor, expanding the shorthand to its explicit form:
final Foo a = .new()becomesfinal a = Foo(), andlate final Foo a = .named()becomeslate final a = Foo.named(). Thelatemodifier and thefinal/constkeyword are preserved.
v0.9.1
- Rewrote the README in a plainer, less promotional style.
- Modernized the package's own sources with the tool and simplified the CI workflows. No functional changes.
v0.9.0
v0.8.0
v0.7.4
- Bump analyzer from 14.0.0 to 14.1.0.
v0.7.3
- Dot shorthands now collapse a static member or method on a generic class.
WidgetStateProperty.resolveWith(...)in aWidgetStateProperty<Color?>?
context becomes.resolveWith(...), and a static getter such as
WidgetStateProperty.nonebecomes.none. A static member never uses the
class's type arguments, so the collapse resolves against the same element the
context type already names; previously every generic-owner static was left
qualified.