Chromium Code Reviews| Index: lib/src/version_range.dart |
| diff --git a/lib/src/version_range.dart b/lib/src/version_range.dart |
| index faffb4742335f9d207bc5a86a545a7b925a1405d..4cf2871ef39cf37aa2e0c3e0e93e848437154eaa 100644 |
| --- a/lib/src/version_range.dart |
| +++ b/lib/src/version_range.dart |
| @@ -6,6 +6,7 @@ library pub_semver.src.version_range; |
| import 'version.dart'; |
| import 'version_constraint.dart'; |
| +import 'version_union.dart'; |
| /// Constrains versions to a fall within a given range. |
| /// |
| @@ -99,8 +100,64 @@ class VersionRange implements VersionConstraint { |
| return true; |
| } |
| + bool allowsAll(VersionConstraint other) { |
| + if (other.isEmpty) return true; |
| + if (other is Version) return allows(other); |
|
Bob Nystrom
2015/05/05 20:49:09
All these type checks make me think it might be cl
nweiz
2015/05/05 22:52:33
That seems like a lot more conceptual overhead, an
|
| + |
| + if (other is VersionUnion) { |
| + return other.constraints.every((constraint) => allowsAll(constraint)); |
| + } |
| + |
| + if (other is VersionRange) { |
| + if (min != null) { |
| + if (other.min == null) return false; |
| + if (min > other.min) return false; |
| + if (min == other.min && !includeMin && other.includeMin) return false; |
| + } |
| + |
| + if (max != null) { |
| + if (other.max == null) return false; |
| + if (max < other.max) return false; |
| + if (max == other.max && !includeMax && other.includeMax) return false; |
| + } |
| + |
| + return true; |
| + } |
| + |
| + throw new ArgumentError('Unknown VersionConstraint type $other.'); |
| + } |
| + |
| + bool allowsAny(VersionConstraint other) { |
| + if (other.isEmpty) return false; |
| + if (other is Version) return allows(other); |
| + |
| + if (other is VersionUnion) { |
| + return other.constraints.any((constraint) => allowsAny(constraint)); |
| + } |
| + |
| + if (other is VersionRange) { |
| + if (min == null || (other.min != null && min < other.min)) { |
| + if (other.min == null) return true; |
|
Bob Nystrom
2015/05/05 20:49:09
How about hoisting this out of the outer loop? It'
nweiz
2015/05/05 22:52:33
Done.
|
| + if (max == null) return true; |
| + if (max > other.min) return true; |
| + if (max < other.min) return false; |
| + assert(max == other.min); |
| + return includeMax && other.includeMin; |
| + } |
| + |
| + if (other.max == null) return true; |
| + if (min < other.max) return true; |
| + if (min > other.max) return false; |
| + assert(min == other.max); |
| + return includeMin && other.includeMax; |
| + } |
| + |
| + throw new ArgumentError('Unknown VersionConstraint type $other.'); |
| + } |
| + |
| VersionConstraint intersect(VersionConstraint other) { |
| if (other.isEmpty) return other; |
| + if (other is VersionUnion) return other.intersect(this); |
| // A range and a Version just yields the version if it's in the range. |
| if (other is Version) { |
| @@ -162,6 +219,63 @@ class VersionRange implements VersionConstraint { |
| throw new ArgumentError('Unknown VersionConstraint type $other.'); |
| } |
| + VersionConstraint union(VersionConstraint other) { |
| + if (other is Version) { |
| + if (allows(other)) return this; |
| + |
| + if (other == min) { |
| + return new VersionRange( |
| + min: this.min, max: this.max, |
| + includeMin: true, includeMax: this.includeMax); |
| + } |
| + |
| + if (other == max) { |
| + return new VersionRange( |
| + min: this.min, max: this.max, |
| + includeMin: this.includeMin, includeMax: true); |
| + } |
| + } |
| + |
| + if (other is VersionRange) { |
| + // If the two ranges don't overlap, we won't be able to create a single |
| + // VersionRange for both of them. |
| + var edgesTouch = max == other.min && (includeMax || other.includeMin); |
|
Bob Nystrom
2015/05/05 20:49:09
What about the other order:
other.max == min && (
nweiz
2015/05/05 22:52:34
Done.
|
| + if (max != null && other.min != null && max <= other.min && !edgesTouch) { |
| + return new VersionConstraint.unionOf([this, other]); |
| + } |
| + |
| + var unionMin = min; |
| + var unionIncludeMin = includeMin; |
| + var unionMax = max; |
| + var unionIncludeMax = includeMax; |
| + |
| + if (unionMin == null) { |
| + // Do nothing. |
| + } else if (other.min == null || other.min < unionMin) { |
|
Bob Nystrom
2015/05/05 20:49:09
I think it's a bit easier to read if you use "min"
nweiz
2015/05/05 22:52:34
I was mirroring intersect(), but sure.
|
| + unionMin = other.min; |
| + unionIncludeMin = other.includeMin; |
| + } else if (unionMin == other.min && other.includeMin) { |
|
Bob Nystrom
2015/05/05 20:49:09
...and here. That way the reader doesn't have to s
nweiz
2015/05/05 22:52:33
Done.
|
| + // If the edges are the same but one is inclusive, make it inclusive. |
| + unionIncludeMin = true; |
| + } |
| + |
| + if (unionMax == null) { |
| + // Do nothing. |
| + } else if (other.max == null || other.max > unionMax) { |
| + unionMax = other.max; |
| + unionIncludeMax = other.includeMax; |
| + } else if (unionMax == other.max && other.includeMax) { |
| + // If the edges are the same but one is inclusive, make it inclusive. |
| + unionIncludeMax = true; |
| + } |
| + |
| + return new VersionRange(min: unionMin, max: unionMax, |
| + includeMin: unionIncludeMin, includeMax: unionIncludeMax); |
| + } |
| + |
| + return new VersionConstraint.unionOf([this, other]); |
| + } |
| + |
| String toString() { |
| var buffer = new StringBuffer(); |