OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'package:collection/collection.dart'; | 5 import 'package:collection/collection.dart'; |
6 | 6 |
7 import 'utils.dart'; | 7 import 'utils.dart'; |
8 import 'version.dart'; | 8 import 'version.dart'; |
9 import 'version_constraint.dart'; | 9 import 'version_constraint.dart'; |
10 import 'version_range.dart'; | 10 import 'version_range.dart'; |
11 | 11 |
12 /// A version constraint representing a union of multiple disjoint version | 12 /// A version constraint representing a union of multiple disjoint version |
13 /// ranges. | 13 /// ranges. |
14 /// | 14 /// |
15 /// An instance of this will only be created if the version can't be represented | 15 /// An instance of this will only be created if the version can't be represented |
16 /// as a non-compound value. | 16 /// as a non-compound value. |
17 class VersionUnion implements VersionConstraint { | 17 class VersionUnion implements VersionConstraint { |
18 /// The constraints that compose this union. | 18 /// The constraints that compose this union. |
19 /// | 19 /// |
20 /// This list has two invariants: | 20 /// This list has two invariants: |
21 /// | 21 /// |
22 /// * Its contents are sorted from lowest to highest matched versions. | 22 /// * Its contents are sorted using the standard ordering of [VersionRange]s. |
23 /// * Its contents are disjoint and non-adjacent. In other words, for any two | 23 /// * Its contents are disjoint and non-adjacent. In other words, for any two |
24 /// constraints next to each other in the list, there's some version between | 24 /// constraints next to each other in the list, there's some version between |
25 /// those constraints that they don't match. | 25 /// those constraints that they don't match. |
26 final List<VersionRange> ranges; | 26 final List<VersionRange> ranges; |
27 | 27 |
28 bool get isEmpty => false; | 28 bool get isEmpty => false; |
29 | 29 |
30 bool get isAny => false; | 30 bool get isAny => false; |
31 | 31 |
32 /// Creates a union from a list of ranges with no pre-processing. | 32 /// Creates a union from a list of ranges with no pre-processing. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 | 67 |
68 // Because both lists of ranges are ordered by minimum version, we can | 68 // Because both lists of ranges are ordered by minimum version, we can |
69 // safely move through them linearly here. | 69 // safely move through them linearly here. |
70 ourRanges.moveNext(); | 70 ourRanges.moveNext(); |
71 theirRanges.moveNext(); | 71 theirRanges.moveNext(); |
72 while (ourRanges.current != null && theirRanges.current != null) { | 72 while (ourRanges.current != null && theirRanges.current != null) { |
73 if (ourRanges.current.allowsAny(theirRanges.current)) { | 73 if (ourRanges.current.allowsAny(theirRanges.current)) { |
74 return true; | 74 return true; |
75 } | 75 } |
76 | 76 |
77 // Move the constraint with the higher max value forward. This ensures | 77 // Move the constraint with the lower max value forward. This ensures that |
78 // that we keep both lists in sync as much as possible. | 78 // we keep both lists in sync as much as possible. |
79 if (compareMax(ourRanges.current, theirRanges.current) < 0) { | 79 if (compareMax(ourRanges.current, theirRanges.current) < 0) { |
80 ourRanges.moveNext(); | 80 ourRanges.moveNext(); |
81 } else { | 81 } else { |
82 theirRanges.moveNext(); | 82 theirRanges.moveNext(); |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 return false; | 86 return false; |
87 } | 87 } |
88 | 88 |
89 VersionConstraint intersect(VersionConstraint other) { | 89 VersionConstraint intersect(VersionConstraint other) { |
90 var ourRanges = ranges.iterator; | 90 var ourRanges = ranges.iterator; |
91 var theirRanges = _rangesFor(other).iterator; | 91 var theirRanges = _rangesFor(other).iterator; |
92 | 92 |
93 // Because both lists of ranges are ordered by minimum version, we can | 93 // Because both lists of ranges are ordered by minimum version, we can |
94 // safely move through them linearly here. | 94 // safely move through them linearly here. |
95 var newRanges = <VersionRange>[]; | 95 var newRanges = <VersionRange>[]; |
96 ourRanges.moveNext(); | 96 ourRanges.moveNext(); |
97 theirRanges.moveNext(); | 97 theirRanges.moveNext(); |
98 while (ourRanges.current != null && theirRanges.current != null) { | 98 while (ourRanges.current != null && theirRanges.current != null) { |
99 var intersection = ourRanges.current | 99 var intersection = ourRanges.current |
100 .intersect(theirRanges.current); | 100 .intersect(theirRanges.current); |
101 | 101 |
102 if (!intersection.isEmpty) newRanges.add(intersection); | 102 if (!intersection.isEmpty) newRanges.add(intersection); |
103 | 103 |
104 // Move the constraint with the higher max value forward. This ensures | 104 // Move the constraint with the lower max value forward. This ensures that |
105 // that we keep both lists in sync as much as possible, and that large | 105 // we keep both lists in sync as much as possible, and that large ranges |
106 // ranges have a chance to match multiple small ranges that they contain. | 106 // have a chance to match multiple small ranges that they contain. |
107 if (compareMax(ourRanges.current, theirRanges.current) < 0) { | 107 if (compareMax(ourRanges.current, theirRanges.current) < 0) { |
108 ourRanges.moveNext(); | 108 ourRanges.moveNext(); |
109 } else { | 109 } else { |
110 theirRanges.moveNext(); | 110 theirRanges.moveNext(); |
111 } | 111 } |
112 } | 112 } |
113 | 113 |
114 if (newRanges.isEmpty) return VersionConstraint.empty; | 114 if (newRanges.isEmpty) return VersionConstraint.empty; |
115 if (newRanges.length == 1) return newRanges.single; | 115 if (newRanges.length == 1) return newRanges.single; |
116 | 116 |
(...skipping 15 matching lines...) Expand all Loading... |
132 | 132 |
133 bool operator ==(other) { | 133 bool operator ==(other) { |
134 if (other is! VersionUnion) return false; | 134 if (other is! VersionUnion) return false; |
135 return const ListEquality().equals(ranges, other.ranges); | 135 return const ListEquality().equals(ranges, other.ranges); |
136 } | 136 } |
137 | 137 |
138 int get hashCode => const ListEquality().hash(ranges); | 138 int get hashCode => const ListEquality().hash(ranges); |
139 | 139 |
140 String toString() => ranges.join(" or "); | 140 String toString() => ranges.join(" or "); |
141 } | 141 } |
OLD | NEW |