diff options
| author | Gayan Perera | 2021-02-23 17:43:03 +0000 |
|---|---|---|
| committer | Gayan Perera | 2021-06-18 10:14:46 +0000 |
| commit | 63e0f757b2acc1528310b44b3463bd2bd4858310 (patch) | |
| tree | c6002cf80ba99f5334372a2cbf6a6d8353cc6c1d | |
| parent | 680081fceaccc04731bfd58151734b054356a6d1 (diff) | |
| download | eclipse.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>
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 Binary files differindex 804cba6db9..d42def46ad 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip +++ b/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip 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); } |
