Skip to content

Running dart format on Dart version 3.7.0 creates inconsistent results. #60163

Open
@jpeiffer

Description

@jpeiffer
dart --version

Dart SDK version: 3.7.0 (stable) (Wed Feb 5 04:53:58 2025 -0800) on "macos_arm64"

When running: dart format lib test on the MacOS computer interactively, I get back:

Formatted 7 files (0 changed) in 0.15 seconds.

However, the GitHub Action that runs the similar command but with the flag to fail on formatted file:

dart format --set-exit-if-changed lib test

... results in:

Formatted lib/src/builder/rive_builder.dart
Formatted 5 files (1 changed) in 0.33 seconds.

I updated this action to print the file before and after. Those are pasted below. The difference appears to be the leading whitespace in the final build method. It's not clear why the MacOS / interactive version is doubling up on the tabs but the GitHub Action using the same dart version is using a single tab spacing.

The file count is different because the format is run before the code generation to print out the before / after prior to the build failing. For a true apples-to-apples, this action runs the code generator but still reformats the rive_builder.dart file.

This can be validated using:

Accepted by dart format on MacOS

import 'dart:convert';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:rive/rive.dart';
part 'rive_builder.g.dart';
/// Creates a [Rive] widget.
@jsonWidget
abstract class _RiveBuilder extends JsonWidgetBuilder {
  const _RiveBuilder({
    super.args,
  });
  @override
  _Rive buildCustom({
    ChildWidgetBuilder? childBuilder,
    required BuildContext context,
    required JsonWidgetData data,
    Key? key,
  });
}
class _Rive extends StatelessWidget {
  const _Rive({
    this.alignment = Alignment.center,
    required this.animations,
    required this.antialiasing,
    required this.artboard,
    required this.asset,
    @JsonBuildArg() this.childBuilder,
    this.fit = BoxFit.contain,
    super.key,
    required this.package,
    required this.placeholder,
    required this.rive,
    required this.stateMachines,
    required this.url,
  })  : assert((asset == null && url == null) ||
            (asset == null && rive == null) ||
            (rive == null && url == null)),
        assert(asset != null || rive != null || url != null);
  final Alignment alignment;
  final List<String>? animations;
  final bool? antialiasing;
  final String? artboard;
    required this.artboard,
    required this.animations,
    required this.antialiasing,
    this.fit = BoxFit.contain,
    required this.rive,
  });
  final Alignment alignment;
  final String? artboard;
  final List<String>? animations;
  final bool? antialiasing;
  final BoxFit fit;
  final String rive;
  @override
  _RiveMemoryWidgetState createState() => _RiveMemoryWidgetState();
}
class _RiveMemoryWidgetState extends State<_RiveMemoryWidget> {
  final List<RiveAnimationController> _animations = [];
  late Artboard _artboard;
  @override
  void initState() {
    super.initState();
    final file = RiveFile.import(
      ByteData.sublistView(base64.decode(widget.rive)),
    );
    if (widget.artboard == null) {
      _artboard = file.mainArtboard;
    } else {
      _artboard = file.artboardByName(widget.artboard!)!;
    }
    if (widget.animations?.isNotEmpty == true) {
      for (var name in widget.animations!) {
        final controller = SimpleAnimation(name);
        _artboard.addController(controller);
        _animations.add(controller);
      }
    } else {
      final controller = SimpleAnimation(_artboard.animations.first.name);
      _artboard.addController(controller);
      _animations.add(controller);
    }
  }
  @override
  void dispose() {
    super.dispose();
    for (var controller in _animations) {
      controller.dispose();
    }
  }
  @override
  Widget build(BuildContext context) => Rive(
        artboard: _artboard,
        alignment: widget.alignment,
        antialiasing: widget.antialiasing ?? true,
        fit: widget.fit,
      );
}

Produced by dart format via GH Action

import 'dart:convert';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:rive/rive.dart';
part 'rive_builder.g.dart';
/// Creates a [Rive] widget.
@jsonWidget
abstract class _RiveBuilder extends JsonWidgetBuilder {
  const _RiveBuilder({super.args});
  @override
  _Rive buildCustom({
    ChildWidgetBuilder? childBuilder,
    required BuildContext context,
    required JsonWidgetData data,
    Key? key,
  });
}
class _Rive extends StatelessWidget {
  const _Rive({
    this.alignment = Alignment.center,
    required this.animations,
    required this.antialiasing,
    required this.artboard,
    required this.asset,
    @JsonBuildArg() this.childBuilder,
    this.fit = BoxFit.contain,
    super.key,
    required this.package,
    required this.placeholder,
    required this.rive,
    required this.stateMachines,
    required this.url,
  }) : assert(
         (asset == null && url == null) ||
             (asset == null && rive == null) ||
             (rive == null && url == null),
       ),
       assert(asset != null || rive != null || url != null);
  final Alignment alignment;
  final List<String>? animations;
  final bool? antialiasing;
  final String? artboard;
  final String? asset;
    required this.animations,
    required this.antialiasing,
    this.fit = BoxFit.contain,
    required this.rive,
  });
  final Alignment alignment;
  final String? artboard;
  final List<String>? animations;
  final bool? antialiasing;
  final BoxFit fit;
  final String rive;
  @override
  _RiveMemoryWidgetState createState() => _RiveMemoryWidgetState();
}
class _RiveMemoryWidgetState extends State<_RiveMemoryWidget> {
  final List<RiveAnimationController> _animations = [];
  late Artboard _artboard;
  @override
  void initState() {
    super.initState();
    final file = RiveFile.import(
      ByteData.sublistView(base64.decode(widget.rive)),
    );
    if (widget.artboard == null) {
      _artboard = file.mainArtboard;
    } else {
      _artboard = file.artboardByName(widget.artboard!)!;
    }
    if (widget.animations?.isNotEmpty == true) {
      for (var name in widget.animations!) {
        final controller = SimpleAnimation(name);
        _artboard.addController(controller);
        _animations.add(controller);
      }
    } else {
      final controller = SimpleAnimation(_artboard.animations.first.name);
      _artboard.addController(controller);
      _animations.add(controller);
    }
  }
  @override
  void dispose() {
    super.dispose();
    for (var controller in _animations) {
      controller.dispose();
    }
  }
  @override
  Widget build(BuildContext context) => Rive(
    artboard: _artboard,
    alignment: widget.alignment,
    antialiasing: widget.antialiasing ?? true,
    fit: widget.fit,
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-dart-cliUse area-dart-cli for issues related to the 'dart' command like tool.dart-cli-formatIssues related to the 'dart format' tool

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions