blob: 4557ea734d6612aa3d813c6a99e01be8d317dfc6 [file] [log] [blame]
// Copyright (c) 2018, 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.
// @dart = 2.7
import 'package:compiler/src/constants/values.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/types.dart';
String constantToText(DartTypes dartTypes, ConstantValue constant) {
StringBuffer sb = new StringBuffer();
new ConstantToTextVisitor(dartTypes).visit(constant, sb);
return sb.toString();
}
class DartTypeToTextVisitor extends DartTypeVisitor<void, StringBuffer> {
String visitList(Iterable<DartType> types, StringBuffer sb,
[String comma = '']) {
for (DartType type in types) {
sb.write(comma);
visit(type, sb);
comma = ',';
}
return comma;
}
@override
void visitLegacyType(LegacyType type, StringBuffer sb) {
bool wrapFunction = type.baseType is FunctionType;
if (wrapFunction) sb.write('(');
visit(type.baseType, sb);
if (wrapFunction) sb.write(')');
sb.write('*');
}
@override
void visitNullableType(NullableType type, StringBuffer sb) {
bool wrapFunction = type.baseType is FunctionType;
if (wrapFunction) sb.write('(');
visit(type.baseType, sb);
if (wrapFunction) sb.write(')');
sb.write('?');
}
@override
void visitNeverType(NeverType type, StringBuffer sb) {
sb.write('Never');
}
@override
void visitVoidType(VoidType type, StringBuffer sb) {
sb.write('void');
}
@override
void visitDynamicType(DynamicType type, StringBuffer sb) {
sb.write('dynamic');
}
@override
void visitErasedType(ErasedType type, StringBuffer sb) {
sb.write('erased');
}
@override
void visitAnyType(AnyType type, StringBuffer sb) {
sb.write('any');
}
@override
void visitTypeVariableType(TypeVariableType type, StringBuffer sb) {
sb.write(type.element.name);
}
@override
void visitFunctionTypeVariable(FunctionTypeVariable type, StringBuffer sb) {
sb.write(type.index);
}
@override
void visitFunctionType(FunctionType type, StringBuffer sb) {
sb.write('(');
String comma = visitList(type.parameterTypes, sb);
if (type.optionalParameterTypes.isNotEmpty) {
sb.write(comma);
sb.write('[');
visitList(type.optionalParameterTypes, sb);
sb.write(']');
comma = ',';
}
if (type.namedParameters.isNotEmpty) {
sb.write(comma);
sb.write('{');
comma = '';
for (int index = 0; index < type.namedParameters.length; index++) {
sb.write(comma);
visit(type.namedParameterTypes[index], sb);
sb.write(' ');
sb.write(type.namedParameters[index]);
comma = ',';
}
sb.write('}');
}
sb.write(')->');
visit(type.returnType, sb);
}
@override
void visitInterfaceType(InterfaceType type, StringBuffer sb) {
sb.write(type.element.name);
if (type.typeArguments.isNotEmpty) {
sb.write('<');
visitList(type.typeArguments, sb);
sb.write('>');
}
}
@override
void visitFutureOrType(FutureOrType type, StringBuffer sb) {
sb.write('FutureOr<');
visit(type.typeArgument, sb);
sb.write('>');
}
}
class ConstantToTextVisitor
implements ConstantValueVisitor<void, StringBuffer> {
final DartTypes _dartTypes;
final DartTypeToTextVisitor typeToText = new DartTypeToTextVisitor();
ConstantToTextVisitor(this._dartTypes);
void visit(ConstantValue constant, StringBuffer sb) =>
constant.accept(this, sb);
void visitConstants(Iterable<ConstantValue> constants, StringBuffer sb) {
String comma = '';
for (ConstantValue constant in constants) {
sb.write(comma);
visit(constant, sb);
comma = ',';
}
}
@override
void visitFunction(FunctionConstantValue constant, StringBuffer sb) {
sb.write('Function(${constant.element.name})');
}
@override
void visitNull(NullConstantValue constant, StringBuffer sb) {
sb.write('Null()');
}
@override
void visitInt(IntConstantValue constant, StringBuffer sb) {
sb.write('Int(${constant.intValue})');
}
@override
void visitDouble(DoubleConstantValue constant, StringBuffer sb) {
sb.write('Double(${constant.doubleValue})');
}
@override
void visitBool(BoolConstantValue constant, StringBuffer sb) {
sb.write('Bool(${constant.boolValue})');
}
@override
void visitString(StringConstantValue constant, StringBuffer sb) {
sb.write('String(${constant.stringValue})');
}
@override
void visitList(ListConstantValue constant, StringBuffer sb) {
sb.write('List<');
typeToText.visitList(constant.type.typeArguments, sb);
sb.write('>(');
visitConstants(constant.entries, sb);
sb.write(')');
}
@override
void visitSet(SetConstantValue constant, StringBuffer sb) {
sb.write('Set<');
typeToText.visitList(constant.type.typeArguments, sb);
sb.write('>(');
visitConstants(constant.values, sb);
sb.write(')');
}
@override
void visitMap(MapConstantValue constant, StringBuffer sb) {
sb.write('Map<');
typeToText.visitList(constant.type.typeArguments, sb);
sb.write('>(');
for (int index = 0; index < constant.keys.length; index++) {
if (index > 0) {
sb.write(',');
}
visit(constant.keys[index], sb);
sb.write(':');
visit(constant.values[index], sb);
}
sb.write(')');
}
@override
void visitConstructed(ConstructedConstantValue constant, StringBuffer sb) {
sb.write('Instance(');
typeToText.visit(constant.type, sb);
if (constant.fields.isNotEmpty) {
sb.write(',{');
String comma = '';
constant.fields.forEach((FieldEntity field, ConstantValue value) {
sb.write(comma);
sb.write(field.name);
sb.write(':');
visit(value, sb);
comma = ',';
});
}
sb.write(')');
}
@override
void visitType(TypeConstantValue constant, StringBuffer sb) {
sb.write('TypeLiteral(');
typeToText.visit(constant.representedType, sb);
sb.write(')');
}
void _unsupported(ConstantValue constant) => throw UnsupportedError(
'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
@override
void visitInterceptor(InterceptorConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitDummyInterceptor(
DummyInterceptorConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitLateSentinel(LateSentinelConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitUnreachable(UnreachableConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitJsName(JsNameConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitDeferredGlobal(
DeferredGlobalConstantValue constant, StringBuffer sb) =>
_unsupported(constant);
@override
void visitNonConstant(NonConstantValue constant, StringBuffer sb) {
sb.write('NonConstant()');
}
@override
void visitInstantiation(
InstantiationConstantValue constant, StringBuffer sb) {
sb.write('Instantiation(');
sb.write(constant.function.element.name);
sb.write('<');
typeToText.visitList(constant.typeArguments, sb);
sb.write('>)');
}
}