TextBuffer (int indent, BytecodeMappingTracer tracer) { boolean literal = DecompilerContext.getOption(IFernflowerPreferences.LITERALS_AS_IS); boolean ascii = DecompilerContext.getOption(IFernflowerPreferences.ASCII_STRING_CHARACTERS); tracer.addMapping(bytecode); if (constType.getType() != CodeConstants.TYPE_NULL && value == null) { return new TextBuffer(ExprProcessor.getCastTypeName(constType, Collections.emptyList())); } return switch (constType.getType()) { case CodeConstants.TYPE_BOOLEAN -> new TextBuffer(Boolean.toString((Integer)value != 0)); case CodeConstants.TYPE_CHAR -> { Integer val = (Integer)value; String ret = CHAR_ESCAPES.get(val); if (ret == null) { char c = (char)val.intValue(); if (isPrintableAscii(c) || !ascii && TextUtil.isPrintableUnicode(c)) { ret = String.valueOf(c); } else { ret = TextUtil.charToUnicodeLiteral(c); } } yield new TextBuffer(ret).enclose("'", "'"); } case CodeConstants.TYPE_BYTE -> new TextBuffer(value.toString()); case CodeConstants.TYPE_BYTECHAR, CodeConstants.TYPE_SHORT -> { int shortVal = (Integer)value; if (!literal) { if (shortVal == Short.MAX_VALUE && !inConstantVariable(SHORT_SIG, MAX_VAL)) { yield new FieldExprent(MAX_VAL, SHORT_SIG, true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (shortVal == Short.MIN_VALUE && !inConstantVariable(SHORT_SIG, MIN_VAL)) { yield new FieldExprent(MIN_VAL, SHORT_SIG, true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer); } } yield new TextBuffer(value.toString()); } case CodeConstants.TYPE_SHORTCHAR, CodeConstants.TYPE_INT -> { int intVal = (Integer)value; if (!literal) { if (intVal == Integer.MAX_VALUE && !inConstantVariable(INT_SIG, MAX_VAL)) { yield new FieldExprent(MAX_VAL, INT_SIG, true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (intVal == Integer.MIN_VALUE && !inConstantVariable(INT_SIG, MIN_VAL)) { yield new FieldExprent(MIN_VAL, INT_SIG, true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer); } } yield new TextBuffer(value.toString()); } case CodeConstants.TYPE_LONG -> { long longVal = (Long)value; if (!literal) { if (longVal == Long.MAX_VALUE && !inConstantVariable(LONG_SIG, MAX_VAL)) { yield new FieldExprent(MAX_VAL, LONG_SIG, true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (longVal == Long.MIN_VALUE && !inConstantVariable(LONG_SIG, MIN_VAL)) { yield new FieldExprent(MIN_VAL, LONG_SIG, true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer); } } yield new TextBuffer(value.toString()).append('L'); } case CodeConstants.TYPE_FLOAT -> { float floatVal = (Float)value; if (!literal) { if (Float.isNaN(floatVal) && !inConstantVariable(FLOAT_SIG, NAN)) { yield new FieldExprent(NAN, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (floatVal == Float.POSITIVE_INFINITY && !inConstantVariable(FLOAT_SIG, POS_INF)) { yield new FieldExprent(POS_INF, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (floatVal == Float.NEGATIVE_INFINITY && !inConstantVariable(FLOAT_SIG, NEG_INF)) { yield new FieldExprent(NEG_INF, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (floatVal == Float.MAX_VALUE && !inConstantVariable(FLOAT_SIG, MAX_VAL)) { yield new FieldExprent(MAX_VAL, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (floatVal == Float.MIN_VALUE && !inConstantVariable(FLOAT_SIG, MIN_VAL)) { yield new FieldExprent(MIN_VAL, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (floatVal == Float.MIN_NORMAL && !inConstantVariable(FLOAT_SIG, MIN_NORM)) { yield new FieldExprent(MIN_NORM, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer); } } else if (Float.isNaN(floatVal)) { yield new TextBuffer("0.0F / 0.0F"); } else if (floatVal == Float.POSITIVE_INFINITY) { yield new TextBuffer("1.0F / 0.0F"); } else if (floatVal == Float.NEGATIVE_INFINITY) { yield new TextBuffer("-1.0F / 0.0F"); } yield new TextBuffer(value.toString()).append('F'); } case CodeConstants.TYPE_DOUBLE -> { double doubleVal = (Double)value; if (!literal) { if (Double.isNaN(doubleVal) && !inConstantVariable(DOUBLE_SIG, NAN)) { yield new FieldExprent(NAN, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Double.POSITIVE_INFINITY && !inConstantVariable(DOUBLE_SIG, POS_INF)) { yield new FieldExprent(POS_INF, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Double.NEGATIVE_INFINITY && !inConstantVariable(DOUBLE_SIG, NEG_INF)) { yield new FieldExprent(NEG_INF, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Double.MAX_VALUE && !inConstantVariable(DOUBLE_SIG, MAX_VAL)) { yield new FieldExprent(MAX_VAL, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Double.MIN_VALUE && !inConstantVariable(DOUBLE_SIG, MIN_VAL)) { yield new FieldExprent(MIN_VAL, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Double.MIN_NORMAL && !inConstantVariable(DOUBLE_SIG, MIN_NORM)) { yield new FieldExprent(MIN_NORM, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Math.E && !inConstantVariable(MATH_SIG, E)) { yield new FieldExprent(E, MATH_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } else if (doubleVal == Math.PI && !inConstantVariable(MATH_SIG, PI)) { yield new FieldExprent(PI, MATH_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer); } } else if (Double.isNaN(doubleVal)) { yield new TextBuffer("0.0 / 0.0"); } else if (doubleVal == Double.POSITIVE_INFINITY) { yield new TextBuffer("1.0 / 0.0"); } else if (doubleVal == Double.NEGATIVE_INFINITY) { yield new TextBuffer("-1.0 / 0.0"); } yield new TextBuffer(value.toString()); } case CodeConstants.TYPE_NULL -> new TextBuffer("null"); case CodeConstants.TYPE_OBJECT -> { if (constType.equals(VarType.VARTYPE_STRING)) { yield new TextBuffer(convertStringToJava(value.toString(), ascii)).enclose("\"", "\""); } else if (constType.equals(VarType.VARTYPE_CLASS)) { String stringVal = value.toString(); VarType type = new VarType(stringVal, !stringVal.startsWith("[")); yield new TextBuffer(ExprProcessor.getCastTypeName(type, Collections.emptyList())).append(".class"); } throw new RuntimeException("invalid constant type: " + constType); } default -> throw new RuntimeException("invalid constant type: " + constType); }; }