From 1c1a69a3bc8ad22c592417b97c69e646ca8d47ec Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 11 Jun 2024 11:19:32 -0700 Subject: [PATCH] contribute a dart fix declaritive fix --- .github/workflows/ci.yml | 20 ++++++ analysis_options.yaml | 2 + lib/fix_data.yaml | 24 ++++++++ pubspec.yaml | 1 + test/dart_fix_test.dart | 101 +++++++++++++++++++++++++++++++ test_fixes/README.md | 20 ++++++ test_fixes/analysis_options.yaml | 1 + test_fixes/renames.dart | 11 ++++ test_fixes/renames.dart.expect | 11 ++++ 9 files changed, 191 insertions(+) create mode 100644 lib/fix_data.yaml create mode 100644 test/dart_fix_test.dart create mode 100644 test_fixes/README.md create mode 100644 test_fixes/analysis_options.yaml create mode 100644 test_fixes/renames.dart create mode 100644 test_fixes/renames.dart.expect diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e21d2e9..9df2428 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,3 +64,23 @@ jobs: - name: Run Chrome tests - wasm run: dart test --platform chrome --compiler dart2wasm if: always() && steps.install.outcome == 'success' && matrix.sdk == 'dev' + + # Test the contributed `dart fix` fixes. + dart-fix: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + sdk: [main] + steps: + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + with: + sdk: ${{ matrix.sdk }} + - name: Install Dart dependencies + run: dart pub get + - name: Test the declarative fixes + run: dart fix --compare-to-golden + working-directory: test_fixes diff --git a/analysis_options.yaml b/analysis_options.yaml index 3321f3b..7e824f8 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -3,6 +3,8 @@ include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true + exclude: + - test_fixes/** linter: rules: diff --git a/lib/fix_data.yaml b/lib/fix_data.yaml new file mode 100644 index 0000000..ed7232b --- /dev/null +++ b/lib/fix_data.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +# Please add new fixes to the top of the file. For documentation about this file +# format, see https://dart.dev/go/data-driven-fixes. + +version: 1 + +transforms: + # whereNotNull() => nonNulls + # https://github.com/dart-lang/collection/issues/350 + - title: "Replace with 'nonNulls'" + date: 2024-06-11 + element: + uris: [ 'package:collection/collection.dart' ] + inClass: 'IterableNullableExtension' + method: 'whereNotNull' + changes: + - kind: 'replacedBy' + newElement: + uris: [ 'dart:core' ] + inClass: 'NullableIterableExtensions' + getter: 'nonNulls' diff --git a/pubspec.yaml b/pubspec.yaml index 7a92e22..cd7b9fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,4 +13,5 @@ environment: dev_dependencies: dart_flutter_team_lints: ^3.0.0 + path: ^1.9.0 test: ^1.16.0 diff --git a/test/dart_fix_test.dart b/test/dart_fix_test.dart new file mode 100644 index 0000000..01a6fa9 --- /dev/null +++ b/test/dart_fix_test.dart @@ -0,0 +1,101 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +library; + +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +// Used for debugging the test. +const keepTempDir = false; + +void main() { + test("'dart fix' integration", () { + // create temp dir + final tempDir = Directory.systemTemp.createTempSync('test'); + + var sdkVersion = Platform.version; + if (sdkVersion.contains(' ')) { + sdkVersion = sdkVersion.substring(0, sdkVersion.indexOf(' ')); + } + + try { + // set up project + writeFile(tempDir, 'pubspec.yaml', ''' +name: test_project +environment: + sdk: '^$sdkVersion' +dependencies: + collection: + path: ${Directory.current.path} +'''); + final sourceFile = File(p.join('test_fixes', 'renames.dart')); + writeFile( + tempDir, + p.join('lib', sourceFile.name), + sourceFile.readAsStringSync(), + ); + + // run pub get + pubGet(tempDir); + + // dart fix + dartFix(tempDir); + + // verify no analysis issues + dartAnalyze(tempDir); + } finally { + // ignore: dead_code + if (keepTempDir) { + print('dart fix test temp dir: ${tempDir.path}'); + } else { + tempDir.deleteSync(recursive: true); + } + } + }); +} + +void writeFile(Directory dir, String filePath, String contents) { + final file = File(p.join(dir.path, filePath)); + file.parent.createSync(); + file.writeAsStringSync(contents); +} + +void pubGet(Directory dir) { + exec('pub', ['get'], cwd: dir); +} + +void dartFix(Directory dir) { + exec('fix', ['--apply'], cwd: dir); +} + +void dartAnalyze(Directory dir) { + exec('analyze', [], cwd: dir); +} + +void exec(String command, List args, {required Directory cwd}) { + printOnFailure('dart $command ${args.join(', ')}'); + + final result = Process.runSync( + Platform.resolvedExecutable, + [command, ...args], + workingDirectory: cwd.path, + ); + + var out = result.stdout as String; + if (out.isNotEmpty) printOnFailure(out); + out = result.stderr as String; + if (out.isNotEmpty) printOnFailure(out); + + if (result.exitCode != 0) { + fail('dart $command: exitCode ${result.exitCode}'); + } +} + +extension on File { + String get name => p.basename(path); +} diff --git a/test_fixes/README.md b/test_fixes/README.md new file mode 100644 index 0000000..693fff7 --- /dev/null +++ b/test_fixes/README.md @@ -0,0 +1,20 @@ +## What's here? + +For information about the files in this directory, see +https://github.com/flutter/flutter/wiki/Data-driven-Fixes#testing. + +## Organization + +The contents of this directory are used to test the `dart fix` refactorings +offered by this package. See `lib/dart_fix.yaml` for the fix definitions. + +Note that files in this directory are excluded from analysis. + +## Running the dart fix tests + +In order to test the fixes manually: + +```bash +> cd test_fixes +> dart fix --compare-to-golden +``` diff --git a/test_fixes/analysis_options.yaml b/test_fixes/analysis_options.yaml new file mode 100644 index 0000000..d978f81 --- /dev/null +++ b/test_fixes/analysis_options.yaml @@ -0,0 +1 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/test_fixes/renames.dart b/test_fixes/renames.dart new file mode 100644 index 0000000..5dd0a5c --- /dev/null +++ b/test_fixes/renames.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; + +void main() { + final list1 = ['foo', 'bar', null, 'baz']; + // ignore: unused_local_variable + final list2 = list1.whereNotNull(); +} diff --git a/test_fixes/renames.dart.expect b/test_fixes/renames.dart.expect new file mode 100644 index 0000000..c0e9949 --- /dev/null +++ b/test_fixes/renames.dart.expect @@ -0,0 +1,11 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; + +void main() { + final list1 = ['foo', 'bar', null, 'baz']; + // ignore: unused_local_variable + final list2 = list1.nonNulls; +}