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 |