Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library unittest.runner.parse_metadata; | |
| 6 | |
| 7 import 'dart:io'; | |
| 8 | |
| 9 import 'package:analyzer/src/generated/ast.dart'; | |
| 10 import 'package:path/path.dart' as p; | |
| 11 import 'package:source_span/source_span.dart'; | |
| 12 | |
| 13 import '../backend/metadata.dart'; | |
| 14 import '../util/dart.dart'; | |
| 15 | |
| 16 /// Parse the test metadata for the test file at [path]. | |
| 17 /// | |
| 18 /// Throws an [AnalysisError] if parsing fails or a [FormatException] if the | |
| 19 /// test annotations are incorrect. | |
| 20 Metadata parseMetadata(String path) { | |
| 21 var testOn; | |
| 22 for (var annotation in parseAnnotations(path)) { | |
| 23 // The annotation syntax is ambiguous between named constructors and | |
| 24 // prefixed annotations. We don't want to have to parse the imports in order | |
| 25 // to resolve this ambiguity, so we just assume that unittest annotations | |
|
Bob Nystrom
2015/03/12 21:03:21
Given that you are parsing the directives now, thi
nweiz
2015/03/12 23:40:22
Done.
| |
| 26 // will never be prefixed. | |
| 27 // | |
| 28 // The analyzer parses "@x.y()" as prefix "x", annotation "y", and named | |
| 29 // constructor null. It parses "@x.y.z()" as prefix "x", annotation "y", and | |
| 30 // named constructor "z". | |
| 31 | |
| 32 // Always skip annotations with constructor names, because they must also | |
| 33 // have prefixes and we assume unittest metadata never has a prefix. | |
| 34 if (annotation.constructorName != null) continue; | |
| 35 | |
| 36 var name; | |
| 37 var constructorName; | |
| 38 var identifier = annotation.name; | |
| 39 if (identifier is PrefixedIdentifier) { | |
| 40 name = identifier.prefix.name; | |
| 41 constructorName = identifier.identifier.name; | |
| 42 } else { | |
| 43 name = identifier.name; | |
| 44 } | |
| 45 | |
| 46 if (name != 'TestOn') continue; | |
| 47 if (constructorName != null) { | |
| 48 throw new SourceSpanFormatException( | |
| 49 'TestOn doesn\'t have a constructor named "$constructorName".', | |
| 50 _spanFor(identifier.identifier, path)); | |
| 51 } | |
| 52 | |
| 53 if (annotation.arguments == null) { | |
| 54 throw new SourceSpanFormatException( | |
| 55 'TestOn takes one argument.', _spanFor(annotation, path)); | |
| 56 } | |
| 57 | |
| 58 var args = annotation.arguments.arguments; | |
| 59 if (args.isEmpty) { | |
| 60 throw new SourceSpanFormatException( | |
| 61 'TestOn takes one argument.', _spanFor(annotation.arguments, path)); | |
| 62 } | |
| 63 | |
| 64 if (args.first is NamedExpression) { | |
| 65 throw new SourceSpanFormatException( | |
| 66 "TestOn doesn't take named parameters.", _spanFor(args.first, path)); | |
| 67 } | |
| 68 | |
| 69 if (args.length > 1) { | |
| 70 throw new SourceSpanFormatException( | |
| 71 "TestOn takes only one argument.", | |
| 72 _spanFor(annotation.arguments, path)); | |
| 73 } | |
| 74 | |
| 75 if (args.first is! StringLiteral) { | |
| 76 throw new SourceSpanFormatException( | |
| 77 "TestOn takes a String.", _spanFor(args.first, path)); | |
|
Bob Nystrom
2015/03/12 21:03:21
Since you don't handle adjacent strings (which is
nweiz
2015/03/12 23:40:22
StringLiteral is the superclass of both adjacent s
| |
| 78 } | |
| 79 | |
| 80 if (testOn != null) { | |
| 81 throw new SourceSpanFormatException( | |
| 82 "Only a single TestOn annotation may be used for a given test file.", | |
| 83 _spanFor(annotation, path)); | |
| 84 } | |
| 85 | |
| 86 testOn = args.first.stringValue; | |
| 87 } | |
| 88 | |
| 89 return new Metadata(testOn); | |
| 90 } | |
| 91 | |
| 92 /// Creates a [SourceSpan] for [node]. | |
| 93 SourceSpan _spanFor(AstNode node, String path) => | |
| 94 // Load a SourceFile from scratch here since we're only ever going to emit | |
| 95 // one error per file anyway. | |
| 96 new SourceFile(new File(path).readAsStringSync(), url: p.toUri(path)) | |
| 97 .span(node.offset, node.end); | |
| OLD | NEW |