Skip to content

Releases: isyll/dart_modernize

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 10:19

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(...) becomes new(...), Point.origin() becomes new origin(), factory Point.fromJson becomes factory fromJson, and enum constructors drop their redundant const (Dart 3.13).
  • empty-bodies: an empty class, mixin, extension type or extension body {} becomes ; (Dart 3.13).
  • future-pause: an awaited Future.delayed(d) with no callback becomes Future.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(); becomes x?.f();, and if (cb != null) cb!(); becomes cb?.call();.
  • unmodifiable-of, off by default: List.unmodifiable(x) becomes List.unmodifiableOf(x), and the same for Map, when the result keeps its static type.

primary-constructors

  • Fixed default values being dropped (this.port = 8080 became final 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 to this : 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-parameters setting, off by default, to also promote classes whose constructor forwards super. parameters, which covers nearly every Flutter widget.
  • A non-const class that is or extends an @immutable class and keeps an initialized or late field in its body is no longer promoted: the Dart 3.13 lint prefer_const_constructors_in_immutables wrongly asks for const on the result, and dart fix added one that did not compile.

Other pass fixes

  • prefer-inferred-types no longer emits <T>const [...], no longer turns double x = -1 (or (1)) into an int, and keeps the type of a field that overrides an inherited member, which would otherwise take the inherited member's type.
  • final-locals now sees pattern assignments ((a, b) = pair) and for (x in xs) loops over an existing variable.
  • destructure-for-in and destructure-locals no longer write a type name the file does not import (and write prefix.Type for a prefixed import), and no longer destructure a nullable value or a ?. read.
  • super-parameters no 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 mixes super. positionals with positional arguments, and no longer folds an optional parameter whose super parameter has a default.
  • dot-shorthands no longer shortens a record field returned from an async function, or an element of a collection passed to a generic call without <...> such as ISetConst({...}), where Dart gives no context type. New constructors setting to keep constructor calls written out while still shortening enum values and static members.
  • null-aware-conditionals no longer breaks a member chain written over several lines.
  • inline-return no longer moves an initializer whose inferred type depends on its context into a return where that context changes, such as a generic call in an async function.
  • abstract-final-classes leaves the public API of a published package alone, and keeps the private constructor when the project enables avoid_classes_with_only_static_members.
  • sort-constructors-first respects // ignore: sort_constructors_first and ignore_for_file, and treats a primary constructor body as a constructor (so does sort-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 analyze check 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/backup before the first write. A failure puts them back; after a crash, the new --restore does.
  • dart format now only touches the files the tool changed. New --no-format (or format under disabled:) and --line-length (or line_length:). When formatting breaks a line in a way a lint the project enables then flags (an if body moving under its condition without braces), dart fix runs once more, so a second run of the tool finds nothing left to do.
  • --check and --dry-run now take the finalize steps too (organize imports, sorting, and dart format on a scratch copy), and list the files dart fix would change, so --check no longer passes when a real run would still change files.
  • New --upgrade-sdk, which raises a project's SDK constraint to ^3.13.0, runs pub get, and removes the final and var that Dart 3.13 no longer allows on ordinary parameters, before modernizing.
  • New options: section in the dart_modernize: configuration to tune a pass, and lint_fixes: to apply chosen lints' dart fix corrections 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 analyze runs alongside the stages, and organize-imports reuses the stages' analyzer. --verbose prints how long each stage took.
  • A compiled executable now finds the Dart SDK (through DART_SDK, FLUTTER_ROOT or the PATH) and runs dart subcommands from it instead of relaunching itself. Every GitHub release now ships standalone executables for Linux, macOS and Windows.

Project

  • Updated analyzer to 14.6.0 and test to 1.33.0.
  • Added tool/campaign.dart and a manual Real-project campaign workflow, which run the tool over pinned public projects and fail on any revert, new error, or non-idempotent second run.

v0.11.1

Choose a tag to compare

@github-actions github-actions released this 30 Sep 11:51
773c26c

No behavior change. Dependency updates and a documentation pass.

  • Updated analyzer to 14.3.0, test to 1.32.0, glob to 2.2.0, pub_semver to 2.2.1, yaml to 3.1.4, and dart-lang/setup-dart to 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-members was called the only opt-in pass, when collection-elements is off by default too, and its --collection-elements switch was missing from the options table.
  • Fixed doc/ORDERING.md: cascades runs in stage 2, not stage 3, and the finalize section now lists sort-constructors-first and 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 --only names.
  • Brought AGENTS.md in 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 bare dart format . rewrites the deliberately unformatted golden fixtures.
  • Updated the defaultOffTransformations and FinalizeTransformation doc comments, which predated collection-elements and sort-constructors-first.
  • Added test/cli/version_sync_test.dart, which fails when the pubspec.yaml version, the --version constant in runner.dart, and the top CHANGELOG.md heading disagree. Nothing enforced that before.

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 14 Aug 06:50
c809ae5

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-parameters rewrites a constructor into the this._field form that primary-constructors promotes, but promotion ran first, so the class only collapsed on a second run and the pipeline was not idempotent. primary-constructors now 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-constructors pass now promotes const classes too, emitting the constant primary constructor form (class const Point(final int x, final int y)), where before it skipped every class with a const constructor. This is safe by construction: Dart already requires every instance field of a const-constructor class to be final, so the header never needs var, 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-all picks up from a target project, and why use_primary_constructors cannot fight the primary-constructors pass.
  • Golden expectation files are now named <case>.expected.dart instead 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 skip test/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-syntax robustness 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_return lint, which Dart 3.13 flags, for the new async_return_with_no_await.

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 10 Aug 03:49
  • #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

Choose a tag to compare

@github-actions github-actions released this 18 Jul 14:19
  • 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() becomes final a = Foo(), and late final Foo a = .named() becomes late final a = Foo.named(). The late modifier and the final/const keyword are preserved.

v0.9.1

Choose a tag to compare

@github-actions github-actions released this 17 Jul 17:13
  • 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

Choose a tag to compare

@github-actions github-actions released this 17 Jul 13:22
  • #13 Add a --check flag that exits non-zero when changes are needed
  • #14 Refuse to run on a dirty Git tree unless --allow-dirty is passed

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 17 Jul 10:59
  • #9 Generated files without a known suffix get rewritten
  • #10 Re-analyze after editing and roll back files that stop compiling
  • #11 The dart fix step ignores excludes and runs on the whole project
  • #12 Line endings and BOM are not preserved

v0.7.4

Choose a tag to compare

@github-actions github-actions released this 14 Jul 10:25
  • Bump analyzer from 14.0.0 to 14.1.0.

v0.7.3

Choose a tag to compare

@github-actions github-actions released this 13 Jul 11:21
  • Dot shorthands now collapse a static member or method on a generic class.
    WidgetStateProperty.resolveWith(...) in a WidgetStateProperty<Color?>?
    context becomes .resolveWith(...), and a static getter such as
    WidgetStateProperty.none becomes .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.