diff options
| author | Gayan Perera | 2022-01-06 19:05:44 +0000 |
|---|---|---|
| committer | Sarika Sinha | 2022-01-10 19:02:21 +0000 |
| commit | 530846db516280ca88dbc80e098107ce37501477 (patch) | |
| tree | 9a81474d605c1b9d9d44574ed2a3498ecc5541a1 | |
| parent | 0a20bdb9a62333eb8cde7b16e801fbb5246da79d (diff) | |
| download | eclipse.jdt.debug-530846db516280ca88dbc80e098107ce37501477.tar.gz eclipse.jdt.debug-530846db516280ca88dbc80e098107ce37501477.tar.xz eclipse.jdt.debug-530846db516280ca88dbc80e098107ce37501477.zip | |
Bug 575551 - Fix evaluations at deeply nested intermediate lambda framesI20220112-0210I20220111-2130I20220111-1910I20220111-1800I20220111-0450I20220110-1800
The fix will add support to extract variables starting from correct
frame in the current call stack for lambda frames. Also this fix generic
variables with upper bound type variables.
Change-Id: I86a181df34c3a1045c4a30ec07b9dbcd9ab5c073
Signed-off-by: Gayan Perera <gayanper@gmail.com>
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.debug/+/189357
Tested-by: JDT Bot <jdt-bot@eclipse.org>
Reviewed-by: Sarika Sinha <sarika.sinha@in.ibm.com>
5 files changed, 87 insertions, 8 deletions
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug575551.java b/org.eclipse.jdt.debug.tests/java8/Bug575551.java new file mode 100644 index 000000000..930b981d6 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/java8/Bug575551.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2022 Gayan Perera and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Gayan Perera - initial API and implementation + *******************************************************************************/ +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Bug575551 { + public void hoverOverLocal(String[] names) throws InterruptedException, ExecutionException { + CompletableFuture<List<String>> future = CompletableFuture.supplyAsync(() -> { + return Stream.of(names).filter(s -> { + try { + return CompletableFuture.supplyAsync(() -> { + return containsDigit(s.codePointAt(0), names.length); + }).get(); + } catch (Exception e) { + return false; + } + }).collect(Collectors.toList()); + }); + future.get(); + } + + private boolean containsDigit(int c, int length) { + return Bug575551.Character.isDigit(c) && c == length; + } + + public static void main(String[] args) throws InterruptedException, ExecutionException { + new Bug575551().hoverOverLocal(new String[] {"name"}); + } + + public static class Character { + public static boolean isDigit(int c) { + return (new CharacterLatin()).isDigit(c); + } + + private static class CharacterLatin { + public boolean isDigit(int ch) { + return ch > 0; + } + } + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java index f2fcc6842..599ed29ef 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java @@ -500,6 +500,7 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation cfgs.add(createLaunchConfiguration(jp, "Bug574395")); cfgs.add(createLaunchConfiguration(jp, "Bug571310")); cfgs.add(createLaunchConfiguration(jp, "Bug573547")); + cfgs.add(createLaunchConfiguration(jp, "Bug575551")); loaded18 = true; waitForBuild(); } diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/LambdaVariableTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/LambdaVariableTest.java index 351302a24..39c8b3caa 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/LambdaVariableTest.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/LambdaVariableTest.java @@ -183,6 +183,23 @@ public class LambdaVariableTest extends AbstractDebugTest { assertEquals("wrong result : ", "ab", value.getValueString()); } + public void testEvaluate_Bug575551_onIntermediateFrame_InsideLambda_OutFromMethodInvocationFrame() throws Exception { + createMethodBreakpoint("Bug575551$Character$CharacterLatin", "isDigit", + "(I)Z", true, false); + javaThread = launchToBreakpoint("Bug575551"); + assertNotNull("The program did not suspend", javaThread); + // at method invocation stack + IValue value = doEval(javaThread, "ch"); + assertEquals("wrong result at method stack : ", String.valueOf((int) 'n'), value.getValueString()); + + // at 1st lambda stack + value = doEval(javaThread, () -> (IJavaStackFrame) javaThread.getStackFrames()[3], "names.length"); + assertEquals("wrong result at 1st lambda stack : ", "1", value.getValueString()); + + value = doEval(javaThread, () -> (IJavaStackFrame) javaThread.getStackFrames()[3], "s"); + assertEquals("wrong result at 1st lambda stack : ", "name", value.getValueString()); + } + private void debugWithBreakpoint(String testClass, int lineNumber) throws Exception { createLineBreakpoint(lineNumber, testClass); javaThread = launchToBreakpoint(testClass); diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java index 82f5ff9fd..2152c60ca 100644 --- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java +++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java @@ -420,11 +420,11 @@ public class ASTEvaluationEngine implements IAstEvaluationEngine { private void scanAndFixSignature(String genericSignature, String erasureSignature, StringBuilder fixedSignature) { /* - * This actually fix variables which are type of Generic Types which cannot be resolved to a type in the current content. For example variable - * type like P_OUT in java.util.stream.ReferencePipeline.filter(Predicate<? super P_OUT>) + * This actually fix variables which are type of Generic Types which cannot be resolved to a type in the current context. + * For example variable type like P_OUT in java.util.stream.ReferencePipeline.filter(Predicate<? super P_OUT>) * * and also generic signature such as Ljava/util/function/Predicate<+Ljava/util/List<Ljava/lang/Integer;>;>; Ljava/util/Comparator<-TT;>; - * which will fail the properly resolved to the type. + * which will fail to properly resolved to the type. */ if (genericSignature.startsWith(String.valueOf(Signature.C_TYPE_VARIABLE)) || genericSignature.startsWith(String.valueOf(Signature.C_CAPTURE)) || @@ -444,8 +444,11 @@ public class ASTEvaluationEngine implements IAstEvaluationEngine { String[] typeArguments = Signature.getTypeArguments(genericSignature); if (typeArguments.length > 0) { - if (typeArguments.length == 1 && typeArguments[0].equals(String.valueOf(Signature.C_STAR))) { - // this is when we have recursive generics, so remove the generics to avoid compilation issues. + if (typeArguments.length == 1 && + (typeArguments[0].equals(String.valueOf(Signature.C_STAR)) || + typeArguments[0].startsWith(String.valueOf(new char[] { Signature.C_EXTENDS, Signature.C_TYPE_VARIABLE })))) { + // this is when we have recursive generics or we have a upper bound type variable + // so remove the generics to avoid compilation issues. return; } diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java index ac0c5512b..6cf380392 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java @@ -18,6 +18,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; @@ -83,9 +85,10 @@ public class LambdaUtils { List<IVariable> variables = new ArrayList<>(); if (LambdaUtils.isLambdaFrame(frame)) { IThread thread = frame.getThread(); - IStackFrame[] stackFrames = thread.getStackFrames(); - for (int i = 0; i < Math.min(3, stackFrames.length); ++i) { - IStackFrame stackFrame = stackFrames[i]; + // look for two frames below the frame which is provided instead starting from first frame. + List<IStackFrame> stackFrames = Stream.of(thread.getStackFrames()).dropWhile(f -> f != frame) + .limit(3).collect(Collectors.toUnmodifiableList()); + for (IStackFrame stackFrame : stackFrames) { IVariable[] stackFrameVariables = stackFrame.getVariables(); variables.addAll(Arrays.asList(stackFrameVariables)); for (IVariable frameVariable : stackFrameVariables) { |
