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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 } | 76 } |
77 source = source.trim(); | 77 source = source.trim(); |
78 | 78 |
79 // Ignore empty (or comment-only) lines. | 79 // Ignore empty (or comment-only) lines. |
80 if (source.isEmpty) continue; | 80 if (source.isEmpty) continue; |
81 | 81 |
82 // See if we are starting a new section. | 82 // See if we are starting a new section. |
83 var match = _sectionPattern.firstMatch(source); | 83 var match = _sectionPattern.firstMatch(source); |
84 if (match != null) { | 84 if (match != null) { |
85 try { | 85 try { |
86 section = new StatusSection(Expression.parse(match[1].trim())); | 86 var condition = Expression.parse(match[1].trim()); |
| 87 section = new StatusSection(condition, lineNumber); |
87 sections.add(section); | 88 sections.add(section); |
88 } on FormatException { | 89 } on FormatException { |
89 fail("Status expression syntax error"); | 90 fail("Status expression syntax error"); |
90 } | 91 } |
91 continue; | 92 continue; |
92 } | 93 } |
93 | 94 |
94 // Otherwise, it should be a new entry under the current section. | 95 // Otherwise, it should be a new entry under the current section. |
95 match = _entryPattern.firstMatch(source); | 96 match = _entryPattern.firstMatch(source); |
96 if (match != null) { | 97 if (match != null) { |
97 var path = match[1].trim(); | 98 var path = match[1].trim(); |
98 // TODO(whesse): Handle test names ending in a wildcard (*). | 99 // TODO(whesse): Handle test names ending in a wildcard (*). |
99 var expectations = <Expectation>[]; | 100 var expectations = <Expectation>[]; |
100 for (var name in match[2].split(",")) { | 101 for (var name in match[2].split(",")) { |
101 name = name.trim(); | 102 name = name.trim(); |
102 try { | 103 try { |
103 expectations.add(Expectation.find(name)); | 104 expectations.add(Expectation.find(name)); |
104 } on ArgumentError { | 105 } on ArgumentError { |
105 fail('Unrecognized test expectation "$name"'); | 106 fail('Unrecognized test expectation "$name"'); |
106 } | 107 } |
107 } | 108 } |
108 | 109 |
109 var issue = _issueNumber(comment); | 110 var issue = _issueNumber(comment); |
110 | 111 |
111 // If we haven't found a section header yet, create an implicit section | 112 // If we haven't found a section header yet, create an implicit section |
112 // that matches everything. | 113 // that matches everything. |
113 if (section == null) { | 114 if (section == null) { |
114 section = new StatusSection(null); | 115 section = new StatusSection(null, -1); |
115 sections.add(section); | 116 sections.add(section); |
116 } | 117 } |
117 | 118 |
118 section.entries.add(new StatusEntry(path, expectations, issue)); | 119 section.entries |
| 120 .add(new StatusEntry(path, lineNumber, expectations, issue)); |
119 continue; | 121 continue; |
120 } | 122 } |
121 | 123 |
122 fail("Unrecognized input"); | 124 fail("Unrecognized input"); |
123 } | 125 } |
124 } | 126 } |
125 | 127 |
126 bool get isEmpty => sections.isEmpty; | 128 bool get isEmpty => sections.isEmpty; |
127 | 129 |
128 /// Validates that the variables and values used in all of the section | 130 /// Validates that the variables and values used in all of the section |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 /// One section in a status file. | 183 /// One section in a status file. |
182 /// | 184 /// |
183 /// Contains the condition from the header that begins the section, then all of | 185 /// Contains the condition from the header that begins the section, then all of |
184 /// the entries within the section. | 186 /// the entries within the section. |
185 class StatusSection { | 187 class StatusSection { |
186 /// The expression that determines when this section is applied. | 188 /// The expression that determines when this section is applied. |
187 /// | 189 /// |
188 /// May be `null` for paths that appear before any section header in the file. | 190 /// May be `null` for paths that appear before any section header in the file. |
189 /// In that case, the section always applies. | 191 /// In that case, the section always applies. |
190 final Expression condition; | 192 final Expression condition; |
| 193 |
| 194 /// The one-based line number where the entry appears in the file. |
| 195 final int lineNumber; |
| 196 |
191 final List<StatusEntry> entries = []; | 197 final List<StatusEntry> entries = []; |
192 | 198 |
193 /// Returns true if this section should apply in the given [environment]. | 199 /// Returns true if this section should apply in the given [environment]. |
194 bool isEnabled(Environment environment) => | 200 bool isEnabled(Environment environment) => |
195 condition == null || condition.evaluate(environment); | 201 condition == null || condition.evaluate(environment); |
196 | 202 |
197 StatusSection(this.condition); | 203 StatusSection(this.condition, this.lineNumber); |
198 } | 204 } |
199 | 205 |
200 /// Describes the test status of the file or files at a given path. | 206 /// Describes the test status of the file or files at a given path. |
201 class StatusEntry { | 207 class StatusEntry { |
202 final String path; | 208 final String path; |
| 209 |
| 210 /// The one-based line number where the entry appears in the file. |
| 211 final int lineNumber; |
| 212 |
203 final List<Expectation> expectations; | 213 final List<Expectation> expectations; |
204 final int issue; | 214 final int issue; |
205 | 215 |
206 StatusEntry(this.path, this.expectations, this.issue); | 216 StatusEntry(this.path, this.lineNumber, this.expectations, this.issue); |
207 } | 217 } |
208 | 218 |
209 /// Error thrown when a parse or validation error occurs in a [StatusFile]. | 219 /// Error thrown when a parse or validation error occurs in a [StatusFile]. |
210 class SyntaxError implements Exception { | 220 class SyntaxError implements Exception { |
211 final String file; | 221 final String file; |
212 final int lineNumber; | 222 final int lineNumber; |
213 final String line; | 223 final String line; |
214 final String message; | 224 final String message; |
215 final List<String> errors; | 225 final List<String> errors; |
216 | 226 |
217 SyntaxError(this.file, this.lineNumber, this.line, this.message, this.errors); | 227 SyntaxError(this.file, this.lineNumber, this.line, this.message, this.errors); |
218 | 228 |
219 String toString() { | 229 String toString() { |
220 var buffer = new StringBuffer(); | 230 var buffer = new StringBuffer(); |
221 buffer.writeln('$message in "$file" line $lineNumber:'); | 231 buffer.writeln('$message in "$file" line $lineNumber:'); |
222 buffer.writeln(line); | 232 buffer.writeln(line); |
223 | 233 |
224 if (errors != null) { | 234 if (errors != null) { |
225 for (var error in errors) { | 235 for (var error in errors) { |
226 buffer.writeln("- ${error.replaceAll('\n', '\n ')}"); | 236 buffer.writeln("- ${error.replaceAll('\n', '\n ')}"); |
227 } | 237 } |
228 } | 238 } |
229 | 239 |
230 return buffer.toString().trimRight(); | 240 return buffer.toString().trimRight(); |
231 } | 241 } |
232 } | 242 } |
OLD | NEW |