Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dart fix --apply generates duplicate entries for debugFillProperties #55772

Open
bsutton opened this issue May 19, 2024 · 1 comment
Open

dart fix --apply generates duplicate entries for debugFillProperties #55772

bsutton opened this issue May 19, 2024 · 1 comment
Labels
analyzer-quick-fix area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@bsutton
Copy link

bsutton commented May 19, 2024

Dart 3.3.3

When running 'dart fix --apply' where the lint debugFillProperties has been generated, the fix tool creates duplicate entries.

Here is the test file:

import 'dart:io';
import 'dart:math' hide log;

// ignore: import_of_legacy_library_into_null_safe
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fsm2/fsm2.dart' hide State;
import 'package:path/path.dart' as p;
import 'package:pluto_menu_bar/pluto_menu_bar.dart';

import 'src/layout_buttons.dart';
import 'src/page_buttons.dart';
import 'src/providers/current_page.dart';
import 'src/providers/log_provider.dart';
import 'src/providers/svg_page_provider.dart';
import 'src/providers/svg_reload_provider.dart';
import 'src/svg/size.dart' as s;
import 'src/svg/svg_layout.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context, WidgetRef watch) => MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          // This is the theme of your application.
          //
          // Try running your application with "flutter run". You'll see the
          // application has a blue toolbar. Then, without quitting the app, try
          // changing the primarySwatch below to Colors.green and then invoke
          // "hot reload" (press "r" in the console where you ran "flutter run",
          // or simply save your changes to "hot reload" in a Flutter IDE).
          // Notice that the counter didn't reset back to zero; the application
          // is not restarted.
          primarySwatch: Colors.blue,
        ),
        home: const MyHomePage(title: 'FSM2 SMCAT Viewer'),
      );
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({required this.title, super.key});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('title', title));
  }
}

class _MyHomePageState extends State<MyHomePage> {
  late SMCatFolder _smcatFolder;

  GlobalKey scaffoldKey = GlobalKey();

  final largest = s.Size(0, 0);

  int currentPage = -1;

  String logBuffer = '';

  final debugging = false;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          // Here we take the value from the MyHomePage object that was created by
          // the App.build method, and use it to set our appbar title.
          title: Text(widget.title),
        ),
        body: Center(
          // Center is a layout widget. It takes a single child and positions it
          // in the middle of the parent.
          child: Column(
            children: <Widget>[
              PlutoMenuBar(
                menus: getMenus(context),
              ),
              const LayoutButtons(),
              const Expanded(child: SVGLayout()),
              const PageButtons(),
              buildDebugPanel(context)
            ],
          ),
        ),
      );

  Widget buildDebugPanel(BuildContext context) => debugging
      ? Consumer(builder: (context, watch, _) {
          final content = watch(logProvider.state);
          return SizedBox(
              height: 100, child: SingleChildScrollView(child: Text(content)));
        })
      : const SizedBox.shrink();

  List<MenuItem> getMenus(BuildContext context) => [
        MenuItem(
          title: 'File',
          icon: Icons.home,
          children: [
            MenuItem(
              title: 'Open',
              icon: Icons.open_in_new,
              onTap: () => openFile(context),
            ),
            MenuItem(
              title: 'Close',
              onTap: () => exit(1),
            ),
          ],
        ),
      ];

  void message(BuildContext context, String text) {
    // scaffoldKey.currentState.hideCurrentSnackBar();
    ScaffoldMessenger.of(context).hideCurrentSnackBar();

    final snackBar = SnackBar(
      content: Text(text),
    );

    Future.delayed(Duration.zero,
        () => ScaffoldMessenger.of(context).showSnackBar(snackBar));
  }

  Future<void> openFile(BuildContext context) async {
    try {
      final selectedFile = await FilePickerCross.importFromStorage(
          type: FileTypeCross.any, fileExtension: 'smcat');

      _smcatFolder = SMCatFolder(
          folderPath: p.dirname(selectedFile.path),
          basename: SMCatFolder.getBasename(selectedFile.path));
      await _smcatFolder.generateAll(force: null);

      final smcatFile = SMCatFile(selectedFile.path);

      if (context.mounted) {
        context.read(smcatPageProvider).loadPages(_smcatFolder.list);

        context.read(currentPageProvider).currentPage =
            max(0, smcatFile.pageNo - 1);

        await WatchFolder(
            pathTo: _smcatFolder.folderPath,
            extension: 'smcat',
            onChanged: (file, action) async =>
                reload(context, file, action)).watch();
      }
    } on FileSelectionCanceledError catch (_) {
      log('User cancelled the file open');
    }
  }

  int compareFile(SvgFile lhs, SvgFile rhs) => lhs.pageNo - rhs.pageNo;

  Future<void> reload(
    BuildContext context,
    String file,
    FolderChangeAction action,
  ) async {
    log('reloading smcat files');

    final pageProvider = context.read(smcatPageProvider);
    await _smcatFolder.generateAll();

    switch (action) {
      case FolderChangeAction.create:
        pageProvider.add(SMCatFile(file));
        break;
      case FolderChangeAction.modify:
        pageProvider.replace(SMCatFile(file));
        break;
      case FolderChangeAction.move:
        break;
      case FolderChangeAction.delete:
        pageProvider.remove(SMCatFile(file));
        break;
    }

    if (context.mounted) {
      context.read(svgReloadProvider).reload = true;
    }
  }

}

I'm expecting to see the following generated method added to _MyHomePageState:

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<GlobalKey<State<StatefulWidget>>>(
        'scaffoldKey', scaffoldKey));
    properties.add(DiagnosticsProperty<s.Size>('largest', largest));
    properties.add(IntProperty('currentPage', currentPage));
    properties.add(StringProperty('logBuffer', logBuffer));
    properties.add(DiagnosticsProperty<bool>('debugging', debugging));
  }

Here is the result that I get:

@override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<GlobalKey<State<StatefulWidget>>>('scaffoldKey', scaffoldKey));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<s.Size>('largest', largest));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('currentPage', currentPage));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('logBuffer', logBuffer));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('debugging', debugging));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<s.Size>('largest', largest));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('currentPage', currentPage));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('logBuffer', logBuffer));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('debugging', debugging));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<s.Size>('largest', largest));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('currentPage', currentPage));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('logBuffer', logBuffer));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('debugging', debugging));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<s.Size>('largest', largest));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('currentPage', currentPage));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('logBuffer', logBuffer));
  }
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('debugging', debugging));
  }

If there is already a debugFillProperties in the class (as there is for MyHomePage) then it behaves correctly.

@lrhn lrhn added area-dart-cli Use area-dart-cli for issues related to the 'dart' command like tool. dart-cli-fix labels May 19, 2024
@bwilkerson bwilkerson added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. analyzer-quick-fix P2 A bug or feature request we're likely to work on and removed area-dart-cli Use area-dart-cli for issues related to the 'dart' command like tool. dart-cli-fix labels May 20, 2024
@bwilkerson
Copy link
Member

@keertip

@srawlins srawlins added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-quick-fix area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

4 participants