OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 'dart:io'; | 5 import 'dart:io'; |
6 | 6 |
7 import 'package:path/path.dart' as p; | 7 import 'package:path/path.dart' as p; |
8 | 8 |
9 import 'environment.dart'; | 9 import 'environment.dart'; |
10 import 'expectation.dart'; | 10 import 'expectation.dart'; |
(...skipping 25 matching lines...) Expand all Loading... |
36 /// an environment. If it evaluates to true, then the entries after the header | 36 /// an environment. If it evaluates to true, then the entries after the header |
37 /// take effect. | 37 /// take effect. |
38 /// | 38 /// |
39 /// Each entry is a glob-like file path followed by a colon and then a | 39 /// Each entry is a glob-like file path followed by a colon and then a |
40 /// comma-separated list of [Expectation]s. The path may point to an individual | 40 /// comma-separated list of [Expectation]s. The path may point to an individual |
41 /// file, or a directory, in which case it applies to all files under that path. | 41 /// file, or a directory, in which case it applies to all files under that path. |
42 /// | 42 /// |
43 /// Entries may also appear before any section header, in which case they | 43 /// Entries may also appear before any section header, in which case they |
44 /// always apply. | 44 /// always apply. |
45 class StatusFile { | 45 class StatusFile { |
46 final String _path; | 46 final String path; |
47 final List<StatusSection> sections = []; | 47 final List<StatusSection> sections = []; |
48 | 48 |
49 /// Parses the status file at [_path]. | 49 StatusFile(this.path); |
| 50 |
| 51 /// Parses the status file at [path]. |
50 /// | 52 /// |
51 /// Throws a [SyntaxError] if the file could not be parsed. | 53 /// Throws a [SyntaxError] if the file could not be parsed. |
52 StatusFile.read(this._path) { | 54 StatusFile.read(this.path) { |
53 var lines = new File(_path).readAsLinesSync(); | 55 var lines = new File(path).readAsLinesSync(); |
54 | 56 |
55 // The current section whose rules are being parsed. | 57 // The current section whose rules are being parsed. |
56 StatusSection section; | 58 StatusSection section; |
57 | 59 |
58 var lineNumber = 0; | 60 var lineNumber = 0; |
59 | 61 |
60 for (var line in lines) { | 62 for (var line in lines) { |
61 lineNumber++; | 63 lineNumber++; |
62 | 64 |
63 fail(String message, [List<String> errors]) { | 65 fail(String message, [List<String> errors]) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 } | 116 } |
115 | 117 |
116 section.entries.add(new StatusEntry(path, expectations, issue)); | 118 section.entries.add(new StatusEntry(path, expectations, issue)); |
117 continue; | 119 continue; |
118 } | 120 } |
119 | 121 |
120 fail("Unrecognized input"); | 122 fail("Unrecognized input"); |
121 } | 123 } |
122 } | 124 } |
123 | 125 |
| 126 bool get isEmpty => sections.isEmpty; |
| 127 |
124 /// Validates that the variables and values used in all of the section | 128 /// Validates that the variables and values used in all of the section |
125 /// condition expressions are defined in [environment]. | 129 /// condition expressions are defined in [environment]. |
126 /// | 130 /// |
127 /// Throws a [SyntaxError] on the first found error. | 131 /// Throws a [SyntaxError] on the first found error. |
128 void validate(Environment environment) { | 132 void validate(Environment environment) { |
129 // TODO(rnystrom): It would be more useful if it reported all of the errors | 133 // TODO(rnystrom): It would be more useful if it reported all of the errors |
130 // instead of stopping on the first. | 134 // instead of stopping on the first. |
131 for (var section in sections) { | 135 for (var section in sections) { |
132 if (section._condition == null) continue; | 136 if (section.condition == null) continue; |
133 | 137 |
134 var errors = <String>[]; | 138 var errors = <String>[]; |
135 section._condition.validate(environment, errors); | 139 section.condition.validate(environment, errors); |
136 | 140 |
137 if (errors.isNotEmpty) { | 141 if (errors.isNotEmpty) { |
138 var s = errors.length > 1 ? "s" : ""; | 142 var s = errors.length > 1 ? "s" : ""; |
139 throw new SyntaxError(_shortPath, section.lineNumber, | 143 throw new SyntaxError(_shortPath, section.lineNumber, |
140 "[ ${section._condition} ]", 'Validation error$s', errors); | 144 "[ ${section.condition} ]", 'Validation error$s', errors); |
141 } | 145 } |
142 } | 146 } |
143 } | 147 } |
144 | 148 |
145 /// Gets the path to this status file relative to the Dart repo root. | 149 /// Gets the path to this status file relative to the Dart repo root. |
146 String get _shortPath { | 150 String get _shortPath { |
147 var repoRoot = p.join(p.dirname(p.fromUri(Platform.script)), "../../../"); | 151 var repoRoot = p.join(p.dirname(p.fromUri(Platform.script)), "../../../"); |
148 return p.normalize(p.relative(_path, from: repoRoot)); | 152 return p.normalize(p.relative(path, from: repoRoot)); |
149 } | 153 } |
150 | 154 |
151 /// Returns the issue number embedded in [comment] or `null` if there is none. | 155 /// Returns the issue number embedded in [comment] or `null` if there is none. |
152 int _issueNumber(String comment) { | 156 int _issueNumber(String comment) { |
153 var match = _issuePattern.firstMatch(comment); | 157 var match = _issuePattern.firstMatch(comment); |
154 if (match == null) return null; | 158 if (match == null) return null; |
155 | 159 |
156 return int.parse(match[1]); | 160 return int.parse(match[1]); |
157 } | 161 } |
158 | 162 |
159 String toString() { | 163 String toString() { |
160 var buffer = new StringBuffer(); | 164 var buffer = new StringBuffer(); |
161 for (var section in sections) { | 165 for (var section in sections) { |
162 buffer.writeln("[ ${section._condition} ]"); | 166 buffer.writeln("[ ${section.condition} ]"); |
163 | 167 |
164 for (var entry in section.entries) { | 168 for (var entry in section.entries) { |
165 buffer.write("${entry.path}: ${entry.expectations.join(', ')}"); | 169 buffer.write("${entry.path}: ${entry.expectations.join(', ')}"); |
166 if (entry.issue != null) buffer.write(" # Issue ${entry.issue}"); | 170 if (entry.issue != null) buffer.write(" # Issue ${entry.issue}"); |
167 buffer.writeln(); | 171 buffer.writeln(); |
168 } | 172 } |
169 | 173 |
170 buffer.writeln(); | 174 buffer.writeln(); |
171 } | 175 } |
172 | 176 |
173 return buffer.toString(); | 177 return buffer.toString(); |
174 } | 178 } |
175 } | 179 } |
176 | 180 |
177 /// One section in a status file. | 181 /// One section in a status file. |
178 /// | 182 /// |
179 /// Contains the condition from the header that begins the section, then all of | 183 /// Contains the condition from the header that begins the section, then all of |
180 /// the entries within the section. | 184 /// the entries within the section. |
181 class StatusSection { | 185 class StatusSection { |
182 /// The expression that determines when this section is applied. | 186 /// The expression that determines when this section is applied. |
183 /// | 187 /// |
184 /// May be `null` for paths that appear before any section header in the file. | 188 /// May be `null` for paths that appear before any section header in the file. |
185 /// In that case, the section always applies. | 189 /// In that case, the section always applies. |
186 final Expression _condition; | 190 final Expression condition; |
187 final List<StatusEntry> entries = []; | 191 final List<StatusEntry> entries = []; |
188 | 192 |
189 /// Returns true if this section should apply in the given [environment]. | 193 /// Returns true if this section should apply in the given [environment]. |
190 bool isEnabled(Environment environment) => | 194 bool isEnabled(Environment environment) => |
191 _condition == null || _condition.evaluate(environment); | 195 condition == null || condition.evaluate(environment); |
192 | 196 |
193 StatusSection(this._condition); | 197 StatusSection(this.condition); |
194 } | 198 } |
195 | 199 |
196 /// Describes the test status of the file or files at a given path. | 200 /// Describes the test status of the file or files at a given path. |
197 class StatusEntry { | 201 class StatusEntry { |
198 final String path; | 202 final String path; |
199 final List<Expectation> expectations; | 203 final List<Expectation> expectations; |
200 final int issue; | 204 final int issue; |
201 | 205 |
202 StatusEntry(this.path, this.expectations, this.issue); | 206 StatusEntry(this.path, this.expectations, this.issue); |
203 } | 207 } |
(...skipping 15 matching lines...) Expand all Loading... |
219 | 223 |
220 if (errors != null) { | 224 if (errors != null) { |
221 for (var error in errors) { | 225 for (var error in errors) { |
222 buffer.writeln("- ${error.replaceAll('\n', '\n ')}"); | 226 buffer.writeln("- ${error.replaceAll('\n', '\n ')}"); |
223 } | 227 } |
224 } | 228 } |
225 | 229 |
226 return buffer.toString().trimRight(); | 230 return buffer.toString().trimRight(); |
227 } | 231 } |
228 } | 232 } |
OLD | NEW |