blob: 8e86616cd4e084feab9273d1ad7031c6ca47996f [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 'dart:io';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
/// The language version this package supports.
///
/// For the purposes of code generation and tooling, we treat this as the
/// language version of the SDK.
final dartLanguageVersion = Version(3, 10, 0);
/// Derives the language version from an SDK constraint.
Version deriveLanguageVersion(VersionConstraint constraint) {
final minVersion = switch (constraint) {
Version() => constraint,
VersionRange(min: final min) => min ?? Version(0, 0, 0),
_ => throw ArgumentError(
'Unsupported constraint type: ${constraint.runtimeType}',
),
};
return Version(minVersion.major, minVersion.minor, 0);
}
/// Checks that the target package at [targetPackagePath] has a valid SDK
/// constraint that aligns with [dartLanguageVersion].
void checkSdkVersion(String targetPackagePath) {
final pubspecFile = File(p.join(targetPackagePath, 'pubspec.yaml'));
if (!pubspecFile.existsSync()) {
throw SdkVersionException(
'Could not find pubspec.yaml in "$targetPackagePath".',
);
}
try {
final pubspecContent = pubspecFile.readAsStringSync();
final sdkConstraintStr = switch (loadYaml(pubspecContent)) {
{'environment': {'sdk': final String s}} => s,
_ => null,
};
if (sdkConstraintStr == null) {
throw SdkVersionException(
'The target package must have an SDK constraint in pubspec.yaml. '
'Expected at least ^$dartLanguageVersion.',
);
}
final sdkConstraint = VersionConstraint.parse(sdkConstraintStr);
final targetLanguageVersion = deriveLanguageVersion(sdkConstraint);
if (targetLanguageVersion < dartLanguageVersion) {
throw SdkVersionException(
'The target package requires a language version of '
'$targetLanguageVersion derived from SDK constraint '
'"$sdkConstraintStr", but the generator requires at least '
'$dartLanguageVersion.',
);
}
} on SdkVersionException {
rethrow;
} catch (e) {
throw SdkVersionException('Failed to read or parse pubspec.yaml: $e');
}
}
/// Exception thrown when the target package's SDK version is incompatible.
class SdkVersionException implements Exception {
final String message;
SdkVersionException(this.message);
@override
String toString() => message;
}