| // 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('>)'); |
| } |
| } |