dot_shorthand 1.0.0
dot_shorthand: ^1.0.0 copied to clipboard
CLI and analyzer plugin that finds Color.red style references a context type already supplies and rewrites them to the .red dot shorthand form.
dot_shorthand #
What it is #
A command that finds every expression naming a static member, enum value or named constructor where the context type already supplies it.
It rewrites these to dot shorthand form: Color.red becomes .red, Insets.zero becomes .zero, Shape.circle() becomes .circle().
The same engine runs as an analyzer plugin in the editor, showing misses with a quick fix.
How it works #
Command line:
- It takes file or directory paths.
- It walks up to the nearest package manifest and uses that directory as the analysis root.
- It resolves every Dart file under the paths and skips generated sources.
- It computes the context type around each type-qualified member, value or named constructor.
- It keeps the place when the context type is the written type, or a supertype whose constructor of that name redirects to it.
- Scan mode prints the places and exits non zero. Fix mode deletes the type name from the end of each file backwards, rescans the changed files, and prints what is left.
Editor plugin:
- The analysis server loads the plugin from the project's analysis options.
- The rule runs the same engine on each resolved file.
- Each miss shows as a diagnostic.
- The quick fix deletes the type name.
Who changes what #
| Role | Where | What |
|---|---|---|
| Developer | Command line | Scans a codebase or runs fix mode to clean a sweep |
| Tool owner | lib/src/shorthand_visitor.dart |
Construct kinds that carry a context type |
| Tool owner | lib/dot_shorthand.dart |
Path selection, generated file skipping, ignore marker |
| Tool owner | bin/dot_shorthand.dart |
Flags and report shape |
| Tool owner | lib/src/plugin/ |
The analyzer rule and its quick fix |
| Any developer | analysis_options.yaml of a project |
Enables the plugin |
Engineering reference #
Install once per machine:
dart pub global activate dot_shorthand
From a checkout of this repository instead:
dart pub global activate --source path .
Then run it in any project:
dot_shorthand lib test # scan
dot_shorthand --fix lib test # rewrite and rescan
dot_shorthand --format json lib # output as JSON
dot_shorthand --exclude 'lib/legacy/**' lib # skip paths, repeatable
Run it in place without a global install:
dart run bin/dot_shorthand.dart <paths...>
Exit codes: 0 (no findings), 1 (findings found), 2 (invalid path).
| Flag | Effect |
|---|---|
--fix |
Rewrites every finding, then rescans and prints the remainder |
--exclude <glob> |
Skips matching paths, repeatable |
--format json |
Prints findings as JSON instead of one line each |
Ignore marker: a line ending with // dot_shorthand: ignore keeps every finding on that line.
The standard analyzer comments are honoured too: // ignore: prefer_dot_shorthand on the line or the line above keeps that finding, and // ignore_for_file: prefer_dot_shorthand or // ignore_for_file: type=lint keeps the whole file.
Generated files: always skipped: .g.dart, .gen.dart, .freezed.dart, .mocks.dart. Files whose first lines carry the generated-code header are skipped too.
Dart version: dot shorthand requires Dart 3.10 or later. Files with an older language version are skipped.
Context kinds the tool understands:
| Kind | Example |
|---|---|
| Default parameter values | this.status = Status.initial |
| Named and positional arguments | take(Color.red) |
| Typed variable and field declarations | final Color c = Color.red |
| Plain assignments | c = Color.red |
| Constructor field initializers | : _color = Color.red |
| Returns with a declared return type | Color pick() => Color.red |
Equality (== and !=) against a typed left side |
if (c == Color.red) |
| Switch cases and if-case patterns | case Color.red: |
| Conditional branches in a typed position | flag ? Color.red : Color.green |
| Collection elements with a known element type | final List<Color> all = [Color.red] |
| Type arguments fixed by the receiver | target.add(Color.red) where target: List<Color> |
| Fields of a generic class | slot.value = Color.red where slot: Slot<Color> |
Kinds the tool leaves alone:
| Kind | Reason |
|---|---|
| Unnamed constructors | .new(...) reads worse than the type name |
| A written type carrying type arguments | Foo<int>.bar() cannot drop the type name and keep arguments |
| A static member through a supertype | Only known to forward when it is a redirecting constructor |
| An argument whose type comes from the invocation's type parameters | Inferred from the argument, no context to resolve against |
Enum.values |
The shorthand form does not apply |
??, await, yield, cascade positions |
Context type is not read in these positions |
Enable the plugin in a project by adding to analysis_options.yaml:
plugins:
dot_shorthand: ^1.0.0
A path or git source works too:
plugins:
dot_shorthand:
path: ../path/to/dot_shorthand
The rule prefer_dot_shorthand shows misses in the editor. The quick fix works through the analysis server.
On SDK 3.13, dart fix --apply does not apply plugin fixes. Use the CLI --fix for batch rewrites.
When it goes wrong #
| Symptom | Likely cause | What to check |
|---|---|---|
no such path |
A path argument does not exist | The paths passed on the command line |
| The scan finds nothing in a package that needs it | Paths sit outside any pubspec.yaml |
A pubspec.yaml above the given paths |
| The plugin does not load in the editor | Plugin not configured or analysis server needs restart | analysis_options.yaml sits at the package root, restart the analysis server, read the plugin log under .dart_tool/ |
| The scan is slow on a large repo | Every file is resolved | Narrow the paths, or exclude generated and vendored trees |
dot_shorthand_missing_context after a fix |
Context read differently than the compiler | Add // dot_shorthand: ignore to the line, keep the type name |
| Unused imports after a fix | The type name is that import's only use | Run dart fix --apply --code=unused_import |