Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: lib/src/version_union.dart

Issue 2045803002: Add VersionConstraint.difference(). (Closed) Base URL: git@github.com:dart-lang/pub_semver@master
Patch Set: Code review changes Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/version_range.dart ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 lower max value forward. This ensures that 77 // Move the constraint with the lower max value forward. This ensures that
78 // 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 (allowsHigher(theirRanges.current, ourRanges.current)) {
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 lower max value forward. This ensures that 104 // Move the constraint with the lower max value forward. This ensures that
105 // we keep both lists in sync as much as possible, and that large ranges 105 // we keep both lists in sync as much as possible, and that large ranges
106 // 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 (allowsHigher(theirRanges.current, ourRanges.current)) {
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
117 return new VersionUnion.fromRanges(newRanges); 117 return new VersionUnion.fromRanges(newRanges);
118 } 118 }
119 119
120 VersionConstraint difference(VersionConstraint other) {
121 var ourRanges = ranges.iterator;
122 var theirRanges = _rangesFor(other).iterator;
123
124 var newRanges = <VersionRange>[];
125 ourRanges.moveNext();
126 theirRanges.moveNext();
127 var current = ourRanges.current;
128
129 theirNextRange() {
130 if (theirRanges.moveNext()) return true;
131
132 // If there are no more of their ranges, none of the rest of our ranges
133 // need to be subtracted so we can add them as-is.
134 newRanges.add(current);
135 while (ourRanges.moveNext()) {
136 newRanges.add(ourRanges.current);
137 }
138 return false;
139 }
140
141 ourNextRange({bool includeCurrent: true}) {
142 if (includeCurrent) newRanges.add(current);
143 if (!ourRanges.moveNext()) return false;
144 current = ourRanges.current;
145 return true;
146 }
147
148 while (true) {
149 // If the current ranges are disjoint, move the lowest one forward.
150 if (strictlyLower(theirRanges.current, current)) {
151 if (!theirNextRange()) break;
152 continue;
153 }
154
155 if (strictlyHigher(theirRanges.current, current)) {
156 if (!ourNextRange()) break;
157 continue;
158 }
159
160 // If we're here, we know [theirRanges.current] overlaps [current].
161 var difference = current.difference(theirRanges.current);
162 if (difference is VersionUnion) {
163 // If their range split [current] in half, we only need to continue
164 // checking future ranges against the latter half.
165 assert(difference.ranges.length == 2);
166 newRanges.add(difference.ranges.first);
167 current = difference.ranges.last;
168
169 // Since their range split [current], it definitely doesn't allow higher
170 // versions, so we should move their ranges forward.
171 if (!theirNextRange()) break;
172 } else if (difference.isEmpty) {
173 if (!ourNextRange(includeCurrent: false)) break;
174 } else {
175 current = difference as VersionRange;
176
177 // Move the constraint with the lower max value forward. This ensures
178 // that we keep both lists in sync as much as possible, and that large
179 // ranges have a chance to subtract or be subtracted by multiple small
180 // ranges that they contain.
181 if (allowsHigher(current, theirRanges.current)) {
182 if (!theirNextRange()) break;
183 } else {
184 if (!ourNextRange()) break;
185 }
186 }
187 }
188
189 if (newRanges.isEmpty) return VersionConstraint.empty;
190 if (newRanges.length == 1) return newRanges.single;
191 return new VersionUnion.fromRanges(newRanges);
192 }
193
120 /// Returns [constraint] as a list of ranges. 194 /// Returns [constraint] as a list of ranges.
121 /// 195 ///
122 /// This is used to normalize ranges of various types. 196 /// This is used to normalize ranges of various types.
123 List<VersionRange> _rangesFor(VersionConstraint constraint) { 197 List<VersionRange> _rangesFor(VersionConstraint constraint) {
124 if (constraint.isEmpty) return []; 198 if (constraint.isEmpty) return [];
125 if (constraint is VersionUnion) return constraint.ranges; 199 if (constraint is VersionUnion) return constraint.ranges;
126 if (constraint is VersionRange) return [constraint]; 200 if (constraint is VersionRange) return [constraint];
127 throw new ArgumentError('Unknown VersionConstraint type $constraint.'); 201 throw new ArgumentError('Unknown VersionConstraint type $constraint.');
128 } 202 }
129 203
130 VersionConstraint union(VersionConstraint other) => 204 VersionConstraint union(VersionConstraint other) =>
131 new VersionConstraint.unionOf([this, other]); 205 new VersionConstraint.unionOf([this, other]);
132 206
133 bool operator ==(other) { 207 bool operator ==(other) {
134 if (other is! VersionUnion) return false; 208 if (other is! VersionUnion) return false;
135 return const ListEquality().equals(ranges, other.ranges); 209 return const ListEquality().equals(ranges, other.ranges);
136 } 210 }
137 211
138 int get hashCode => const ListEquality().hash(ranges); 212 int get hashCode => const ListEquality().hash(ranges);
139 213
140 String toString() => ranges.join(" or "); 214 String toString() => ranges.join(" or ");
141 } 215 }
OLDNEW
« no previous file with comments | « lib/src/version_range.dart ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698