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

[package_config] Implement relational operators for LanguageVersion #2016

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgs/package_config/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.2.0-wip

- Add relational operators to `LanguageVersion` with extension methods
exported under `LanguageVersionRelationalOperators`.

## 2.1.1

- Require Dart 3.4
Expand Down
7 changes: 6 additions & 1 deletion pkgs/package_config/lib/package_config_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ library;

export 'src/errors.dart' show PackageConfigError;
export 'src/package_config.dart'
show InvalidLanguageVersion, LanguageVersion, Package, PackageConfig;
show
InvalidLanguageVersion,
LanguageVersion,
LanguageVersionRelationalOperators,
Package,
PackageConfig;
82 changes: 81 additions & 1 deletion pkgs/package_config/lib/src/package_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ abstract class LanguageVersion implements Comparable<LanguageVersion> {
/// Two language versions are considered equal if they have the
/// same major and minor version numbers.
///
/// A language version is greater then another if the former's major version
/// A language version is greater than another if the former's major version
/// is greater than the latter's major version, or if they have
/// the same major version and the former's minor version is greater than
/// the latter's.
Expand Down Expand Up @@ -400,3 +400,83 @@ abstract class InvalidLanguageVersion implements LanguageVersion {
@override
String toString();
}

/// Relational operators for [LanguageVersion] that
/// compare versions with [LanguageVersion.compareTo].
parlough marked this conversation as resolved.
Show resolved Hide resolved
///
/// An [InvalidLanguageVersion] is not less or greater than other versions
/// and is only equal to itself.
// TODO(v3): Consider declaring on LanguageVersion class.
extension LanguageVersionRelationalOperators on LanguageVersion {
/// Whether this language version is less than [other].
///
/// If either version is an [InvalidLanguageVersion], returns `false`.
parlough marked this conversation as resolved.
Show resolved Hide resolved
///
/// For details on how valid language versions are compared,
/// check out [LanguageVersion.compareTo].
bool operator <(LanguageVersion other) {
// Account for invalid language versions which aren't
// greater or less than any other version.
if (this is InvalidLanguageVersion || other is InvalidLanguageVersion) {
return false;
}

return compareTo(other) < 0;
}

/// Whether this language version is less than or equal to [other].
///
/// If either version is an [InvalidLanguageVersion],
/// returns whether they are the same object.
///
/// For details on how valid language versions are compared,
/// check out [LanguageVersion.compareTo].
bool operator <=(LanguageVersion other) {
// Account for invalid language versions only being equal to themselves.
if (identical(this, other)) {
return true;
}

if (this is InvalidLanguageVersion || other is InvalidLanguageVersion) {
return false;
}

return compareTo(other) <= 0;
}

/// Whether this language version is greater than [other].
///
/// If either version is an [InvalidLanguageVersion], returns `false`.
///
/// For details on how valid language versions are compared,
/// check out [LanguageVersion.compareTo].
bool operator >(LanguageVersion other) {
// Account for invalid language versions which aren't
// greater or less than any other version.
if (this is InvalidLanguageVersion || other is InvalidLanguageVersion) {
return false;
}

return compareTo(other) > 0;
}

/// Whether this language version is greater than or equal to [other].
///
/// If either version is an [InvalidLanguageVersion],
/// returns whether they are the same object.
///
/// For details on how valid language versions are compared,
/// check out [LanguageVersion.compareTo].
bool operator >=(LanguageVersion other) {
// Account for invalid language versions only being equal to themselves.
if (identical(this, other)) {
return true;
}

if (this is InvalidLanguageVersion || other is InvalidLanguageVersion) {
return false;
}

return compareTo(other) >= 0;
}
}
2 changes: 1 addition & 1 deletion pkgs/package_config/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: package_config
version: 2.1.1
version: 2.2.0-wip
description: Support for reading and writing Dart Package Configuration files.
repository: https://github.com/dart-lang/tools/tree/main/pkgs/package_config
issue_tracker: https://github.com/dart-lang/tools/labels/package%3Apackage_config
Expand Down
79 changes: 79 additions & 0 deletions pkgs/package_config/test/package_config_impl_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,85 @@ void main() {
failParse('WhiteSpace 2', '1 .1');
failParse('WhiteSpace 3', '1. 1');
failParse('WhiteSpace 4', '1.1 ');

test('compareTo valid', () {
var version = LanguageVersion(3, 5);
var identicalVersion = version;
var sameMajorSameMinorVersion = LanguageVersion(3, 5);
var sameMajorLowerMinorVersion = LanguageVersion(3, 4);
var lowerMajorSameMinorVersion = LanguageVersion(2, 5);
var sameMajorGreaterMinorVersion = LanguageVersion(3, 6);
var greaterMajorSameMinorVersion = LanguageVersion(4, 5);
parlough marked this conversation as resolved.
Show resolved Hide resolved

expect(version.compareTo(identicalVersion), 0);
expect(version.compareTo(sameMajorSameMinorVersion), 0);
expect(identicalVersion.compareTo(version), 0);
expect(sameMajorSameMinorVersion.compareTo(version), 0);

expect(version.compareTo(sameMajorLowerMinorVersion), isPositive);
expect(version.compareTo(lowerMajorSameMinorVersion), isPositive);

expect(version.compareTo(sameMajorGreaterMinorVersion), isNegative);
expect(version.compareTo(greaterMajorSameMinorVersion), isNegative);
});

test('compareTo invalid', () {
var validVersion = LanguageVersion(3, 5);
var invalidVersion = LanguageVersion.parse('', onError: (_) {});

expect(validVersion.compareTo(invalidVersion), isPositive);
expect(invalidVersion.compareTo(validVersion), isNegative);
});

test('relational valid', () {
var version = LanguageVersion(3, 5);

void testComparisons(LanguageVersion otherVersion) {
expect(version == otherVersion, version.compareTo(otherVersion) == 0);

expect(version < otherVersion, version.compareTo(otherVersion) < 0);
expect(version <= otherVersion, version.compareTo(otherVersion) <= 0);

expect(version > otherVersion, version.compareTo(otherVersion) > 0);
expect(version >= otherVersion, version.compareTo(otherVersion) >= 0);
}

// Check that relational operator implementations match
// the results of compareTo for valid versions.
[
version, // Identical.
LanguageVersion(3, 5), // Same major, same minor.
LanguageVersion(3, 4), // Same major, lower minor.
LanguageVersion(2, 5), // Lower major, same minor.
LanguageVersion(3, 6), // Same major, greater minor.
LanguageVersion(4, 5), // Great major, same minor.
parlough marked this conversation as resolved.
Show resolved Hide resolved
].forEach(testComparisons);
});

test('relational invalid', () {
void testComparisonsWithInvalid(
LanguageVersion version,
LanguageVersion otherVersion,
) {
expect(version == otherVersion, identical(version, otherVersion));

expect(version < otherVersion, false);
expect(version <= otherVersion, identical(version, otherVersion));

expect(version > otherVersion, false);
expect(version >= otherVersion, identical(version, otherVersion));
}

var validVersion = LanguageVersion(3, 5);
var invalidVersion = LanguageVersion.parse('', onError: (_) {});
var identicalInvalidVersion = invalidVersion;
parlough marked this conversation as resolved.
Show resolved Hide resolved
var differentInvalidVersion = LanguageVersion.parse('-', onError: (_) {});

testComparisonsWithInvalid(validVersion, invalidVersion);
testComparisonsWithInvalid(invalidVersion, validVersion);
testComparisonsWithInvalid(invalidVersion, identicalInvalidVersion);
testComparisonsWithInvalid(invalidVersion, differentInvalidVersion);
});
parlough marked this conversation as resolved.
Show resolved Hide resolved
});

group('Package', () {
Expand Down