Don't allow non-null-safety constraints in the root pubspec (#3800)
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index afd6c8a..d18f6e2 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -19,6 +19,7 @@
import 'exceptions.dart';
import 'executable.dart';
import 'io.dart';
+import 'language_version.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
@@ -938,21 +939,21 @@
/// We don't allow unknown sdks.
void _checkSdkConstraint(Pubspec pubspec) {
final dartSdkConstraint = pubspec.dartSdkConstraint.effectiveConstraint;
- if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
- // Suggest an sdk constraint giving the same language version as the
- // current sdk.
- var suggestedConstraint = VersionConstraint.compatibleWith(
- Version(sdk.version.major, sdk.version.minor, 0),
+ // Suggest an sdk constraint giving the same language version as the
+ // current sdk.
+ var suggestedConstraint = VersionConstraint.compatibleWith(
+ Version(sdk.version.major, sdk.version.minor, 0),
+ );
+ // But if somehow that doesn't work, we fallback to safe sanity, mostly
+ // important for tests, or if we jump to 3.x without patching this code.
+ if (!suggestedConstraint.allows(sdk.version)) {
+ suggestedConstraint = VersionRange(
+ min: sdk.version,
+ max: sdk.version.nextBreaking,
+ includeMin: true,
);
- // But if somehow that doesn't work, we fallback to safe sanity, mostly
- // important for tests, or if we jump to 3.x without patching this code.
- if (!suggestedConstraint.allows(sdk.version)) {
- suggestedConstraint = VersionRange(
- min: sdk.version,
- max: sdk.version.nextBreaking,
- includeMin: true,
- );
- }
+ }
+ if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
throw DataException('''
$pubspecPath has no lower-bound SDK constraint.
You should edit $pubspecPath to contain an SDK constraint:
@@ -963,6 +964,24 @@
See https://dart.dev/go/sdk-constraint
''');
}
+ if (!LanguageVersion.fromSdkConstraint(dartSdkConstraint)
+ .supportsNullSafety) {
+ throw DataException('''
+The lower bound of "sdk: '$dartSdkConstraint'" must be 2.12.0'
+or higher to enable null safety.
+
+The current version of the Dart SDK (${sdk.version}) does not support non-null
+safety code.
+
+Consider using an older, compatible Dart SDK or try the following sdk
+constraint:
+
+environment:
+ sdk: '${suggestedConstraint.asCompatibleWithIfPossible()}'
+
+For details, see https://dart.dev/null-safety
+''');
+ }
for (final sdk in pubspec.sdkConstraints.keys) {
if (!sdks.containsKey(sdk)) {
final environment = pubspec.fields.nodes['environment'] as YamlMap;
diff --git a/lib/src/sdk.dart b/lib/src/sdk.dart
index 7da78c1..bc1c6c9 100644
--- a/lib/src/sdk.dart
+++ b/lib/src/sdk.dart
@@ -31,9 +31,6 @@
/// The SDK's version number, or `null` if the SDK is unavailable.
Version? get version;
- /// The version of pub that added support for this SDK.
- Version get firstPubVersion;
-
/// A message to indicate to the user how to make this SDK available.
///
/// This is printed after a version solve where the SDK wasn't found. It may
diff --git a/lib/src/sdk/dart.dart b/lib/src/sdk/dart.dart
index 75cf6f9..19af627 100644
--- a/lib/src/sdk/dart.dart
+++ b/lib/src/sdk/dart.dart
@@ -20,8 +20,6 @@
bool get isAvailable => true;
@override
String? get installMessage => null;
- @override
- Version get firstPubVersion => Version.none;
static final String _rootDirectory = () {
if (runningFromDartRepo) return p.join(dartRepoRoot, 'sdk');
diff --git a/lib/src/sdk/flutter.dart b/lib/src/sdk/flutter.dart
index c9f1914..2151e87 100644
--- a/lib/src/sdk/flutter.dart
+++ b/lib/src/sdk/flutter.dart
@@ -15,8 +15,6 @@
String get name => 'Flutter';
@override
bool get isAvailable => _isAvailable;
- @override
- Version get firstPubVersion => Version.parse('1.19.0');
// We only consider the Flutter SDK to present if we find a root directory
// and the root directory contains a valid 'version' file.
diff --git a/lib/src/sdk/fuchsia.dart b/lib/src/sdk/fuchsia.dart
index 3b884a4..e0f551b 100644
--- a/lib/src/sdk/fuchsia.dart
+++ b/lib/src/sdk/fuchsia.dart
@@ -15,8 +15,6 @@
String get name => 'Fuchsia';
@override
bool get isAvailable => _isAvailable;
- @override
- Version get firstPubVersion => Version.parse('2.0.0-dev.51.0');
static final bool _isAvailable = _rootDirectory != null;
static final String? _rootDirectory =
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index 5a03d7b..6fcab2a 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -23,7 +23,6 @@
import 'validator/flutter_constraint.dart';
import 'validator/flutter_plugin_format.dart';
import 'validator/gitignore.dart';
-import 'validator/language_version.dart';
import 'validator/leak_detection.dart';
import 'validator/license.dart';
import 'validator/name.dart';
@@ -156,7 +155,6 @@
StrictDependenciesValidator(),
FlutterConstraintValidator(),
FlutterPluginFormatValidator(),
- LanguageVersionValidator(),
RelativeVersionNumberingValidator(),
PubspecTypoValidator(),
LeakDetectionValidator(),
diff --git a/lib/src/validator/dependency.dart b/lib/src/validator/dependency.dart
index 939d9be..ebfa101 100644
--- a/lib/src/validator/dependency.dart
+++ b/lib/src/validator/dependency.dart
@@ -10,18 +10,11 @@
import '../log.dart' as log;
import '../package_name.dart';
import '../sdk.dart';
-import '../source/git.dart';
import '../source/hosted.dart';
import '../source/path.dart';
import '../source/sdk.dart';
import '../validator.dart';
-/// The first Dart SDK version that supported caret constraints.
-final _firstCaretVersion = Version.parse('1.8.0-dev.3.0');
-
-/// The first Dart SDK version that supported Git path dependencies.
-final _firstGitPathVersion = Version.parse('2.0.0-dev.1.0');
-
/// A validator that validates a package's dependencies.
class DependencyValidator extends Validator {
@override
@@ -38,11 +31,6 @@
errors.add('Unknown SDK "$identifier" for dependency "${dep.name}".');
return;
}
-
- validateSdkConstraint(
- sdk.firstPubVersion,
- "Older versions of pub don't support the ${sdk.name} SDK.",
- );
}
/// Warn that dependencies should use the hosted source.
@@ -195,14 +183,6 @@
warnAboutSdkSource(dependency);
} else if (dependency.source is! HostedSource) {
await warnAboutSource(dependency);
-
- final description = dependency.description;
- if (description is GitDescription && description.path != '.') {
- validateSdkConstraint(
- _firstGitPathVersion,
- "Older versions of pub don't support Git path dependencies.",
- );
- }
} else {
if (constraint.isAny) {
warnAboutNoConstraint(dependency);
@@ -224,12 +204,5 @@
}
await validateDependencies(entrypoint.root.pubspec.dependencies.values);
-
- if (hasCaretDep) {
- validateSdkConstraint(
- _firstCaretVersion,
- "Older versions of pub don't support ^ version constraints.",
- );
- }
}
}
diff --git a/lib/src/validator/language_version.dart b/lib/src/validator/language_version.dart
deleted file mode 100644
index ab2d868..0000000
--- a/lib/src/validator/language_version.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2020, 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 'dart:async';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:path/path.dart' as p;
-import 'package:stack_trace/stack_trace.dart';
-
-import '../dart.dart';
-import '../language_version.dart';
-import '../log.dart' as log;
-import '../utils.dart';
-import '../validator.dart';
-
-/// Validates that libraries do not opt into newer language versions than what
-/// they declare in their pubspec.
-class LanguageVersionValidator extends Validator {
- @override
- Future validate() async {
- var packagePath = p.normalize(p.absolute(entrypoint.root.dir));
- final analysisContextManager = AnalysisContextManager(packagePath);
-
- final declaredLanguageVersion = entrypoint.root.pubspec.languageVersion;
-
- for (final path in ['lib', 'bin'].expand((path) {
- return filesBeneath(path, recursive: true)
- .where((file) => p.extension(file) == '.dart');
- })) {
- CompilationUnit unit;
- try {
- unit = analysisContextManager.parse(path);
- } on AnalyzerErrorGroup catch (e, s) {
- // Ignore files that do not parse.
- log.fine(getErrorMessage(e));
- log.fine(Chain.forTrace(s).terse);
- continue;
- }
-
- final unitLanguageVersionToken = unit.languageVersionToken;
- if (unitLanguageVersionToken != null) {
- final unitLanguageVersion =
- LanguageVersion.fromLanguageVersionToken(unitLanguageVersionToken);
- if (unitLanguageVersion > declaredLanguageVersion) {
- final relativePath = p.relative(path);
- errors.add('$relativePath is declaring language version '
- '$unitLanguageVersion that is newer than the SDK '
- 'constraint $declaredLanguageVersion declared in '
- '`pubspec.yaml`.');
- }
- }
- }
- }
-}
diff --git a/lib/src/validator/sdk_constraint.dart b/lib/src/validator/sdk_constraint.dart
index 729981e..c95cd91 100644
--- a/lib/src/validator/sdk_constraint.dart
+++ b/lib/src/validator/sdk_constraint.dart
@@ -6,7 +6,6 @@
import 'package:pub_semver/pub_semver.dart';
-import '../sdk.dart';
import '../validator.dart';
/// A validator of the SDK constraint.
@@ -62,15 +61,5 @@
''');
}
}
-
- for (var sdk in sdks.values) {
- if (sdk.identifier == 'dart') continue;
- if (entrypoint.root.pubspec.sdkConstraints.containsKey(sdk.identifier)) {
- validateSdkConstraint(
- sdk.firstPubVersion,
- "Older versions of pub don't support ${sdk.name} SDK constraints.",
- );
- }
- }
}
}
diff --git a/test/dart3_sdk_constraint_hack_test.dart b/test/dart3_sdk_constraint_hack_test.dart
index e8e18ab..5771ff6 100644
--- a/test/dart3_sdk_constraint_hack_test.dart
+++ b/test/dart3_sdk_constraint_hack_test.dart
@@ -2,6 +2,7 @@
// 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:pub/src/exit_codes.dart';
import 'package:test/test.dart';
import 'descriptor.dart' as d;
@@ -18,9 +19,10 @@
await pubGet(
error: contains(
- 'Because myapp doesn\'t support null safety, version solving failed',
+ 'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
),
environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ exitCode: DATA,
);
});
test('The bound of ">=2.12.0 <3.1.0" is not modified', () async {
@@ -49,9 +51,10 @@
await pubGet(
error: contains(
- 'Because myapp doesn\'t support null safety, version solving failed',
+ 'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
),
environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ exitCode: DATA,
);
});
@@ -65,9 +68,10 @@
await pubGet(
error: contains(
- 'Because myapp doesn\'t support null safety, version solving failed',
+ 'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
),
environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ exitCode: DATA,
);
});
diff --git a/test/get/sdk_constraint_required_test.dart b/test/get/sdk_constraint_required_test.dart
index 992abcc..50c6420 100644
--- a/test/get/sdk_constraint_required_test.dart
+++ b/test/get/sdk_constraint_required_test.dart
@@ -34,4 +34,43 @@
d.nothing('.dart_tool/package_config.json'),
]).validate();
});
+
+ test('pub get fails with an non-null-safety SDK constraint', () async {
+ await d.dir(appPath, [
+ d.rawPubspec(
+ {
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.9.0 <4.0.0'}
+ },
+ ),
+ ]).create();
+
+ await pubGet(
+ error: '''
+The lower bound of "sdk: '>=2.9.0 <4.0.0'" must be 2.12.0'
+or higher to enable null safety.
+
+The current version of the Dart SDK (3.1.2+3) does not support non-null
+safety code.
+
+Consider using an older, compatible Dart SDK or try the following sdk
+constraint:
+
+environment:
+ sdk: '^3.1.0'
+
+For details, see https://dart.dev/null-safety
+''',
+ exitCode: exit_codes.DATA,
+ );
+
+ await d.dir(appPath, [
+ // The lockfile should not be created.
+ d.nothing('pubspec.lock'),
+ // The "packages" directory should not have been generated.
+ d.nothing('packages'),
+ // The package config file should not have been created.
+ d.nothing('.dart_tool/package_config.json'),
+ ]).validate();
+ });
}
diff --git a/test/hosted/short_syntax_test.dart b/test/hosted/short_syntax_test.dart
index 6ea6851..eb1003f 100644
--- a/test/hosted/short_syntax_test.dart
+++ b/test/hosted/short_syntax_test.dart
@@ -18,7 +18,7 @@
'foo',
'1.2.3',
pubspec: {
- 'environment': {'sdk': '^2.0.0'}
+ 'environment': {'sdk': '^2.12.0'}
},
);
});
@@ -73,15 +73,11 @@
deps: {
'foo': {'hosted': 'foo', 'version': '^1.2.3'}
},
- sdk: '^2.0.0',
+ sdk: '^2.14.0',
),
]).create();
- await pubCommand(
- command,
- exitCode: 0,
- environment: {'_PUB_TEST_SDK_VERSION': '2.15.0'},
- );
+ await pubCommand(command);
final lockFile = loadYaml(
await File(p.join(d.sandbox, appPath, 'pubspec.lock')).readAsString(),
diff --git a/test/must_pub_get_test.dart b/test/must_pub_get_test.dart
index 7663401..4eace86 100644
--- a/test/must_pub_get_test.dart
+++ b/test/must_pub_get_test.dart
@@ -258,7 +258,7 @@
'foo',
'3.0.0',
pubspec: {
- 'environment': {'sdk': '>=1.0.0 <2.0.0'}
+ 'environment': {'sdk': '>=3.0.0 <3.1.0'}
},
);
@@ -267,12 +267,12 @@
'name': 'myapp',
'dependencies': {'foo': '3.0.0'},
'environment': {
- 'sdk': '>=1.0.0 <2.0.0',
+ 'sdk': '>=3.0.0 <3.1.0',
},
}),
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.2.3+4'});
+ await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.0.0'});
});
_requiresPubGet("Dart 3.1.2+3 is incompatible with your dependencies' "
diff --git a/test/run/enable_experiments_test.dart b/test/run/enable_experiments_test.dart
deleted file mode 100644
index a21fee3..0000000
--- a/test/run/enable_experiments_test.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2014, 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:test/test.dart';
-
-import '../descriptor.dart' as d;
-import '../test_pub.dart';
-
-void main() {
- test('Succeeds running experimental code.', () async {
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- 'environment': {'sdk': '>=2.10.0 <=3.0.0'},
- }),
- d.dir('bin', [
- d.file('script.dart', '''
- main() {
- int? a = int.tryParse('123');
- }
-''')
- ])
- ]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.10.0'});
- await runPub(
- args: ['run', '--enable-experiment=non-nullable', 'bin/script.dart'],
- environment: {'_PUB_TEST_SDK_VERSION': '2.10.0'},
- );
- });
-}
diff --git a/test/validator/analyze_test.dart b/test/validator/analyze_test.dart
index a20f4cd..1ce8b4f 100644
--- a/test/validator/analyze_test.dart
+++ b/test/validator/analyze_test.dart
@@ -7,50 +7,30 @@
import '../descriptor.dart' as d;
import '../test_pub.dart';
-
-Future<void> expectValidation(
- error,
- int exitCode, {
- List<String> extraArgs = const [],
- Map<String, String> environment = const {},
- String? workingDirectory,
-}) async {
- await runPub(
- error: error,
- args: ['publish', '--dry-run', ...extraArgs],
- environment: {'_PUB_TEST_SDK_VERSION': '1.12.0', ...environment},
- workingDirectory: workingDirectory ?? d.path(appPath),
- exitCode: exitCode,
- );
-}
+import 'utils.dart';
void main() {
test('should consider a package valid if it contains no warnings or errors',
() async {
await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+ d.validPubspec(),
d.file('LICENSE', 'Eh, do what you want.'),
d.file('README.md', "This package isn't real."),
d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
d.dir('lib', [d.file('test_pkg.dart', 'int i = 1;')])
]).create();
-
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
- await expectValidation(contains('Package has 0 warnings.'), 0);
+ await expectValidation();
});
test('should handle having no code in the analyzed directories', () async {
await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+ d.validPubspec(),
d.file('LICENSE', 'Eh, do what you want.'),
d.file('README.md', "This package isn't real."),
d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
- await expectValidation(contains('Package has 0 warnings.'), 0);
+ await expectValidation();
});
test(
@@ -59,7 +39,7 @@
await d.dir(appPath, [
d.libPubspec(
'test_pkg', '1.0.0',
- sdk: '>=1.8.0 <=2.0.0',
+ sdk: '^3.0.0',
// Using http where https is recommended.
extras: {'repository': 'http://repo.org/'},
),
@@ -73,16 +53,14 @@
''')
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
await expectValidation(
- allOf([
+ error: allOf([
contains(
"The 'http' protocol shouldn't be used because it isn't secure. Try using a secure protocol, such as 'https'.",
),
contains('Package has 1 warning.'),
]),
- DATA,
+ exitCode: DATA,
);
});
@@ -90,7 +68,7 @@
'should consider a package valid even if it contains errors in the example/ sub-folder',
() async {
await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+ d.validPubspec(),
d.file('LICENSE', 'Eh, do what you want.'),
d.file('README.md', "This package isn't real."),
d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -104,16 +82,14 @@
])
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
- await expectValidation(contains('Package has 0 warnings.'), 0);
+ await expectValidation();
});
test(
'should warn if package contains errors in bin/, and works with --directory',
() async {
await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+ d.validPubspec(),
d.file('LICENSE', 'Eh, do what you want.'),
d.file('README.md', "This package isn't real."),
d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -126,17 +102,15 @@
])
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
await expectValidation(
- allOf([
+ error: allOf([
contains('`dart analyze` found the following issue(s):'),
contains('Analyzing lib, bin, pubspec.yaml...'),
contains('error -'),
contains("Expected to find '}'."),
contains('Package has 1 warning.')
]),
- DATA,
+ exitCode: DATA,
extraArgs: ['--directory', appPath],
workingDirectory: d.sandbox,
);
@@ -144,7 +118,7 @@
test('should warn if package contains infos in test folder', () async {
await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+ d.validPubspec(),
d.file('LICENSE', 'Eh, do what you want.'),
d.file('README.md', "This package isn't real."),
d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -158,17 +132,15 @@
]),
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
await expectValidation(
- allOf([
+ error: allOf([
contains('`dart analyze` found the following issue(s):'),
contains('Analyzing lib, test, pubspec.yaml...'),
contains('info -'),
contains("The value of the local variable 'a' isn't used"),
contains('Package has 1 warning.')
]),
- DATA,
+ exitCode: DATA,
);
});
}
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 6d8349e..dead156 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -93,12 +93,6 @@
await expectValidation();
});
- test('has a ^ constraint with an appropriate SDK constraint', () async {
- (await servePackages()).serve('foo', '1.2.3', sdk: '^1.8.3');
- await package(deps: {'foo': '^1.2.3'}, sdk: '^1.8.3').create();
- await expectValidation(environment: {'_PUB_TEST_SDK_VERSION': '1.18.0'});
- });
-
test('with a dependency on a pre-release while being one', () async {
(await servePackages()).serve('foo', '1.2.3-dev');
await package(version: '1.0.0-dev', deps: {'foo': '^1.2.3-dev'}).create();
@@ -109,7 +103,7 @@
() async {
await servePackages();
await d.git('foo', [
- d.dir('subdir', [d.libPubspec('foo', '1.0.0', sdk: '^2.0.0')]),
+ d.dir('subdir', [d.libPubspec('foo', '1.0.0')]),
]).create();
await package(
deps: {
@@ -117,7 +111,6 @@
'git': {'url': '../foo', 'path': 'subdir'}
}
},
- sdk: '>=2.0.0 <3.0.0',
).create();
// We should get a warning for using a git dependency, but not an error.
@@ -127,25 +120,20 @@
contains("Publishable packages can't have 'git' dependencies"),
]),
count: 2,
- environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'},
);
});
test('depends on Flutter from an SDK source', () async {
await d.dir('flutter', [d.file('version', '1.2.3')]).create();
- await flutterPackage('flutter', sdk: '>=1.19.0 <2.0.0').create();
+ await flutterPackage('flutter').create();
await package(
deps: {
'flutter': {'sdk': 'flutter'}
},
- sdk: '>=1.19.0 <2.0.0',
).create();
await expectValidation(
- environment: {
- '_PUB_TEST_SDK_VERSION': '1.19.0',
- 'FLUTTER_ROOT': path.join(d.sandbox, 'flutter')
- },
+ environment: {'FLUTTER_ROOT': path.join(d.sandbox, 'flutter')},
);
});
@@ -153,18 +141,16 @@
'depends on a package from Flutter with an appropriate Dart SDK constraint',
() async {
await d.dir('flutter', [d.file('version', '1.2.3')]).create();
- await flutterPackage('foo', sdk: '^1.0.0').create();
+ await flutterPackage('foo').create();
await d.dir('flutter', [d.file('version', '1.2.3')]).create();
await package(
deps: {
'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'},
},
- sdk: '>=1.19.0 <2.0.0',
).create();
await expectValidation(
environment: {
- '_PUB_TEST_SDK_VERSION': '1.19.0',
'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
},
);
@@ -174,9 +160,8 @@
test(
'depends on a package from Fuchsia with an appropriate Dart SDK constraint',
() async {
- await fuschiaPackage('foo', sdk: '>=2.0.0 <3.0.0').create();
+ await fuschiaPackage('foo', sdk: '^3.0.0').create();
await package(
- sdk: '>=2.0.0 <3.0.0',
deps: {
'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
},
@@ -185,7 +170,6 @@
await expectValidation(
environment: {
'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
- '_PUB_TEST_SDK_VERSION': '2.12.0',
},
);
},
@@ -199,16 +183,14 @@
group('where a hosted version exists', () {
test('and should suggest the hosted primary version', () async {
await d.dir('foo', [
- d.libPubspec('foo', '1.2.3', sdk: 'any'),
+ d.libPubspec('foo', '1.2.3'),
]).create();
await setUpDependency(
- sdk: '^1.8.0',
{'path': path.join(d.sandbox, 'foo')},
hostedVersions: ['3.0.0-pre', '2.0.0', '1.0.0'],
);
await expectValidationError(
' foo: ^2.0.0',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
@@ -216,32 +198,28 @@
"and should suggest the hosted prerelease version if it's the only version available",
() async {
await d.dir('foo', [
- d.libPubspec('foo', '1.2.3', sdk: 'any'),
+ d.libPubspec('foo', '1.2.3'),
]).create();
await setUpDependency(
- sdk: '^1.8.0',
{'path': path.join(d.sandbox, 'foo')},
hostedVersions: ['3.0.0-pre', '2.0.0-pre'],
);
await expectValidationError(
' foo: ^3.0.0-pre',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
test('and should suggest a tighter constraint if primary is pre-1.0.0',
() async {
await d.dir('foo', [
- d.libPubspec('foo', '1.2.3', sdk: 'any'),
+ d.libPubspec('foo', '1.2.3'),
]).create();
await setUpDependency(
- sdk: '^1.8.0',
{'path': path.join(d.sandbox, 'foo')},
hostedVersions: ['0.0.1', '0.0.2'],
);
await expectValidationError(
' foo: ^0.0.2',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
});
@@ -249,15 +227,14 @@
group('where no hosted version exists', () {
test("and should use the other source's version", () async {
await d.dir('foo', [
- d.libPubspec('foo', '1.2.3', sdk: 'any'),
+ d.libPubspec('foo', '1.2.3'),
]).create();
- await setUpDependency(sdk: '^1.8.0', {
+ await setUpDependency({
'path': path.join(d.sandbox, 'foo'),
'version': '>=1.0.0 <2.0.0'
});
await expectValidationError(
' foo: ">=1.0.0 <2.0.0"',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
@@ -265,15 +242,13 @@
"and should use the other source's unquoted version if "
'concrete', () async {
await d.dir('foo', [
- d.libPubspec('foo', '0.2.3', sdk: '^1.8.0'),
+ d.libPubspec('foo', '0.2.3'),
]).create();
await setUpDependency(
- sdk: '^1.8.0',
{'path': path.join(d.sandbox, 'foo'), 'version': '0.2.3'},
);
await expectValidationError(
' foo: 0.2.3',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
});
@@ -318,20 +293,18 @@
});
test('with a dependency on a pre-release without being one', () async {
- (await servePackages()).serve('foo', '1.2.3-dev', sdk: '^1.8.0');
+ (await servePackages()).serve('foo', '1.2.3-dev');
await d.dir(appPath, [
d.libPubspec(
'test_pkg',
'1.0.0',
deps: {'foo': '^1.2.3-dev'},
- sdk: '>=1.8.0 <2.0.0',
)
]).create();
await expectValidationWarning(
'Packages dependent on a pre-release',
- environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
);
});
test(
@@ -427,157 +400,6 @@
await expectValidationWarning(' foo: ">1.2.3 <2.0.0"');
});
});
-
- group('has a ^ dependency', () {
- test('with a too-broad SDK constraint', () async {
- (await servePackages()).serve('foo', '1.2.3', sdk: '^1.4.0');
- await d.dir(appPath, [
- d.libPubspec(
- 'test_pkg',
- '1.0.0',
- deps: {'foo': '^1.2.3'},
- sdk: '>=1.5.0 <2.0.0',
- )
- ]).create();
-
- await expectValidationError(
- ' sdk: "^1.8.0"',
- environment: {'_PUB_TEST_SDK_VERSION': '1.5.0'},
- );
- });
- });
-
- group('has a git path dependency', () {
- test('without an SDK constraint', () async {
- // Ensure we don't report anything from the real pub.dev.
- await setUpDependency({});
- await d.git('foo', [
- d.dir('subdir', [
- d.libPubspec('foo', '1.0.0', extras: {'dependencies': {}})
- ]),
- ]).create();
- await d.dir(appPath, [
- d.libPubspec(
- 'integration_pkg',
- '1.0.0',
- deps: {
- 'foo': {
- 'git': {'url': d.path('foo'), 'path': 'subdir'}
- },
- },
- sdk: '>=1.0.0 <4.0.0',
- )
- ]).create();
-
- await expectValidation(
- error: allOf(
- contains(' sdk: "^2.0.0"'),
- contains(' foo: any'),
- ),
- exitCode: DATA,
- );
- });
-
- test('with a too-broad SDK constraint', () async {
- // Ensure we don't report anything from the real pub.dev.
- await setUpDependency({});
- await d.git('foo', [
- d.dir(
- 'subdir',
- [d.libPubspec('foo', '1.0.0', sdk: '>=0.0.0 <3.0.0')],
- ),
- ]).create();
- await d.dir(appPath, [
- d.libPubspec(
- 'integration_pkg',
- '1.0.0',
- deps: {
- 'foo': {
- 'git': {'url': d.path('foo'), 'path': 'subdir'}
- }
- },
- sdk: '>=1.24.0 <3.0.0',
- )
- ]).create();
-
- await expectValidation(
- error: allOf([
- contains(' sdk: "^2.0.0"'),
- contains(' foo: any'),
- ]),
- environment: {'_PUB_TEST_SDK_VERSION': '1.24.0'},
- exitCode: DATA,
- );
- });
- });
-
- test('depends on Flutter from a non-SDK source', () async {
- (await servePackages()).serve('flutter', '1.5.0');
- await d.dir(appPath, [
- d.libPubspec('test_pkg', '1.0.0', deps: {'flutter': '>=1.2.3 <2.0.0'})
- ]).create();
-
- await expectValidationError('sdk: >=1.2.3 <2.0.0');
- });
-
- test('depends on a Flutter package with a too-broad SDK constraint',
- () async {
- await d.dir('flutter', [d.file('version', '1.2.3')]).create();
- await flutterPackage('foo', sdk: 'any').create();
- await package(
- deps: {
- 'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
- },
- sdk: '>=1.18.0 <2.0.0',
- ).create();
-
- await expectValidationError(
- 'sdk: "^1.19.0"',
- environment: {
- '_PUB_TEST_SDK_VERSION': '1.19.0',
- 'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
- },
- );
- });
-
- test('depends on a Flutter package with no SDK constraint', () async {
- await d.dir('flutter', [d.file('version', '1.2.3')]).create();
- await flutterPackage('foo', sdk: '>=0.0.0 <1.0.0').create();
- await package(
- sdk: '>=0.0.0 <=0.0.1',
- deps: {
- 'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
- },
- ).create();
-
- await expectValidationError(
- 'sdk: "^1.19.0"',
- environment: {
- '_PUB_TEST_SDK_VERSION': '0.0.0',
- 'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
- },
- );
- });
-
- test('depends on a Fuchsia package with a too-broad SDK constraint',
- () async {
- await fuschiaPackage('foo', sdk: '>=0.0.0 <3.0.0').create();
-
- await package(
- sdk: '>=2.0.0-dev.50.0 <2.0.2',
- deps: {
- 'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
- },
- ).create();
-
- await expectValidationError(
- 'sdk: ">=2.0.0 <2.0.2"',
- environment: {
- 'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
- '_PUB_TEST_SDK_VERSION': '2.0.1-dev.51.0',
- },
- );
- });
});
}
@@ -599,13 +421,12 @@
d.Descriptor flutterPackage(
String name, {
Map<String, String> deps = const {},
- String? sdk,
}) {
return d.dir('flutter', [
d.dir('packages', [
d.dir(name, [
d.libDir(name, 'f(x) => 2 * x;'),
- d.libPubspec(name, '1.5.0', deps: deps, sdk: sdk),
+ d.libPubspec(name, '1.5.0', deps: deps),
]),
]),
]);
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index f477038..815e6e4 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -12,7 +12,6 @@
error: error,
args: ['publish', '--dry-run'],
environment: {
- '_PUB_TEST_SDK_VERSION': '2.12.0',
'FLUTTER_ROOT': fakeFlutterRoot.io.path,
},
workingDirectory: d.path(appPath),
@@ -36,16 +35,13 @@
'homepage': 'https://example.com/',
'version': '1.0.0',
'environment': {
- 'sdk': '>=2.9.0 <3.0.0',
+ 'sdk': '^3.0.0',
if (flutterConstraint != null) 'flutter': flutterConstraint
},
}),
]).create();
await pubGet(
- environment: {
- '_PUB_TEST_SDK_VERSION': '2.12.0',
- 'FLUTTER_ROOT': fakeFlutterRoot.io.path
- },
+ environment: {'FLUTTER_ROOT': fakeFlutterRoot.io.path},
);
}
diff --git a/test/validator/language_version_test.dart b/test/validator/language_version_test.dart
index cfcb0d8..9832fd2 100644
--- a/test/validator/language_version_test.dart
+++ b/test/validator/language_version_test.dart
@@ -2,78 +2,74 @@
// 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:pub/src/validator.dart';
-import 'package:pub/src/validator/language_version.dart';
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
import 'utils.dart';
-Validator validator() => LanguageVersionValidator();
-
Future<void> setup({
required String sdkConstraint,
String? libraryLanguageVersion,
}) async {
await d.validPackage.create();
await d.dir(appPath, [
- d.pubspec({
- 'name': 'test_pkg',
- 'version': '1.0.0',
- 'environment': {'sdk': sdkConstraint},
- }),
+ d.validPubspec(
+ extras: {
+ 'environment': {'sdk': sdkConstraint},
+ },
+ ),
d.dir('lib', [
if (libraryLanguageVersion != null)
d.file('library.dart', '// @dart = $libraryLanguageVersion\n'),
])
]).create();
- await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.7.0'});
}
void main() {
group('should consider a package valid if it', () {
test('has no library-level language version annotations', () async {
- await setup(sdkConstraint: '>=2.4.0 <3.0.0');
- await expectValidationDeprecated(validator);
+ await setup(sdkConstraint: '^3.0.0');
+ await expectValidation();
});
test('opts in to older language versions', () async {
await setup(
- sdkConstraint: '>=2.4.0 <3.0.0',
- libraryLanguageVersion: '2.0',
+ sdkConstraint: '^3.0.0',
+ libraryLanguageVersion: '2.14',
);
- await d.dir(appPath, []).create();
- await expectValidationDeprecated(validator);
+ await expectValidation();
});
test('opts in to same language versions', () async {
await setup(
- sdkConstraint: '>=2.4.0 <3.0.0',
- libraryLanguageVersion: '2.4',
+ sdkConstraint: '^3.0.0',
+ libraryLanguageVersion: '3.0',
);
- await d.dir(appPath, []).create();
- await expectValidationDeprecated(validator);
+ await expectValidation();
});
test('opts in to older language version, with non-range constraint',
() async {
- await setup(sdkConstraint: '2.7.0', libraryLanguageVersion: '2.3');
- await d.dir(appPath, []).create();
- await expectValidationDeprecated(validator);
+ await setup(sdkConstraint: '3.1.2+3', libraryLanguageVersion: '2.18');
+ await expectValidation();
});
});
- group('should error if it', () {
+ group('should warn if it', () {
test('opts in to a newer version.', () async {
await setup(
- sdkConstraint: '>=2.4.1 <3.0.0',
- libraryLanguageVersion: '2.5',
+ sdkConstraint: '^3.0.0',
+ libraryLanguageVersion: '3.1',
);
- await expectValidationDeprecated(validator, errors: isNotEmpty);
+ await expectValidationWarning(
+ 'The language version override can\'t specify a version greater than the latest known language version',
+ );
});
test('opts in to a newer version, with non-range constraint.', () async {
- await setup(sdkConstraint: '2.7.0', libraryLanguageVersion: '2.8');
- await expectValidationDeprecated(validator, errors: isNotEmpty);
+ await setup(sdkConstraint: '3.1.2+3', libraryLanguageVersion: '3.2');
+ await expectValidationWarning(
+ 'The language version override can\'t specify a version greater than the latest known language version',
+ );
});
});
}
diff --git a/test/validator/relative_version_numbering_test.dart b/test/validator/relative_version_numbering_test.dart
index 34dc23d..6b73dff 100644
--- a/test/validator/relative_version_numbering_test.dart
+++ b/test/validator/relative_version_numbering_test.dart
@@ -27,44 +27,6 @@
void main() {
group('should consider a package valid if it', () {
- test('is not opting in to null-safety with previous non-null-safe version',
- () async {
- final server = await servePackages();
- server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator);
- });
-
- test(
- 'is not opting in to null-safety with previous non-null-safe version. '
- 'Even with a later null-safe version', () async {
- await servePackages()
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.0',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator);
- });
-
test('is opting in to null-safety with previous null-safe version',
() async {
final server = await servePackages();
@@ -125,36 +87,6 @@
await expectValidationDeprecated(validator);
});
- test('is not opting in to null-safety with no existing versions', () async {
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await servePackages();
-
- await expectValidationDeprecated(validator);
- });
-
- test(
- 'is not opting in to null-safety with previous null-safe stable version. '
- 'With an in-between not null-safe prerelease', () async {
- await servePackages()
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator);
- });
-
test(
'opts in to null-safety, with previous stable version not-null-safe. '
'With an in-between non-null-safe prerelease', () async {
@@ -196,44 +128,6 @@
});
test(
- 'is not opting in to null-safety with no existing stable versions. '
- 'With a previous in-between null-safe prerelease', () async {
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- final server = await servePackages();
- server.serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- );
-
- await expectValidationDeprecated(validator, hints: isNotEmpty);
- });
- test(
- 'is not opting in to null-safety with previous non-null-safe stable version. '
- 'With an in-between null-safe prerelease', () async {
- await servePackages()
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator, hints: isNotEmpty);
- });
-
- test(
'opts in to null-safety, with previous version not-null-safe. '
'Even with a later null-safe version', () async {
await servePackages()
@@ -256,44 +150,6 @@
await expectValidationDeprecated(validator, hints: isNotEmpty);
});
- test('is not opting in to null-safety with previous null-safe version',
- () async {
- final server = await servePackages();
- server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator, hints: isNotEmpty);
- });
-
- test(
- 'is not opting in to null-safety with previous null-safe version. '
- 'Even with a later non-null-safe version', () async {
- await servePackages()
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.0',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- );
-
- await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await expectValidationDeprecated(validator, hints: isNotEmpty);
- });
-
test(
'is opting in to null-safety with previous null-safe stable version. '
'with an in-between non-null-safe prerelease', () async {
diff --git a/test/validator/sdk_constraint_test.dart b/test/validator/sdk_constraint_test.dart
index 4f0e2db..b050c72 100644
--- a/test/validator/sdk_constraint_test.dart
+++ b/test/validator/sdk_constraint_test.dart
@@ -94,66 +94,6 @@
);
});
- test(
- 'has a Flutter SDK constraint with a too-broad SDK '
- 'constraint', () async {
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'test_pkg',
- 'version': '1.0.0',
- 'environment': {'sdk': '>=1.18.0 <1.50.0', 'flutter': '^1.2.3'}
- })
- ]).create();
- await expectValidationDeprecated(
- sdkConstraint,
- errors: anyElement(contains('">=1.19.0 <1.50.0"')),
- );
- });
-
- test('has a Flutter SDK constraint with no SDK constraint', () async {
- await d.dir(appPath, [
- d.rawPubspec({
- 'name': 'test_pkg',
- 'version': '1.0.0',
- 'environment': {'flutter': '^1.2.3'}
- })
- ]).create();
- await expectValidationDeprecated(
- sdkConstraint,
- errors: anyElement(contains('"^1.19.0"')),
- );
- });
-
- test(
- 'has a Fuchsia SDK constraint with a too-broad SDK '
- 'constraint', () async {
- await d.dir(appPath, [
- d.rawPubspec({
- 'name': 'test_pkg',
- 'version': '1.0.0-dev.1',
- 'environment': {'sdk': '>=2.0.0-dev.50.0 <2.0.0', 'fuchsia': '^1.2.3'}
- })
- ]).create();
- await expectValidationDeprecated(
- sdkConstraint,
- errors: anyElement(contains('"^2.0.0"')),
- );
- });
-
- test('has a Fuchsia SDK constraint with no SDK constraint', () async {
- await d.dir(appPath, [
- d.rawPubspec({
- 'name': 'test_pkg',
- 'version': '1.0.0',
- 'environment': {'fuchsia': '^1.2.3'}
- })
- ]).create();
- await expectValidationDeprecated(
- sdkConstraint,
- errors: anyElement(contains('"^2.0.0"')),
- );
- });
-
test('depends on a pre-release sdk from a non-pre-release', () async {
await d.dir(appPath, [
d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0-dev.1 <2.0.0')
diff --git a/test/validator/utils.dart b/test/validator/utils.dart
index ffbe892..2262a55 100644
--- a/test/validator/utils.dart
+++ b/test/validator/utils.dart
@@ -28,13 +28,16 @@
error,
int exitCode = 0,
Map<String, String> environment = const {},
+ List<String>? extraArgs,
+ String? workingDirectory,
}) async {
await runPub(
error: error ?? contains('Package has 0 warnings.'),
- args: ['publish', '--dry-run'],
+ args: ['publish', '--dry-run', ...?extraArgs],
// workingDirectory: d.path(appPath),
exitCode: exitCode,
environment: environment,
+ workingDirectory: workingDirectory,
);
}