| 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:boolean_selector/boolean_selector.dart'; |
| 5 import 'package:source_span/source_span.dart'; | 6 import 'package:source_span/source_span.dart'; |
| 6 | 7 |
| 7 import 'operating_system.dart'; | 8 import 'operating_system.dart'; |
| 8 import 'platform_selector/ast.dart'; | |
| 9 import 'platform_selector/evaluator.dart'; | |
| 10 import 'platform_selector/parser.dart'; | |
| 11 import 'platform_selector/visitor.dart'; | |
| 12 import 'test_platform.dart'; | 9 import 'test_platform.dart'; |
| 13 | 10 |
| 14 /// The set of all valid variable names. | 11 /// The set of all valid variable names. |
| 15 final _validVariables = | 12 final _validVariables = |
| 16 new Set<String>.from(["posix", "dart-vm", "browser", "js", "blink"]) | 13 new Set<String>.from(["posix", "dart-vm", "browser", "js", "blink"]) |
| 17 ..addAll(TestPlatform.all.map((platform) => platform.identifier)) | 14 ..addAll(TestPlatform.all.map((platform) => platform.identifier)) |
| 18 ..addAll(OperatingSystem.all.map((os) => os.name)); | 15 ..addAll(OperatingSystem.all.map((os) => os.name)); |
| 19 | 16 |
| 20 /// An expression for selecting certain platforms, including operating systems | 17 /// An expression for selecting certain platforms, including operating systems |
| 21 /// and browsers. | 18 /// and browsers. |
| 22 /// | 19 /// |
| 23 /// The syntax is mostly Dart's expression syntax restricted to boolean | 20 /// This uses the [boolean selector][] syntax. |
| 24 /// operations. See [the README][] for full details. | |
| 25 /// | 21 /// |
| 26 /// [the README]: https://github.com/dart-lang/test/#platform-selector-syntax | 22 /// [boolean selector]: https://pub.dartlang.org/packages/boolean_selector |
| 27 abstract class PlatformSelector { | 23 class PlatformSelector { |
| 28 /// A selector that declares that a test can be run on all platforms. | 24 /// A selector that declares that a test can be run on all platforms. |
| 29 /// | 25 static const all = const PlatformSelector._(BooleanSelector.all); |
| 30 /// This isn't representable in the platform selector syntax but it is the | 26 |
| 31 /// default selector. | 27 /// The boolean selector used to implement this selector. |
| 32 static const all = const _AllPlatforms(); | 28 final BooleanSelector _inner; |
| 33 | 29 |
| 34 /// Parses [selector]. | 30 /// Parses [selector]. |
| 35 /// | 31 /// |
| 36 /// This will throw a [SourceSpanFormatException] if the selector is | 32 /// This will throw a [SourceSpanFormatException] if the selector is |
| 37 /// malformed or if it uses an undefined variable. | 33 /// malformed or if it uses an undefined variable. |
| 38 factory PlatformSelector.parse(String selector) => | 34 PlatformSelector.parse(String selector) |
| 39 new _PlatformSelector.parse(selector); | 35 : _inner = new BooleanSelector.parse(selector) { |
| 36 _inner.validate(_validVariables.contains); |
| 37 } |
| 38 |
| 39 const PlatformSelector._(this._inner); |
| 40 | 40 |
| 41 /// Returns whether the selector matches the given [platform] and [os]. | 41 /// Returns whether the selector matches the given [platform] and [os]. |
| 42 /// | 42 /// |
| 43 /// [os] defaults to [OperatingSystem.none]. | 43 /// [os] defaults to [OperatingSystem.none]. |
| 44 bool evaluate(TestPlatform platform, {OperatingSystem os}); | 44 bool evaluate(TestPlatform platform, {OperatingSystem os}) { |
| 45 os ??= OperatingSystem.none; |
| 46 |
| 47 return _inner.evaluate((variable) { |
| 48 if (variable == platform.identifier) return true; |
| 49 if (variable == os.name) return true; |
| 50 switch (variable) { |
| 51 case "dart-vm": return platform.isDartVM; |
| 52 case "browser": return platform.isBrowser; |
| 53 case "js": return platform.isJS; |
| 54 case "blink": return platform.isBlink; |
| 55 case "posix": return os.isPosix; |
| 56 default: return false; |
| 57 } |
| 58 }); |
| 59 } |
| 45 | 60 |
| 46 /// Returns a new [PlatformSelector] that matches only platforms matched by | 61 /// Returns a new [PlatformSelector] that matches only platforms matched by |
| 47 /// both [this] and [other]. | 62 /// both [this] and [other]. |
| 48 PlatformSelector intersect(PlatformSelector other); | 63 PlatformSelector intersection(PlatformSelector other) { |
| 49 } | 64 if (other == PlatformSelector.all) return this; |
| 50 | 65 return new PlatformSelector._(_inner.intersection(other._inner)); |
| 51 /// The concrete implementation of a [PlatformSelector] parsed from a string. | |
| 52 /// | |
| 53 /// This is separate from [PlatformSelector] so that [_AllPlatforms] can | |
| 54 /// implement [PlatformSelector] without having to implement private members. | |
| 55 class _PlatformSelector implements PlatformSelector{ | |
| 56 /// The parsed AST. | |
| 57 final Node _selector; | |
| 58 | |
| 59 _PlatformSelector.parse(String selector) | |
| 60 : _selector = new Parser(selector).parse() { | |
| 61 _selector.accept(const _VariableValidator()); | |
| 62 } | 66 } |
| 63 | 67 |
| 64 _PlatformSelector(this._selector); | 68 String toString() => _inner.toString(); |
| 65 | |
| 66 bool evaluate(TestPlatform platform, {OperatingSystem os}) => | |
| 67 _selector.accept(new Evaluator(platform, os: os)); | |
| 68 | |
| 69 PlatformSelector intersect(PlatformSelector other) { | |
| 70 if (other == PlatformSelector.all) return this; | |
| 71 return new _PlatformSelector(new AndNode( | |
| 72 _selector, (other as _PlatformSelector)._selector)); | |
| 73 } | |
| 74 | |
| 75 String toString() => _selector.toString(); | |
| 76 } | 69 } |
| 77 | |
| 78 /// A selector that matches all platforms. | |
| 79 class _AllPlatforms implements PlatformSelector { | |
| 80 const _AllPlatforms(); | |
| 81 | |
| 82 bool evaluate(TestPlatform platform, {OperatingSystem os}) => true; | |
| 83 | |
| 84 PlatformSelector intersect(PlatformSelector other) => other; | |
| 85 | |
| 86 String toString() => "*"; | |
| 87 } | |
| 88 | |
| 89 /// An AST visitor that ensures that all variables are valid. | |
| 90 /// | |
| 91 /// This isn't done when evaluating to ensure that errors are eagerly detected, | |
| 92 /// and it isn't done when parsing to avoid coupling the syntax too tightly to | |
| 93 /// the semantics. | |
| 94 class _VariableValidator extends RecursiveVisitor { | |
| 95 const _VariableValidator(); | |
| 96 | |
| 97 void visitVariable(VariableNode node) { | |
| 98 if (_validVariables.contains(node.name)) return; | |
| 99 throw new SourceSpanFormatException("Undefined variable.", node.span); | |
| 100 } | |
| 101 } | |
| OLD | NEW |