OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library docgen.models.annotation; | 5 library docgen.models.annotation; |
6 | 6 |
7 import '../exports/mirrors_util.dart' as dart2js_util; | |
8 import '../exports/source_mirrors.dart'; | 7 import '../exports/source_mirrors.dart'; |
9 | 8 |
| 9 import '../exports/dart2js_mirrors.dart' show ResolvedNode; |
| 10 |
10 import '../library_helpers.dart'; | 11 import '../library_helpers.dart'; |
11 | 12 |
12 import 'library.dart'; | 13 import 'library.dart'; |
13 import 'mirror_based.dart'; | 14 import 'mirror_based.dart'; |
14 | 15 |
| 16 import 'dart:mirrors'; |
| 17 import '../../../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart'
; |
| 18 |
15 /// Holds the name of the annotation, and its parameters. | 19 /// Holds the name of the annotation, and its parameters. |
16 class Annotation extends MirrorBased<ClassMirror> { | 20 class Annotation extends MirrorBased<ClassMirror> { |
17 /// The class of this annotation. | 21 /// The class of this annotation. |
18 final ClassMirror mirror; | 22 DeclarationMirror mirror; |
| 23 Send node; |
19 final Library owningLibrary; | 24 final Library owningLibrary; |
20 final List<String> parameters; | 25 List<String> parameters; |
21 | 26 |
22 Annotation(InstanceMirror originalMirror, this.owningLibrary) | 27 Annotation(ResolvedNode resolvedNode, this.owningLibrary) { |
23 : mirror = originalMirror.type, | 28 parameters = []; |
24 parameters = _createParamaters(originalMirror); | 29 getMirrorForResolvedNode(resolvedNode, (m, n) { mirror = m; node = n;}, |
| 30 (String param) => parameters.add(param)); |
| 31 } |
| 32 |
| 33 String getMirrorForResolvedNode(ResolvedNode node, callbackFunc, |
| 34 paramCallbackFunc) { |
| 35 ResolvedNodeMirrorFinder finder = new ResolvedNodeMirrorFinder(node, |
| 36 callbackFunc, paramCallbackFunc); |
| 37 finder.unparse(node.node); |
| 38 return finder.result; |
| 39 } |
25 | 40 |
26 Map toMap() => { | 41 Map toMap() => { |
27 'name': getDocgenObject(mirror, owningLibrary).docName, | 42 'qualifiedName': owningLibrary.packagePrefix + |
| 43 getDocgenObject(mirror, owningLibrary).docName, |
28 'parameters': parameters | 44 'parameters': parameters |
29 }; | 45 }; |
30 } | 46 } |
31 | 47 |
32 List<String> _createParamaters(InstanceMirror originalMirror) { | 48 class ResolvedNodeMirrorFinder extends Unparser { |
33 var curMirror = originalMirror.type; | 49 final ResolvedNode resolvedNode; |
34 Map<Symbol, DeclarationMirror> allDeclarations = | 50 final Function annotationMirrorCallback; |
35 new Map.from(curMirror.declarations); | 51 final Function parameterValueCallback; |
36 // This method assumes that our users aren't creating deep inheritance | 52 int recursionLevel; |
37 // chains of custom annotation inheritance. If this is not the case, | 53 |
38 // re-write this section for performance. | 54 ResolvedNodeMirrorFinder(this.resolvedNode, this.annotationMirrorCallback, |
39 while (curMirror.superclass != null && | 55 this.parameterValueCallback) : recursionLevel = 0; |
40 curMirror.superclass.simpleName.toString() != 'Object') { | 56 |
41 allDeclarations.addAll(curMirror.superclass.declarations); | 57 visitSend(Send node) { |
42 curMirror = curMirror.superclass; | 58 if (recursionLevel == 0) { |
| 59 var m = resolvedNode.resolvedMirror(node.selector); |
| 60 annotationMirrorCallback(m, node); |
| 61 } else { |
| 62 Operator op = node.selector.asOperator(); |
| 63 String opString = op != null ? op.source : null; |
| 64 bool spacesNeeded = |
| 65 identical(opString, 'is') || identical(opString, 'as'); |
| 66 if (node.isPrefix) visit(node.selector); |
| 67 unparseSendReceiver(node, spacesNeeded: spacesNeeded); |
| 68 if (!node.isPrefix && !node.isIndex) visit(node.selector); |
| 69 if (spacesNeeded) sb.write(' '); |
| 70 // Also add a space for sequences like x + +1 and y - -y. |
| 71 // TODO(ahe): remove case for '+' when we drop the support for it. |
| 72 if (node.argumentsNode != null && (identical(opString, '-') |
| 73 || identical(opString, '+'))) { |
| 74 var beginToken = node.argumentsNode.getBeginToken(); |
| 75 if (beginToken != null && |
| 76 identical(beginToken.stringValue, opString)) { |
| 77 sb.write(' '); |
| 78 } |
| 79 } |
| 80 } |
| 81 recursionLevel++; |
| 82 visit(node.argumentsNode); |
| 83 recursionLevel--; |
43 } | 84 } |
44 | 85 |
45 // TODO(efortuna): Some originalMirrors, such as the | 86 unparseNodeListFrom(NodeList node, var from) { |
46 // Dart2JsMapConstantMirror and Dart2JsListConstantMirror don't have a | 87 if (from.isEmpty) return; |
47 // reflectee field, but we want the value of the parameter from them. | 88 |
48 // Gross workaround is to assemble the object manually. | 89 visit(from.head); |
49 // See issue 18346. | 90 |
50 return dart2js_util.variablesOf(allDeclarations) | 91 for (var link = from.tail; !link.isEmpty; link = link.tail) { |
51 .where((e) => e.isFinal && | 92 if (recursionLevel >= 2) { |
52 originalMirror.getField(e.simpleName).hasReflectee) | 93 parameterValueCallback(sb.toString()); |
53 .map((e) => originalMirror.getField(e.simpleName).reflectee) | 94 sb.clear(); |
54 .where((e) => e != null) | 95 } |
55 .toList(); | 96 visit(link.head); |
| 97 } |
| 98 if (recursionLevel >= 2) { |
| 99 parameterValueCallback(sb.toString()); |
| 100 sb.clear(); |
| 101 } |
| 102 } |
| 103 |
| 104 visitNodeList(NodeList node) { |
| 105 addToken(node.beginToken); |
| 106 if (recursionLevel == 1) sb.clear(); |
| 107 if (node.nodes != null) { |
| 108 recursionLevel++; |
| 109 unparseNodeListFrom(node, node.nodes); |
| 110 recursionLevel--; |
| 111 } |
| 112 if (node.endToken != null) add(node.endToken.value); |
| 113 } |
56 } | 114 } |
OLD | NEW |