blob: 93a5e3065abebb69c02d192b6212694f714dce09 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:meta/meta.dart';
/// Prints AST as a tree, with properties and children.
class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
final String _selfUriStr;
final StringSink _sink;
String _indent = '';
ResolvedAstPrinter({
@required String selfUriStr,
@required StringSink sink,
@required String indent,
}) : _selfUriStr = selfUriStr,
_sink = sink,
_indent = indent;
@override
void visitAnnotation(Annotation node) {
_writeln('Annotation');
_withIndent(() {
_writeNode('arguments', node.arguments);
_writeNode('constructorName', node.constructorName);
_writeElement('element', node.element);
_writeNode('name', node.name);
});
}
@override
void visitArgumentList(ArgumentList node) {
_writeln('ArgumentList');
_withIndent(() {
_writeNodeList('arguments', node.arguments);
});
}
@override
void visitCompilationUnit(CompilationUnit node) {
super.visitCompilationUnit(node);
}
@override
void visitConstructorName(ConstructorName node) {
_writeln('ConstructorName');
_withIndent(() {
_writeNode('name', node.name);
_writeNode('type', node.type);
});
}
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
_writeln('InstanceCreationExpression');
_withIndent(() {
_writeNode('argumentList', node.argumentList);
_writeNode('constructorName', node.constructorName);
_writeElement('staticElement', node.staticElement);
_writeType('staticType', node.staticType);
});
}
@override
void visitIntegerLiteral(IntegerLiteral node) {
_writeln('IntegerLiteral');
_withIndent(() {
_writelnWithIndent('literal: ${node.literal}');
_writeType('staticType', node.staticType);
});
}
@override
void visitListLiteral(ListLiteral node) {
_writeln('ListLiteral');
_withIndent(() {
_writeNodeList('elements', node.elements);
_writeType('staticType', node.staticType);
_writeNode('typeArguments', node.typeArguments);
});
}
@override
void visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node,
) {
_writeln('RedirectingConstructorInvocation');
_withIndent(() {
_writeNode('argumentList', node.argumentList);
_writeNode('constructorName', node.constructorName);
_writeElement('staticElement', node.staticElement);
});
}
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
_writeln('SimpleIdentifier');
_withIndent(() {
_writeAuxiliaryElements('auxiliaryElements', node.auxiliaryElements);
_writeElement('staticElement', node.staticElement);
_writeType('staticType', node.staticType);
_writelnWithIndent('token: ${node.token}');
});
}
@override
void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
_writeln('SuperConstructorInvocation');
_withIndent(() {
_writeNode('argumentList', node.argumentList);
_writeNode('constructorName', node.constructorName);
_writeElement('staticElement', node.staticElement);
});
}
@override
void visitTypeName(TypeName node) {
_writeln('TypeName');
_withIndent(() {
_writeNode('name', node.name);
_writeType('type', node.type);
_writeNode('typeArguments', node.typeArguments);
});
}
String _referenceToString(Reference reference) {
if (reference.parent.name == '@unit') {
var libraryUriStr = reference.parent.parent.name;
if (libraryUriStr == _selfUriStr) {
return 'self';
}
return libraryUriStr;
}
var name = reference.name;
if (name.startsWith('@')) {
return _referenceToString(reference.parent);
}
if (name.isEmpty) {
name = '•';
}
return _referenceToString(reference.parent) + '::$name';
}
void _withIndent(void Function() f) {
var indent = _indent;
_indent = '$_indent ';
f();
_indent = indent;
}
void _writeAuxiliaryElements(String name, AuxiliaryElements elements) {
if (elements != null) {
throw UnimplementedError();
}
}
void _writeElement(String name, Element element) {
_sink.write(_indent);
_sink.write('$name: ');
if (element == null) {
_sink.writeln('<null>');
} else if (element is Member) {
_sink.writeln(_nameOfMemberClass(element));
_withIndent(() {
_writeElement('base', element.baseElement);
_writelnWithIndent('substitution: ${element.substitution.map}');
});
} else {
var reference = (element as ElementImpl).reference;
var referenceStr = _referenceToString(reference);
_sink.writeln(referenceStr);
}
}
void _writeln(String line) {
_sink.writeln(line);
}
void _writelnWithIndent(String line) {
_sink.write(_indent);
_sink.writeln(line);
}
void _writeNode(String name, AstNode node) {
if (node != null) {
_sink.write(_indent);
_sink.write('$name: ');
node.accept(this);
}
}
void _writeNodeList(String name, NodeList nodeList) {
if (nodeList.isNotEmpty) {
_writelnWithIndent(name);
_withIndent(() {
for (var node in nodeList) {
_sink.write(_indent);
node.accept(this);
}
});
}
}
void _writeType(String name, DartType type) {
_writelnWithIndent('$name: $type');
}
static String _nameOfMemberClass(Member member) {
return '${member.runtimeType}';
}
}