Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGayan Perera2021-02-23 17:43:03 +0000
committerGayan Perera2021-06-18 10:14:46 +0000
commit63e0f757b2acc1528310b44b3463bd2bd4858310 (patch)
treec6002cf80ba99f5334372a2cbf6a6d8353cc6c1d
parent680081fceaccc04731bfd58151734b054356a6d1 (diff)
downloadeclipse.jdt.core-63e0f757b2acc1528310b44b3463bd2bd4858310.tar.gz
eclipse.jdt.core-63e0f757b2acc1528310b44b3463bd2bd4858310.tar.xz
eclipse.jdt.core-63e0f757b2acc1528310b44b3463bd2bd4858310.zip
Bug 571310 - Fix method invocations on outer-scope variables
When generating code for lambda expression which are generated as outer scope variables its was not generated with outer scope access. With the fix the CodeSnippetSingleNameReference will generate outer scope access for both local and synthetic variables used inside lambda statements. Change-Id: I9b4976d117ee868b95dde052a02e36f872e3a5ac Signed-off-by: Gayan Perera <gayanper@gmail.com> Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/176748 Reviewed-by: Manoj Palat <manpalat@in.ibm.com> Tested-by: JDT Bot <jdt-bot@eclipse.org>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zipbin13232 -> 13598 bytes
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java79
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/target/CodeSnippetRunner.java24
-rw-r--r--org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java35
4 files changed, 106 insertions, 32 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip b/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
index 804cba6db9..d42def46ad 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
+++ b/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
index f9e2c48551..5e4a7c5a26 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
@@ -967,4 +967,83 @@ public void testBug464656() {
"return s.findFirst();"}),
"Optional[a]".toCharArray());
}
+
+public void testBug571310_ThisReciever() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_8) {
+ return;
+ }
+ evaluateWithExpectedDisplayString(buildCharArray(new String[] {
+ "class Outer {",
+ " public int outerFoo() {",
+ " return 10;",
+ " }",
+ " public int boo() {",
+ " java.util.function.Function<Integer,Integer> f = i -> this.outerFoo() + i;",
+ " return f.apply(5);",
+ " }",
+ "};",
+ "(new Outer()).boo();"}),
+ "15".toCharArray());
+}
+
+public void testBug571310_LocalVarReciever() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_8) {
+ return;
+ }
+ evaluateWithExpectedDisplayString(buildCharArray(new String[] {
+ "class Outer {",
+ " public int outerFoo(){",
+ " return 10;",
+ " }",
+ " public int boo() {",
+ " Outer thisVar = this;",
+ " java.util.function.Function<Integer,Integer> f = (i) -> thisVar.outerFoo() + i;",
+ " return f.apply(5);",
+ " }",
+ "};",
+ "new Outer().boo();"}),
+ "15".toCharArray());
+}
+
+public void testBug571310_QualifiedReciever() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_8) {
+ return;
+ }
+ evaluateWithExpectedDisplayString(buildCharArray(new String[] {
+ "class Outer {",
+ " public int outerFoo(){",
+ " return 10;",
+ " }",
+ " public java.util.function.Supplier<Integer> boo() {",
+ " return new java.util.function.Supplier<Integer>() {",
+ " public Integer get() {",
+ " java.util.function.Function<Integer,Integer> f = (i) -> Outer.this.outerFoo() + i;",
+ " return f.apply(5);",
+ " }",
+ " };",
+ " }",
+ "};",
+ "new Outer().boo().get();"}),
+ "15".toCharArray());
+}
+public void testBug571310_SynthVarReciever() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_8) {
+ return;
+ }
+ evaluateWithExpectedDisplayString(buildCharArray(new String[] {
+ "class Outer {",
+ " Integer intField = 10;",
+ " public java.util.function.Supplier<Integer> boo() {",
+ " intField ++;",
+ " return new java.util.function.Supplier<Integer>() {",
+ " public Integer get() {",
+ " java.util.function.Function<Integer,Integer> f = (i) -> intField.intValue() + i;",
+ " return f.apply(5);",
+ " }",
+ " };",
+ " }",
+ "};",
+ "new Outer().boo().get();"}),
+ "16".toCharArray());
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/target/CodeSnippetRunner.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/target/CodeSnippetRunner.java
index 0f292878e1..9098ddbe60 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/target/CodeSnippetRunner.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/target/CodeSnippetRunner.java
@@ -126,6 +126,30 @@ private String className(byte[] classDefinition) {
case 12 : // NameAndTypeTag
constantPoolOffsets[i] = readOffset;
readOffset += 5; // ConstantNameAndType.fixedSize
+ break;
+ case 15 : // MethodHandleTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 4; // MethodHandle.fixedSize
+ break;
+ case 16 : // MethodTypeTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 3; // MethodType.fixedSize
+ break;
+ case 17 : // DynamicTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 5; // Dynamic.fixedSize
+ break;
+ case 18 : // InvokeDynamicTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 5; // InvokeDynamic.fixedSize
+ break;
+ case 19 : // ModuleTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 3; // Module.fixedSize
+ break;
+ case 20 : // PackageTag
+ constantPoolOffsets[i] = readOffset;
+ readOffset += 3; // Package.fixedSize
}
}
// Skip access flags
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
index 6872a5bfb4..64ea6e4b57 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
@@ -24,7 +24,6 @@ import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
-import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
@@ -58,34 +57,6 @@ public CodeSnippetSingleNameReference(char[] source, long pos, EvaluationContext
super(source, pos);
this.evaluationContext = evaluationContext;
}
-@Override
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
-
- switch (this.bits & RestrictiveFlagMASK) {
- case Binding.FIELD : // reading a field
- // check if reading a final blank field
- FieldBinding fieldBinding;
- if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal()
- && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
- FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
- if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
- currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
- }
- }
- break;
- case Binding.LOCAL : // reading a local variable
- LocalVariableBinding localBinding;
- if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
- currentScope.problemReporter().uninitializedLocalVariable(localBinding, this, currentScope);
- }
- if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
- localBinding.useFlag = LocalVariableBinding.USED;
- } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
- localBinding.useFlag = LocalVariableBinding.FAKE_USED;
- }
- }
- return flowInfo;
-}
/**
* Check and/or redirect the field access to the delegate receiver if any
*/
@@ -261,9 +232,9 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
// managing private access
if (!codegenField.isStatic()) {
if ((this.bits & DepthMASK) != 0) {
- // internal error, per construction we should have found it
- // not yet supported
- currentScope.problemReporter().needImplementation(this);
+ ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
+ Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+ codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
} else {
generateReceiver(codeStream);
}

Back to the top