diff --git a/src/main/java/spoon/support/visitor/java/JavaReflectionTreeBuilder.java b/src/main/java/spoon/support/visitor/java/JavaReflectionTreeBuilder.java index 1a1ce2a4cc8..0d9c32c4233 100644 --- a/src/main/java/spoon/support/visitor/java/JavaReflectionTreeBuilder.java +++ b/src/main/java/spoon/support/visitor/java/JavaReflectionTreeBuilder.java @@ -22,7 +22,10 @@ import java.util.Deque; import java.util.Iterator; import java.util.Set; -import spoon.reflect.code.CtLiteral; + +import spoon.reflect.code.BinaryOperatorKind; +import spoon.reflect.code.CtBinaryOperator; +import spoon.reflect.code.CtExpression; import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtAnnotationMethod; import spoon.reflect.declaration.CtAnnotationType; @@ -337,7 +340,7 @@ public void visitField(Field field) { if (modifiers.contains(ModifierKind.STATIC) && modifiers.contains(ModifierKind.PUBLIC) && (field.getType().isPrimitive() || String.class.isAssignableFrom(field.getType()))) { - CtLiteral defaultExpression = factory.createLiteral(field.get(null)); + CtExpression defaultExpression = buildExpressionForValue(field.get(null)); ctField.setDefaultExpression(defaultExpression); } } catch (IllegalAccessException | ExceptionInInitializerError | UnsatisfiedLinkError e) { @@ -351,6 +354,37 @@ public void visitField(Field field) { contexts.peek().addField(ctField); } + private CtExpression buildExpressionForValue(Object value) { + if (value instanceof Double) { + double d = (double) value; + if (Double.isNaN(d)) { + return buildDivision(0.0d, 0.0d); + } + if (Double.POSITIVE_INFINITY == d) { + return buildDivision(1.0d, 0.0d); + } + if (Double.NEGATIVE_INFINITY == d) { + return buildDivision(-1.0d, 0.0d); + } + } else if (value instanceof Float) { + float f = (float) value; + if (Float.isNaN(f)) { + return buildDivision(0.0f, 0.0f); + } + if (Float.POSITIVE_INFINITY == f) { + return buildDivision(1.0f, 0.0f); + } + if (Float.NEGATIVE_INFINITY == f) { + return buildDivision(-1.0f, 0.0f); + } + } + return factory.createLiteral(value); + } + + private CtBinaryOperator buildDivision(Object first, Object second) { + return factory.createBinaryOperator(factory.createLiteral(first), factory.createLiteral(second), BinaryOperatorKind.DIV); + } + @Override public void visitEnumValue(Field field) { final CtEnumValue ctEnumValue = factory.Core().createEnumValue(); diff --git a/src/test/java/spoon/support/visitor/java/JavaReflectionTreeBuilderTest.java b/src/test/java/spoon/support/visitor/java/JavaReflectionTreeBuilderTest.java index 56a6eda71aa..dc868a10d6b 100644 --- a/src/test/java/spoon/support/visitor/java/JavaReflectionTreeBuilderTest.java +++ b/src/test/java/spoon/support/visitor/java/JavaReflectionTreeBuilderTest.java @@ -64,6 +64,7 @@ import spoon.reflect.code.CtConditional; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtLambda; +import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.CtAnnotation; @@ -957,5 +958,32 @@ void testInnerClassesAreNotAddedToPackage(String collider) throws ClassNotFoundE assertNull(victim.getField("foo")); } + @Test + void test() throws ClassNotFoundException { + // contract: Infinity, -Infinity, NaN are not literals + ClassLoader loader = JavacFacade.compileFiles( + Map.of( + "SpecialValues.java", + "public class SpecialValues {\n" + + " public static final double d_inf = 1.0d / 0.0d;\n" + + " public static final double d_m_inf = -1.0d / 0.0d;\n" + + " public static final double d_nan = 0.0d / 0.0d;\n" + + " public static final float f_inf = 1.0f / 0.0f;\n" + + " public static final float f_m_inf = -1.0f / 0.0f;\n" + + " public static final float f_nan = 0.0f / 0.0f;\n" + + "}\n" + ), + List.of() + ); + + Factory factory = createFactory(); + // Load the class + CtType specialValues = factory.Type().get(loader.loadClass("SpecialValues")); + for (CtField field : specialValues.getFields()) { + assertNotNull(field.getDefaultExpression()); + assertFalse(field.getDefaultExpression() instanceof CtLiteral, "special value cannot be represented by literal"); + } + + } }