From 4a893092ac954219b3f9df9f72d77239a7b608f9 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 25 Jul 2016 13:29:48 +0200 Subject: [PATCH] fix(lambda): Resolve Literal#constant if required. Fixes #755 --- .../support/compiler/jdt/JDTTreeBuilder.java | 13 +++ .../java/spoon/test/literal/LiteralTest.java | 8 ++ .../noclasspath/LiteralInForEach.java | 82 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 src/test/resources/noclasspath/LiteralInForEach.java diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 679a71d9a55..d91d2168659 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -61,6 +61,7 @@ import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; +import org.eclipse.jdt.internal.compiler.ast.Literal; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.LongLiteral; import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; @@ -1602,6 +1603,18 @@ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { if (localDeclaration.initialization != null) { context.arguments.push(v); + // resolve Literal#constant if null (by calling `resolveType`). Otherwise, + // `localDeclaration.initialization.traverse(this, scope);` throws a + // NullPointerException. Fixes #755. + if (localDeclaration.initialization instanceof Literal + // exclude StringLiterals if scope is null. In other words: + // StringLiteral -> scope!=null <=> !StringLiteral v scope!=null. + && (!(localDeclaration.initialization instanceof StringLiteral) || scope != null)) { + final Literal literal = (Literal) localDeclaration.initialization; + if (literal.constant == null) { + literal.resolveType(scope); + } + } localDeclaration.initialization.traverse(this, scope); context.arguments.pop(); } diff --git a/src/test/java/spoon/test/literal/LiteralTest.java b/src/test/java/spoon/test/literal/LiteralTest.java index bf9ebe1f125..249afabfa82 100644 --- a/src/test/java/spoon/test/literal/LiteralTest.java +++ b/src/test/java/spoon/test/literal/LiteralTest.java @@ -29,4 +29,12 @@ public boolean matches(CtLiteral element) { assertEquals(':', (char) charLiteral.getValue()); canBeBuilt("./target/literal", 8, true); } + + @Test + public void testLiteralInForEachWithNoClasspath() { + Launcher runLaunch = new Launcher(); + runLaunch.getEnvironment().setNoClasspath(true); + runLaunch.addInputResource("./src/test/resources/noclasspath/LiteralInForEach.java"); + runLaunch.buildModel(); + } } diff --git a/src/test/resources/noclasspath/LiteralInForEach.java b/src/test/resources/noclasspath/LiteralInForEach.java new file mode 100644 index 00000000000..9c3faf5ef0e --- /dev/null +++ b/src/test/resources/noclasspath/LiteralInForEach.java @@ -0,0 +1,82 @@ +package noclasspath; + +import java.util.HashMap; +import java.util.Map; + +public class LiteralInForEach { + private static Map map = new HashMap<>(); + + public static void main(final String[] args) { + booleanLiteral(); + byteLiteral(); + shortLiteral(); + charLiteral(); + intLiteral(); + floatLiteral(); + longLiteral(); + doubleLiteral(); + stringLiteral(); + } + + private static void booleanLiteral() { + map.forEach((key, value) -> { + boolean b0 = true; + boolean b1 = false; + }); + } + + private static void byteLiteral() { + map.forEach((key, value) -> { + byte b = 3; + }); + } + + private static void shortLiteral() { + map.forEach((key, value) -> { + short s = 5; + }); + } + + private static void charLiteral() { + map.forEach((key, value) -> { + char c0 = 'c'; + char c1 = 2; + }); + } + + private static void intLiteral() { + map.forEach((key, value) -> { + int i = 7; + }); + } + + private static void floatLiteral() { + map.forEach((key, value) -> { + float f0 = 9f; + float f1 = 9.0f; + }); + } + + private static void longLiteral() { + map.forEach((key, value) -> { + long l0 = 11L; + long l1 = 11l; + }); + } + + private static void doubleLiteral() { + map.forEach((key, value) -> { + double d0 = 13d; + double d1 = 13D; + double d2 = 13.0d; + double d3 = 13.0D; + double d4 = 13.0; + }); + } + + private static void stringLiteral() { + map.forEach((key, value) -> { + String s = "spoon"; + }); + } +}