OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 'utils.dart'; | 5 import 'utils.dart'; |
6 import 'version.dart'; | 6 import 'version.dart'; |
7 import 'version_constraint.dart'; | 7 import 'version_constraint.dart'; |
8 import 'version_union.dart'; | 8 import 'version_union.dart'; |
9 | 9 |
10 /// Constrains versions to a fall within a given range. | 10 /// Constrains versions to a fall within a given range. |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 153 |
154 bool allowsAny(VersionConstraint other) { | 154 bool allowsAny(VersionConstraint other) { |
155 if (other.isEmpty) return false; | 155 if (other.isEmpty) return false; |
156 if (other is Version) return allows(other); | 156 if (other is Version) return allows(other); |
157 | 157 |
158 if (other is VersionUnion) { | 158 if (other is VersionUnion) { |
159 return other.ranges.any((constraint) => allowsAny(constraint)); | 159 return other.ranges.any((constraint) => allowsAny(constraint)); |
160 } | 160 } |
161 | 161 |
162 if (other is VersionRange) { | 162 if (other is VersionRange) { |
163 // If neither range has a minimum, they'll overlap at some point. | 163 return !strictlyLower(other, this) && !strictlyHigher(other, this); |
164 // | |
165 // ... this ] | |
166 // ... other ] | |
167 if (min == null && other.min == null) return true; | |
168 | |
169 // If this range has a lower minimum than the other range, it overlaps as | |
170 // long as its maximum is higher than or the same as the other range's | |
171 // minimum. | |
172 // | |
173 // [ this ] [ this ] | |
174 // [ other ] [ other ] | |
175 if (min == null || (other.min != null && min < other.min)) { | |
176 if (max == null) return true; | |
177 if (max > other.min) return true; | |
178 if (max < other.min) return false; | |
179 assert(max == other.min); | |
180 return includeMax && other.includeMin; | |
181 } | |
182 | |
183 // If this range has a higher minimum than the other range, it overlaps as | |
184 // long as its minimum is lower than or the same as the other range's | |
185 // maximum. | |
186 // | |
187 // [ this ] [ this ] | |
188 // [ other ] [ other ] | |
189 if (other.max == null) return true; | |
190 if (min < other.max) return true; | |
191 if (min > other.max) return false; | |
192 assert(min == other.max); | |
193 return includeMin && other.includeMax; | |
194 } | 164 } |
195 | 165 |
196 throw new ArgumentError('Unknown VersionConstraint type $other.'); | 166 throw new ArgumentError('Unknown VersionConstraint type $other.'); |
197 } | 167 } |
198 | 168 |
199 VersionConstraint intersect(VersionConstraint other) { | 169 VersionConstraint intersect(VersionConstraint other) { |
200 if (other.isEmpty) return other; | 170 if (other.isEmpty) return other; |
201 if (other is VersionUnion) return other.intersect(this); | 171 if (other is VersionUnion) return other.intersect(this); |
202 | 172 |
203 // A range and a Version just yields the version if it's in the range. | 173 // A range and a Version just yields the version if it's in the range. |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 unionIncludeMax = true; | 283 unionIncludeMax = true; |
314 } | 284 } |
315 | 285 |
316 return new VersionRange(min: unionMin, max: unionMax, | 286 return new VersionRange(min: unionMin, max: unionMax, |
317 includeMin: unionIncludeMin, includeMax: unionIncludeMax); | 287 includeMin: unionIncludeMin, includeMax: unionIncludeMax); |
318 } | 288 } |
319 | 289 |
320 return new VersionConstraint.unionOf([this, other]); | 290 return new VersionConstraint.unionOf([this, other]); |
321 } | 291 } |
322 | 292 |
| 293 VersionConstraint difference(VersionConstraint other) { |
| 294 if (other.isEmpty) return this; |
| 295 |
| 296 if (other is Version) { |
| 297 if (!allows(other)) return this; |
| 298 |
| 299 if (other == min) { |
| 300 if (!includeMin) return this; |
| 301 return new VersionRange( |
| 302 min: min, max: max, |
| 303 includeMin: false, includeMax: includeMax); |
| 304 } |
| 305 |
| 306 if (other == max) { |
| 307 if (!includeMax) return this; |
| 308 return new VersionRange( |
| 309 min: min, max: max, |
| 310 includeMin: includeMin, includeMax: false); |
| 311 } |
| 312 |
| 313 return new VersionUnion.fromRanges([ |
| 314 new VersionRange( |
| 315 min: min, max: other, |
| 316 includeMin: includeMin, includeMax: false), |
| 317 new VersionRange( |
| 318 min: other, max: max, |
| 319 includeMin: false, includeMax: includeMax) |
| 320 ]); |
| 321 } else if (other is VersionRange) { |
| 322 if (!allowsAny(other)) return this; |
| 323 |
| 324 VersionConstraint before; |
| 325 if (!allowsLower(this, other)) { |
| 326 before = VersionConstraint.empty; |
| 327 } else if (min == other.min) { |
| 328 assert(includeMin && !other.includeMin); |
| 329 assert(min != null); |
| 330 before = min; |
| 331 } else { |
| 332 before = new VersionRange( |
| 333 min: min, max: other.min, |
| 334 includeMin: includeMin, includeMax: !other.includeMin); |
| 335 } |
| 336 |
| 337 VersionConstraint after; |
| 338 if (!allowsHigher(this, other)) { |
| 339 after = VersionConstraint.empty; |
| 340 } else if (max == other.max) { |
| 341 assert(includeMax && !other.includeMax); |
| 342 assert(max != null); |
| 343 after = max; |
| 344 } else { |
| 345 after = new VersionRange( |
| 346 min: other.max, max: max, |
| 347 includeMin: !other.includeMax, includeMax: includeMax); |
| 348 } |
| 349 |
| 350 if (before == VersionConstraint.empty) return after; |
| 351 if (after == VersionConstraint.empty) return before; |
| 352 return new VersionUnion.fromRanges([before, after]); |
| 353 } else if (other is VersionUnion) { |
| 354 var ranges = <VersionRange>[]; |
| 355 var current = this; |
| 356 |
| 357 for (var range in other.ranges) { |
| 358 // Skip any ranges that are strictly lower than [current]. |
| 359 if (strictlyLower(range, current)) continue; |
| 360 |
| 361 // If we reach a range strictly higher than [current], no more ranges |
| 362 // will be relevant so we can bail early. |
| 363 if (strictlyHigher(range, current)) break; |
| 364 |
| 365 var difference = current.difference(range); |
| 366 if (difference is VersionUnion) { |
| 367 // If [range] split [current] in half, we only need to continue |
| 368 // checking future ranges against the latter half. |
| 369 assert(difference.ranges.length == 2); |
| 370 ranges.add(difference.ranges.first); |
| 371 current = difference.ranges.last; |
| 372 } else { |
| 373 current = difference as VersionRange; |
| 374 } |
| 375 } |
| 376 |
| 377 if (ranges.isEmpty) return current; |
| 378 return new VersionUnion.fromRanges(ranges..add(current)); |
| 379 } |
| 380 |
| 381 throw new ArgumentError('Unknown VersionConstraint type $other.'); |
| 382 } |
| 383 |
323 int compareTo(VersionRange other) { | 384 int compareTo(VersionRange other) { |
324 if (min == null) { | 385 if (min == null) { |
325 if (other.min == null) return compareMax(this, other); | 386 if (other.min == null) return _compareMax(other); |
326 return -1; | 387 return -1; |
327 } else if (other.min == null) { | 388 } else if (other.min == null) { |
328 return 1; | 389 return 1; |
329 } | 390 } |
330 | 391 |
331 var result = min.compareTo(other.min); | 392 var result = min.compareTo(other.min); |
332 if (result != 0) return result; | 393 if (result != 0) return result; |
333 if (includeMin != other.includeMin) return includeMin ? -1 : 1; | 394 if (includeMin != other.includeMin) return includeMin ? -1 : 1; |
334 | 395 |
335 return compareMax(this, other); | 396 return _compareMax(other); |
| 397 } |
| 398 |
| 399 /// Compares the maximum values of [this] and [other]. |
| 400 int _compareMax(VersionRange other) { |
| 401 if (max == null) { |
| 402 if (other.max == null) return 0; |
| 403 return 1; |
| 404 } else if (other.max == null) { |
| 405 return -1; |
| 406 } |
| 407 |
| 408 var result = max.compareTo(other.max); |
| 409 if (result != 0) return result; |
| 410 if (includeMax != other.includeMax) return includeMax ? 1 : -1; |
| 411 return 0; |
336 } | 412 } |
337 | 413 |
338 String toString() { | 414 String toString() { |
339 var buffer = new StringBuffer(); | 415 var buffer = new StringBuffer(); |
340 | 416 |
341 if (min != null) { | 417 if (min != null) { |
342 buffer.write(includeMin ? '>=' : '>'); | 418 buffer.write(includeMin ? '>=' : '>'); |
343 buffer.write(min); | 419 buffer.write(min); |
344 } | 420 } |
345 | 421 |
346 if (max != null) { | 422 if (max != null) { |
347 if (min != null) buffer.write(' '); | 423 if (min != null) buffer.write(' '); |
348 buffer.write(includeMax ? '<=' : '<'); | 424 buffer.write(includeMax ? '<=' : '<'); |
349 buffer.write(max); | 425 buffer.write(max); |
350 } | 426 } |
351 | 427 |
352 if (min == null && max == null) buffer.write('any'); | 428 if (min == null && max == null) buffer.write('any'); |
353 return buffer.toString(); | 429 return buffer.toString(); |
354 } | 430 } |
355 } | 431 } |
OLD | NEW |