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 import 'dart:collection'; | |
| 6 | |
| 7 import 'package:analysis_server/src/status/tree_writer.dart'; | |
| 8 import 'package:analyzer/dart/ast/ast.dart'; | |
| 9 import 'package:analyzer/dart/ast/visitor.dart'; | |
| 10 import 'package:analyzer/src/dart/ast/ast.dart'; | |
| 11 | |
| 12 /** | |
| 13 * A visitor that will produce an HTML representation of an AST structure. | |
| 14 */ | |
| 15 class AstWriter extends UnifyingAstVisitor with TreeWriter { | |
|
Brian Wilkerson
2017/05/31 14:54:43
It has frequently been very useful to see the AST
devoncarew
2017/06/01 16:59:11
Done.
| |
| 16 /** | |
| 17 * Initialize a newly created element writer to write the HTML representation | |
| 18 * of visited nodes on the given [buffer]. | |
| 19 */ | |
| 20 AstWriter(StringBuffer buffer) { | |
| 21 this.buffer = buffer; | |
| 22 } | |
| 23 | |
| 24 @override | |
| 25 void visitNode(AstNode node) { | |
| 26 _writeNode(node); | |
| 27 writeProperties(_computeProperties(node)); | |
| 28 indentLevel++; | |
| 29 try { | |
| 30 node.visitChildren(this); | |
| 31 } finally { | |
| 32 indentLevel--; | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 /** | |
| 37 * Write a representation of the properties of the given [node] to the buffer. | |
| 38 */ | |
| 39 Map<String, Object> _computeProperties(AstNode node) { | |
| 40 Map<String, Object> properties = new HashMap<String, Object>(); | |
| 41 | |
| 42 properties['name'] = _getName(node); | |
| 43 if (node is ArgumentListImpl) { | |
| 44 properties['static parameter types'] = node.correspondingStaticParameters; | |
| 45 properties['propagated parameter types'] = | |
| 46 node.correspondingPropagatedParameters; | |
| 47 } else if (node is Annotation) { | |
| 48 properties['element'] = node.element; | |
| 49 properties['element annotation'] = node.elementAnnotation; | |
| 50 } else if (node is BinaryExpression) { | |
| 51 properties['static element'] = node.staticElement; | |
| 52 properties['static type'] = node.staticType; | |
| 53 properties['propagated element'] = node.propagatedElement; | |
| 54 properties['propagated type'] = node.propagatedType; | |
| 55 } else if (node is ClassDeclaration) { | |
| 56 properties['element'] = node.element; | |
| 57 properties['abstract keyword'] = node.abstractKeyword; | |
| 58 } else if (node is ClassTypeAlias) { | |
| 59 properties['element'] = node.element; | |
| 60 properties['abstract keyword'] = node.abstractKeyword; | |
| 61 } else if (node is CompilationUnit) { | |
| 62 properties['element'] = node.element; | |
| 63 } else if (node is Configuration) { | |
| 64 properties['uriSource'] = node.uriSource; | |
| 65 } else if (node is ConstructorName) { | |
| 66 properties['static element'] = node.staticElement; | |
| 67 } else if (node is DeclaredIdentifier) { | |
| 68 properties['element'] = node.element; | |
| 69 properties['keyword'] = node.keyword; | |
| 70 } else if (node is ExportDirective) { | |
| 71 properties['element'] = node.element; | |
| 72 properties['selectedSource'] = node.selectedSource; | |
| 73 properties['uriSource'] = node.uriSource; | |
| 74 } else if (node is FieldDeclaration) { | |
| 75 properties['static keyword'] = node.staticKeyword; | |
| 76 } else if (node is FormalParameter) { | |
| 77 properties['element'] = node.element; | |
| 78 properties['kind'] = node.kind; | |
| 79 } else if (node is FunctionDeclaration) { | |
| 80 properties['element'] = node.element; | |
| 81 properties['external keyword'] = node.externalKeyword; | |
| 82 properties['property keyword'] = node.propertyKeyword; | |
| 83 } else if (node is FunctionExpressionInvocation) { | |
| 84 properties['static element'] = node.staticElement; | |
| 85 properties['static invoke type'] = node.staticInvokeType; | |
| 86 properties['static type'] = node.staticType; | |
| 87 properties['propagated element'] = node.propagatedElement; | |
| 88 properties['propagated invoke type'] = node.propagatedInvokeType; | |
| 89 properties['propagated type'] = node.propagatedType; | |
| 90 } else if (node is ImportDirective) { | |
| 91 properties['element'] = node.element; | |
| 92 properties['selectedSource'] = node.selectedSource; | |
| 93 properties['uriSource'] = node.uriSource; | |
| 94 } else if (node is IndexExpression) { | |
| 95 properties['static element'] = node.staticElement; | |
| 96 properties['static type'] = node.staticType; | |
| 97 properties['propagated element'] = node.propagatedElement; | |
| 98 properties['propagated type'] = node.propagatedType; | |
| 99 } else if (node is InstanceCreationExpression) { | |
| 100 properties['static element'] = node.staticElement; | |
| 101 properties['static type'] = node.staticType; | |
| 102 properties['propagated type'] = node.propagatedType; | |
| 103 } else if (node is LibraryDirective) { | |
| 104 properties['element'] = node.element; | |
| 105 } else if (node is MethodDeclaration) { | |
| 106 properties['element'] = node.element; | |
| 107 properties['external keyword'] = node.externalKeyword; | |
| 108 properties['modifier keyword'] = node.modifierKeyword; | |
| 109 properties['operator keyword'] = node.operatorKeyword; | |
| 110 properties['property keyword'] = node.propertyKeyword; | |
| 111 } else if (node is MethodInvocation) { | |
| 112 properties['static invoke type'] = node.staticInvokeType; | |
| 113 properties['static type'] = node.staticType; | |
| 114 properties['propagated invoke type'] = node.propagatedInvokeType; | |
| 115 properties['propagated type'] = node.propagatedType; | |
| 116 } else if (node is PartDirective) { | |
| 117 properties['element'] = node.element; | |
| 118 properties['uriSource'] = node.uriSource; | |
| 119 } else if (node is PartOfDirective) { | |
| 120 properties['element'] = node.element; | |
| 121 } else if (node is PostfixExpression) { | |
| 122 properties['static element'] = node.staticElement; | |
| 123 properties['static type'] = node.staticType; | |
| 124 properties['propagated element'] = node.propagatedElement; | |
| 125 properties['propagated type'] = node.propagatedType; | |
| 126 } else if (node is PrefixExpression) { | |
| 127 properties['static element'] = node.staticElement; | |
| 128 properties['static type'] = node.staticType; | |
| 129 properties['propagated element'] = node.propagatedElement; | |
| 130 properties['propagated type'] = node.propagatedType; | |
| 131 } else if (node is RedirectingConstructorInvocation) { | |
| 132 properties['static element'] = node.staticElement; | |
| 133 } else if (node is SimpleIdentifier) { | |
| 134 properties['static element'] = node.staticElement; | |
| 135 properties['static type'] = node.staticType; | |
| 136 properties['propagated element'] = node.propagatedElement; | |
| 137 properties['propagated type'] = node.propagatedType; | |
| 138 } else if (node is SimpleStringLiteral) { | |
| 139 properties['value'] = node.value; | |
| 140 } else if (node is SuperConstructorInvocation) { | |
| 141 properties['static element'] = node.staticElement; | |
| 142 } else if (node is TypeAnnotation) { | |
| 143 properties['type'] = node.type; | |
| 144 } else if (node is VariableDeclarationList) { | |
| 145 properties['keyword'] = node.keyword; | |
| 146 } else if (node is Declaration) { | |
| 147 properties['element'] = node.element; | |
| 148 } else if (node is Expression) { | |
| 149 properties['static type'] = node.staticType; | |
| 150 properties['propagated type'] = node.propagatedType; | |
| 151 } else if (node is FunctionBody) { | |
| 152 properties['isAsynchronous'] = node.isAsynchronous; | |
| 153 properties['isGenerator'] = node.isGenerator; | |
| 154 } else if (node is Identifier) { | |
| 155 properties['static element'] = node.staticElement; | |
| 156 properties['static type'] = node.staticType; | |
| 157 properties['propagated element'] = node.propagatedElement; | |
| 158 properties['propagated type'] = node.propagatedType; | |
| 159 } | |
| 160 | |
| 161 return properties; | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * Return the name of the given [node], or `null` if the given node is not a | |
| 166 * declaration. | |
| 167 */ | |
| 168 String _getName(AstNode node) { | |
| 169 if (node is ClassTypeAlias) { | |
| 170 return node.name.name; | |
| 171 } else if (node is ClassDeclaration) { | |
| 172 return node.name.name; | |
| 173 } else if (node is ConstructorDeclaration) { | |
| 174 if (node.name == null) { | |
| 175 return node.returnType.name; | |
| 176 } else { | |
| 177 return node.returnType.name + '.' + node.name.name; | |
| 178 } | |
| 179 } else if (node is ConstructorName) { | |
| 180 return node.toSource(); | |
| 181 } else if (node is FieldDeclaration) { | |
| 182 return _getNames(node.fields); | |
| 183 } else if (node is FunctionDeclaration) { | |
| 184 SimpleIdentifier nameNode = node.name; | |
| 185 if (nameNode != null) { | |
| 186 return nameNode.name; | |
| 187 } | |
| 188 } else if (node is FunctionTypeAlias) { | |
| 189 return node.name.name; | |
| 190 } else if (node is Identifier) { | |
| 191 return node.name; | |
| 192 } else if (node is MethodDeclaration) { | |
| 193 return node.name.name; | |
| 194 } else if (node is TopLevelVariableDeclaration) { | |
| 195 return _getNames(node.variables); | |
| 196 } else if (node is TypeAnnotation) { | |
| 197 return node.toSource(); | |
| 198 } else if (node is TypeParameter) { | |
| 199 return node.name.name; | |
| 200 } else if (node is VariableDeclaration) { | |
| 201 return node.name.name; | |
| 202 } | |
| 203 return null; | |
| 204 } | |
| 205 | |
| 206 /** | |
| 207 * Return a string containing a comma-separated list of the names of all of | |
| 208 * the variables in the given list of [variables]. | |
| 209 */ | |
| 210 String _getNames(VariableDeclarationList variables) { | |
| 211 StringBuffer buffer = new StringBuffer(); | |
| 212 bool first = true; | |
| 213 for (VariableDeclaration variable in variables.variables) { | |
| 214 if (first) { | |
| 215 first = false; | |
| 216 } else { | |
| 217 buffer.write(', '); | |
| 218 } | |
| 219 buffer.write(variable.name.name); | |
| 220 } | |
| 221 return buffer.toString(); | |
| 222 } | |
| 223 | |
| 224 /** | |
| 225 * Write a representation of the given [node] to the buffer. | |
| 226 */ | |
| 227 void _writeNode(AstNode node) { | |
| 228 indent(); | |
| 229 buffer.write(node.runtimeType); | |
| 230 buffer.write(' <span style="color:gray">['); | |
| 231 buffer.write(node.offset); | |
| 232 buffer.write('..'); | |
| 233 buffer.write(node.offset + node.length - 1); | |
| 234 buffer.write(']'); | |
| 235 if (node.isSynthetic) { | |
| 236 buffer.write(' (synthetic)'); | |
| 237 } | |
| 238 buffer.write('</span>'); | |
| 239 buffer.write('<br>'); | |
| 240 } | |
| 241 } | |
| OLD | NEW |