blob: 45cca7321f1a7c386b7a4e96ddad55df743e43db [file]
// Copyright (c) 2026, 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:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer_testing/package_config_file_builder.dart';
import 'package:linter/src/rules.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../tool/lsp_spec/matchers.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(MigrateTest);
});
}
@reflectiveTest
class MigrateTest extends AbstractLspAnalysisServerTest {
@override
void setUp() {
super.setUp();
registerLintRules();
registerBuiltInFixGenerators();
}
Future<void> test_bumpSdkConstraint() async {
await _setupProject(
pubspecContent: '''
name: test_project
environment:
sdk: '^3.0.0'
''',
);
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.0.0 -> ^3.1.0''',
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.1.0'
''',
);
}
Future<void> test_bumpSdkConstraint_emptyPubspec() async {
await _setupProject(pubspecContent: '');
await _assertMigrationResult(
apply: true,
steps: [MigrationStep.Bump],
expectedSummary: 'No SDK constraints were bumped.',
);
}
Future<void> test_bumpSdkConstraint_multiplePackages() async {
var project1Path = pathContext.join(projectFolderPath, 'project1');
var project2Path = pathContext.join(projectFolderPath, 'project2');
newFile(pathContext.join(project1Path, 'pubspec.yaml'), '''
name: project1
environment:
sdk: '^3.0.0'
''');
newFile(pathContext.join(project2Path, 'pubspec.yaml'), '''
name: project2
environment:
sdk: '^3.2.0'
''');
await initialize();
await _assertMigrationResult(
uris: [Uri.file(project1Path), Uri.file(project2Path)],
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 2 package(s):
- project1: ^3.0.0 -> ^3.1.0
- project2: ^3.2.0 -> ^3.3.0''',
expectedEdit: '''
>>>>>>>>>> project1/pubspec.yaml
name: project1
environment:
sdk: '^3.1.0'
>>>>>>>>>> project2/pubspec.yaml
name: project2
environment:
sdk: '^3.3.0'
''',
);
}
Future<void> test_bumpSdkConstraint_noneBumped() async {
await _setupProject(
pubspecContent: '''
name: test_project
''',
);
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: 'No SDK constraints were bumped.',
);
}
Future<void> test_bumpSdkConstraint_range() async {
await _setupProject(
pubspecContent: '''
name: test_project
environment:
sdk: '>=3.0.0 <4.0.0'
''',
);
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: contains('>=3.0.0 <4.0.0 -> >=3.1.0'),
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '>=3.1.0 <4.0.0'
''',
);
}
Future<void> test_bumpSdkConstraint_skipped() async {
var otherDirPath = convertPath('/other_project');
var otherPubspecPath = pathContext.join(otherDirPath, 'pubspec.yaml');
await _setupProject(
pubspecContent: 'name: other_project',
customPubspecFilePath: otherPubspecPath,
);
await _assertMigrationResult(
steps: [MigrationStep.Bump],
uris: [Uri.file(otherDirPath)],
apply: true,
expectedSummary: contains('- other_project: Skipped (not analyzed)'),
);
}
Future<void> test_dependencyConflict() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
var depPath = convertPath('/dep_package');
newFile(join(depPath, 'pubspec.yaml'), '''
name: dep_package
environment:
sdk: '>=3.0.0 <3.13.0'
''');
newFile(join(depPath, 'lib', 'dep.dart'), '');
var builder = PackageConfigFileBuilder();
builder.add(
name: 'dep_package',
rootFolder: resourceProvider.getFolder(depPath),
);
writeTestPackageConfig(config: builder, languageVersion: '3.12');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
- test_project: Skipped
Incompatible dependencies:
- dep_package
No SDK constraints were bumped.''',
);
}
Future<void> test_dependencyConflict_dart3BackwardsCompatibility() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test
environment:
sdk: '^3.12.0'
''');
var depPath = convertPath('/dep_package');
newFile(join(depPath, 'pubspec.yaml'), '''
name: dep_package
environment:
sdk: '>=2.12.0 <3.0.0'
''');
newFile(join(depPath, 'lib', 'dep.dart'), '');
var builder = PackageConfigFileBuilder();
builder.add(
name: 'dep_package',
rootFolder: resourceProvider.getFolder(depPath),
);
writeTestPackageConfig(config: builder, languageVersion: '3.12');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_dependencyConflict_multiple() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
// dep_package1: Incompatible
var dep1Path = convertPath('/dep_package1');
newFile(join(dep1Path, 'pubspec.yaml'), '''
name: dep_package1
environment:
sdk: '>=3.0.0 <3.13.0'
''');
newFile(join(dep1Path, 'lib', 'dep1.dart'), '');
// dep_package2: Incompatible
var dep2Path = convertPath('/dep_package2');
newFile(join(dep2Path, 'pubspec.yaml'), '''
name: dep_package2
environment:
sdk: '>=3.0.0 <3.13.0'
''');
newFile(join(dep2Path, 'lib', 'dep2.dart'), '');
// dep_package3: Compatible
var dep3Path = convertPath('/dep_package3');
newFile(join(dep3Path, 'pubspec.yaml'), '''
name: dep_package3
environment:
sdk: '>=3.0.0 <4.0.0'
''');
newFile(join(dep3Path, 'lib', 'dep3.dart'), '');
// dep_package4: No pubspec.yaml (ignored)
var dep4Path = convertPath('/dep_package4');
newFile(join(dep4Path, 'lib', 'dep4.dart'), '');
var builder = PackageConfigFileBuilder();
builder.add(
name: 'dep_package1',
rootFolder: resourceProvider.getFolder(dep1Path),
);
builder.add(
name: 'dep_package2',
rootFolder: resourceProvider.getFolder(dep2Path),
);
builder.add(
name: 'dep_package3',
rootFolder: resourceProvider.getFolder(dep3Path),
);
builder.add(
name: 'dep_package4',
rootFolder: resourceProvider.getFolder(dep4Path),
);
writeTestPackageConfig(config: builder, languageVersion: '3.12');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
- test_project: Skipped
Incompatible dependencies:
- dep_package1
- dep_package2
No SDK constraints were bumped.''',
);
}
Future<void> test_dependencyConflict_transitive() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
// direct_dep: Compatible
var directDepPath = convertPath('/direct_dep');
newFile(join(directDepPath, 'pubspec.yaml'), '''
name: direct_dep
environment:
sdk: '>=3.0.0 <4.0.0'
''');
newFile(join(directDepPath, 'lib', 'direct_dep.dart'), '');
// transitive_dep: Incompatible
var transitiveDepPath = convertPath('/transitive_dep');
newFile(join(transitiveDepPath, 'pubspec.yaml'), '''
name: transitive_dep
environment:
sdk: '>=3.0.0 <3.13.0'
''');
newFile(join(transitiveDepPath, 'lib', 'transitive_dep.dart'), '');
var builder = PackageConfigFileBuilder();
builder.add(
name: 'direct_dep',
rootFolder: resourceProvider.getFolder(directDepPath),
);
builder.add(
name: 'transitive_dep',
rootFolder: resourceProvider.getFolder(transitiveDepPath),
);
writeTestPackageConfig(config: builder, languageVersion: '3.12');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
- test_project: Skipped
Incompatible dependencies:
- transitive_dep
No SDK constraints were bumped.''',
);
}
Future<void> test_dryRun() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C(var int x);
C.name(final String s);
}
''');
await initialize();
await _assertMigrationResult(
expectedSummary: '''
Preparatory changes for a version bump:
2 changes would be made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 2 changes
Would bump SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes would be made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
);
}
Future<void> test_error_directoryWithoutPubspec() async {
await initialize();
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [projectFolderUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ErrorCodes.InvalidParams,
message: contains(
"The directory '$projectFolderPath' doesn't contain a 'pubspec.yaml' "
'file.',
),
),
);
}
Future<void> test_error_fileUri() async {
await initialize();
newFile(mainFilePath, '');
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [mainFileUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ErrorCodes.InvalidParams,
message: contains(
"The path '$mainFilePath' doesn't refer to a package or pub workspace"
' directory.',
),
),
);
}
Future<void> test_error_fileUri_multipleWithOneInvalid() async {
await initialize();
newFile(pubspecFilePath, 'name: test_project');
var validUri = projectFolderUri;
var invalidUri = Uri.parse('http://example.com');
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [validUri, invalidUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ServerErrorCodes.invalidFilePath,
message: contains("URI scheme 'http' is not supported"),
),
);
}
Future<void> test_error_invalidPubspec() async {
await initialize();
newFile(pubspecFilePath, 'invalid: [');
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [projectFolderUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ErrorCodes.InvalidParams,
message: contains(
"Failed to parse 'pubspec.yaml' at '$projectFolderPath'",
),
),
);
}
Future<void> test_error_nonExistentDirectory() async {
await initialize();
var dirUri = Uri.file(convertPath('/non/existent/dir'));
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [dirUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ErrorCodes.InvalidParams,
message: contains("doesn't exist"),
),
);
}
Future<void> test_error_workspacePackage() async {
await initialize();
newFile(pubspecFilePath, '''
name: test_project
resolution: workspace
''');
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(uris: [projectFolderUri], apply: true),
);
var response = await sendRequestToServer(request);
expect(
response.error,
isResponseError(
ErrorCodes.InvalidParams,
message: contains(
"The directory '$projectFolderPath' is part of a workspace and can't "
'be migrated independently.',
),
),
);
}
Future<void> test_fullMigration_313() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C(final int x);
C.name(final String s);
}
''');
await initialize();
await _assertMigrationResult(
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 2 changes
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new(int x);
new name(String s);
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_fullMigration_313_multiplePackages() async {
failTestOnErrorDiagnostic = false;
var otherPackagePath = convertPath('/home/other_package');
var otherPubspecPath = join(otherPackagePath, 'pubspec.yaml');
var otherFilePath = join(otherPackagePath, 'lib', 'other.dart');
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C(var int x);
}
''');
newFile(otherPubspecPath, '''
name: other_package
environment:
sdk: '^3.12.0'
''');
newFile(otherFilePath, '''
class D {
D(final int y);
}
''');
await initialize(
workspaceFolders: [projectFolderUri, toUri(otherPackagePath)],
);
await _assertMigrationResult(
uris: [projectFolderUri, toUri(otherPackagePath)],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 2 files.
my_project/lib/main.dart
extraneous_modifier • 1 change
other_package/lib/other.dart
extraneous_modifier • 1 change
Bumped SDK constraints in 2 package(s):
- test_project: ^3.12.0 -> ^3.13.0
- other_package: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 2 files.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 1 change
other_package/lib/other.dart
unnecessary_type_name_in_constructor • 1 change''',
expectedEdit: '''
>>>>>>>>>> ../other_package/lib/other.dart
class D {
new(int y);
}
>>>>>>>>>> ../other_package/pubspec.yaml
name: other_package
environment:
sdk: '^3.13.0'
>>>>>>>>>> lib/main.dart
class C {
new(int x);
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_postMigration_313() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C();
C.name();
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump, MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new();
new name();
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_313() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x, var y) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 2 changes
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x, y) {}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_313_multipleFiles() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
var otherFilePath = join(projectFolderPath, 'lib', 'other.dart');
newFile(mainFilePath, 'void m(final int x) {}\n');
newFile(otherFilePath, 'void f(var y) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 2 files.
my_project/lib/main.dart
extraneous_modifier • 1 change
my_project/lib/other.dart
extraneous_modifier • 1 change
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x) {}
>>>>>>>>>> lib/other.dart
void f(y) {}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_313_multiplePackages() async {
failTestOnErrorDiagnostic = false;
var otherPackagePath = convertPath('/home/other_package');
var otherPubspecPath = join(otherPackagePath, 'pubspec.yaml');
var otherFilePath = join(otherPackagePath, 'lib', 'other.dart');
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x) {}\n');
newFile(otherPubspecPath, '''
name: other_package
environment:
sdk: '^3.12.0'
''');
newFile(otherFilePath, 'void f(var y) {}\n');
await initialize(
workspaceFolders: [projectFolderUri, toUri(otherPackagePath)],
);
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
uris: [projectFolderUri, toUri(otherPackagePath)],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 2 files.
my_project/lib/main.dart
extraneous_modifier • 1 change
other_package/lib/other.dart
extraneous_modifier • 1 change
Bumped SDK constraints in 2 package(s):
- test_project: ^3.12.0 -> ^3.13.0
- other_package: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> ../other_package/lib/other.dart
void f(y) {}
>>>>>>>>>> ../other_package/pubspec.yaml
name: other_package
environment:
sdk: '^3.13.0'
>>>>>>>>>> lib/main.dart
void m(int x) {}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_313_nestedAnalysisOptions() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
var analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
newFile(analysisOptionsPath, '');
var aPath = join(projectFolderPath, 'lib', 'a.dart');
newFile(aPath, 'void m(final int x) {}\n');
var nestedAnalysisOptionsPath = join(
projectFolderPath,
'lib',
'src',
'analysis_options.yaml',
);
newFile(nestedAnalysisOptionsPath, '');
var bPath = join(projectFolderPath, 'lib', 'src', 'b.dart');
newFile(bPath, 'void f(final int y) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 2 files.
my_project/lib/a.dart
extraneous_modifier • 1 change
my_project/lib/src/b.dart
extraneous_modifier • 1 change
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> lib/a.dart
void m(int x) {}
>>>>>>>>>> lib/src/b.dart
void f(int y) {}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_313_noEdits() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(int x, y) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_preMigration_nestedPackage() async {
failTestOnErrorDiagnostic = false;
// Parent package
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x) {}\n');
writeTestPackageConfig(languageVersion: '3.12');
// Nested package in 'example/'
var examplePath = join(projectFolderPath, 'example');
var examplePubspecPath = join(examplePath, 'pubspec.yaml');
var exampleMainPath = join(examplePath, 'lib', 'main.dart');
newFile(examplePubspecPath, '''
name: example
environment:
sdk: '^3.12.0'
''');
newFile(exampleMainPath, 'void f(var y) {}\n');
writePackageConfig(
examplePath,
packageName: 'example',
languageVersion: '3.12',
);
await initialize();
// Migrate ONLY the parent package.
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
1 change made in 1 file.
my_project/lib/main.dart
avoid_final_parameters • 1 change
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x) {}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_all() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C(final int x);
C.name(final String s);
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.All],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 2 changes
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new(int x);
new name(String s);
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_bump() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(int x) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_bump_error_prepareNeeded() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: allOf(
contains(
'- test_project:\n'
' Failed version bump with error: Package "test_project" requires '
'pre-bump fixes before the SDK constraint can be bumped.',
),
contains('No SDK constraints were bumped.'),
),
);
}
Future<void> test_step_bump_error_prepareNeeded_multiplePackages() async {
failTestOnErrorDiagnostic = false;
var otherPackagePath = convertPath('/home/other_package');
var otherPubspecPath = join(otherPackagePath, 'pubspec.yaml');
var otherFilePath = join(otherPackagePath, 'lib', 'other.dart');
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x) {}\n');
newFile(otherPubspecPath, '''
name: other_package
environment:
sdk: '^3.12.0'
''');
newFile(otherFilePath, 'void f(int y) {}\n');
await initialize(
workspaceFolders: [projectFolderUri, toUri(otherPackagePath)],
);
await _assertMigrationResult(
uris: [projectFolderUri, toUri(otherPackagePath)],
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: allOf(
contains(
'Bumped SDK constraints in 1 package(s):\n'
' - other_package: ^3.12.0 -> ^3.13.0',
),
contains(
'- test_project:\n'
' Failed version bump with error: Package "test_project" requires '
'pre-bump fixes before the SDK constraint can be bumped.',
),
),
expectedEdit: '''
>>>>>>>>>> ../other_package/pubspec.yaml
name: other_package
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_bumpAndCleanup() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C();
C.name();
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Bump, MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new();
new name();
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void>
test_step_bumpAndCleanup_error_prepareNeeded_multiplePackages() async {
failTestOnErrorDiagnostic = false;
var otherPackagePath = convertPath('/home/other_package');
var otherPubspecPath = join(otherPackagePath, 'pubspec.yaml');
var otherFilePath = join(otherPackagePath, 'lib', 'other.dart');
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, 'void m(final int x) {}\n');
newFile(otherPubspecPath, '''
name: other_package
environment:
sdk: '^3.12.0'
''');
newFile(otherFilePath, '''
class C {
C();
C.name();
}
''');
await initialize(
workspaceFolders: [projectFolderUri, toUri(otherPackagePath)],
);
await _assertMigrationResult(
uris: [projectFolderUri, toUri(otherPackagePath)],
steps: [MigrationStep.Bump, MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
- test_project:
Failed version bump with error: Package "test_project" requires pre-bump fixes before the SDK constraint can be bumped.
Bumped SDK constraints in 1 package(s):
- other_package: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
other_package/lib/other.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> ../other_package/lib/other.dart
class C {
new();
new name();
}
>>>>>>>>>> ../other_package/pubspec.yaml
name: other_package
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_cleanup() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.13.0'
''');
newFile(mainFilePath, '''
class C {
C();
C.name();
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new();
new name();
}
''',
);
}
Future<void> test_step_cleanup_error_missingSdkConstraint() async {
await _setupProject(pubspecContent: 'name: test_project');
await _assertMigrationResult(
steps: [MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
- test_project:
Failed cleanup with error: Unknown SDK version.
Cleanup changes after a version bump:
0 changes made in 0 files.''',
);
}
Future<void> test_step_cleanup_multiplePackages_oneSkipped() async {
failTestOnErrorDiagnostic = false;
var otherPackagePath = convertPath('/home/other_package');
var otherPubspecPath = join(otherPackagePath, 'pubspec.yaml');
var otherFilePath = join(otherPackagePath, 'lib', 'other.dart');
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.13.0'
''');
newFile(mainFilePath, '''
class C {
C();
C.name();
}
''');
newFile(otherPubspecPath, '''
name: other_package
environment:
sdk: '^3.12.0'
''');
newFile(otherFilePath, 'void f(int y) {}\n');
await initialize(
workspaceFolders: [projectFolderUri, toUri(otherPackagePath)],
);
await _assertMigrationResult(
uris: [projectFolderUri, toUri(otherPackagePath)],
steps: [MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new();
new name();
}
''',
);
}
Future<void> test_step_cleanup_noCleanupFixesRegistered_skipped() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^2.12.0'
''');
newFile(mainFilePath, 'void m(int x) {}\n');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Cleanup changes after a version bump:
0 changes made in 0 files.''',
);
}
Future<void> test_step_empty() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
void m(final int x) {}
''');
await initialize();
await _assertMigrationResult(steps: [], apply: true, expectedSummary: '');
}
Future<void> test_step_prepare() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
void m(final int x) {}
class C {
C();
C.name();
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
1 change made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 1 change''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x) {}
class C {
C();
C.name();
}
''',
);
}
Future<void> test_step_prepareAndBump() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
void m(final int x) {}
class C {
C();
C.name();
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
1 change made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 1 change
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x) {}
class C {
C();
C.name();
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_step_prepareAndCleanup_noBump() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
void m(final int x) {}
class C {
C();
C.name();
}
class D {
int? _x;
D({int? x}) : _x = x;
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
1 change made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 1 change
Cleanup changes after a version bump:
1 change made in 1 file.
my_project/lib/main.dart
prefer_initializing_formals • 1 change''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
void m(int x) {}
class C {
C();
C.name();
}
class D {
int? _x;
D({this._x});
}
''',
);
}
Future<void> test_step_prepareBumpAndCleanup() async {
failTestOnErrorDiagnostic = false;
newFile(pubspecFilePath, '''
name: test_project
environment:
sdk: '^3.12.0'
''');
newFile(mainFilePath, '''
class C {
C(final int x);
C.name(final String s);
}
''');
await initialize();
await _assertMigrationResult(
steps: [MigrationStep.Prepare, MigrationStep.Bump, MigrationStep.Cleanup],
apply: true,
expectedSummary: '''
Preparatory changes for a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
extraneous_modifier • 2 changes
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0
Cleanup changes after a version bump:
2 changes made in 1 file.
my_project/lib/main.dart
unnecessary_type_name_in_constructor • 2 changes''',
expectedEdit: '''
>>>>>>>>>> lib/main.dart
class C {
new(int x);
new name(String s);
}
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> test_validDirectory() async {
await _setupProject(
pubspecContent: '''
name: test_project
environment:
sdk: '^3.12.0'
''',
);
await _assertMigrationResult(
steps: [MigrationStep.Bump],
apply: true,
expectedSummary: '''
Bumped SDK constraints in 1 package(s):
- test_project: ^3.12.0 -> ^3.13.0''',
expectedEdit: '''
>>>>>>>>>> pubspec.yaml
name: test_project
environment:
sdk: '^3.13.0'
''',
);
}
Future<void> _assertMigrationResult({
List<Uri>? uris,
List<MigrationStep>? steps,
Object? expectedSummary,
String? expectedEdit,
bool apply = false,
}) async {
await workspaceAnalysisComplete();
var request = makeRequest(
CustomMethods.migrate,
DartMigrateParams(
uris: uris ?? [projectFolderUri],
apply: apply,
steps: steps,
),
);
var response = await sendRequestToServer(request);
expect(response.error, isNull);
var result = DartMigrateResult.fromJson(
response.result as Map<String, Object?>,
);
if (expectedSummary != null) {
expect(result.summary, expectedSummary);
}
if (!apply) {
expect(result.edit, isNull);
} else if (expectedEdit != null) {
verifyEdit(result.edit!, expectedEdit);
}
}
Future<void> _setupProject({
required String pubspecContent,
String? customPubspecFilePath,
}) async {
var pubspecPath = customPubspecFilePath ?? pubspecFilePath;
newFile(pubspecPath, pubspecContent);
await initialize();
}
}