Skip to content

Commit fef48df

Browse files
gayanperSarikaSinha
authored andcommitted
Bug 579100 - Add support for lambda breakpoints with outer variables
When generating lambda methods for expressions with outer variables, those variable becomes part of lambda method parameters. Now those parameters are considered when matching the method entry debug points. Change-Id: Idb46332d8e9fe3df2a9fb4a8ad4103f92e26b04a Signed-off-by: Gayan Perera <[email protected]> Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.debug/+/191517 Tested-by: JDT Bot <[email protected]> Reviewed-by: Sarika Sinha <[email protected]>
1 parent 5321da4 commit fef48df

File tree

4 files changed

+96
-23
lines changed

4 files changed

+96
-23
lines changed

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ToggleBreakpointAdapter.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,15 @@ protected IStatus run(IProgressMonitor monitor) {
269269
job.schedule();
270270
}
271271

272-
public void toggleLambdaEntryMethodBreakpoints(final IWorkbenchPart part, final ISelection finalSelection, final String lambdaMethodName) {
272+
public void toggleLambdaEntryMethodBreakpoints(final IWorkbenchPart part, final ISelection finalSelection, final String lambdaMethodName, final String lambdaMethodSignature) {
273273
Job job = new Job("Toggle Lambda Entry Method Breakpoints") { //$NON-NLS-1$
274274
@Override
275275
protected IStatus run(IProgressMonitor monitor) {
276276
if (monitor.isCanceled()) {
277277
return Status.CANCEL_STATUS;
278278
}
279279
try {
280-
return doToggleLambdaEntryMethodBreakpoints(part, finalSelection, lambdaMethodName, monitor);
280+
return doToggleLambdaEntryMethodBreakpoints(part, finalSelection, lambdaMethodName, lambdaMethodSignature, monitor);
281281
} catch (CoreException e) {
282282
return e.getStatus();
283283
} finally {
@@ -290,7 +290,7 @@ protected IStatus run(IProgressMonitor monitor) {
290290
job.schedule();
291291
}
292292

293-
static IStatus doToggleLambdaEntryMethodBreakpoints(IWorkbenchPart part, ISelection selection, String lambdaMethodName, IProgressMonitor monitor) throws CoreException {
293+
static IStatus doToggleLambdaEntryMethodBreakpoints(IWorkbenchPart part, ISelection selection, String lambdaMethodName, String lambdaMethodSignature, IProgressMonitor monitor) throws CoreException {
294294
ITextEditor textEditor = getTextEditor(part);
295295
if (textEditor == null || !(selection instanceof ITextSelection)) {
296296
return Status.OK_STATUS;
@@ -316,7 +316,7 @@ static IStatus doToggleLambdaEntryMethodBreakpoints(IWorkbenchPart part, ISelect
316316
}
317317

318318
if (method != null) {
319-
doToggleMethodBreakpoint(method, lambdaMethodName, part, selection, monitor);
319+
doToggleMethodBreakpoint(method, lambdaMethodName, lambdaMethodSignature, part, selection, monitor);
320320
} else {
321321
BreakpointToggleUtils.report(ActionMessages.LambdaEntryBreakpointToggleAction_Unavailable, part);
322322
}
@@ -354,7 +354,7 @@ static IStatus doToggleLambdaMethodBreakpoints(IWorkbenchPart part, ISelection s
354354
}
355355

356356
if (method != null) {
357-
doToggleMethodBreakpoint(method, loc.getLambdaMethodName(), part, selection, monitor);
357+
doToggleMethodBreakpoint(method, loc.getLambdaMethodName(), loc.getfLambdaMethodSignature(), part, selection, monitor);
358358
} else {
359359
ValidBreakpointLocationLocator locNew = new ValidBreakpointLocationLocator(loc.getCompilationUnit(), textSelection.getStartLine()
360360
+ 1, true, true);
@@ -392,10 +392,10 @@ static IStatus doToggleMethodBreakpoints(IWorkbenchPart part, ISelection finalSe
392392
}
393393

394394
private static void doToggleMethodBreakpoint(IMethod member, IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
395-
doToggleMethodBreakpoint(member, null, part, finalSelection, monitor);
395+
doToggleMethodBreakpoint(member, null, null, part, finalSelection, monitor);
396396
}
397397

398-
private static void doToggleMethodBreakpoint(IMethod member, String lambdaMethodName, IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
398+
private static void doToggleMethodBreakpoint(IMethod member, String lambdaMethodName, String lambdaMethodSignature, IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
399399
IJavaBreakpoint breakpoint = getMethodBreakpoint(member);
400400
if (breakpoint != null) {
401401
if (BreakpointToggleUtils.isToggleTracepoints()) {
@@ -416,15 +416,15 @@ private static void doToggleMethodBreakpoint(IMethod member, String lambdaMethod
416416
Map<String, Object> attributes = new HashMap<>(10);
417417
BreakpointUtils.addJavaBreakpointAttributes(attributes, member);
418418
IType type = member.getDeclaringType();
419-
String signature = member.getSignature();
420419
String mname = Optional.ofNullable(lambdaMethodName).orElse(member.getElementName());
420+
String signature = Optional.ofNullable(lambdaMethodSignature).orElse(member.getSignature());
421421
if (member.isConstructor()) {
422422
mname = "<init>"; //$NON-NLS-1$
423423
if (type.isEnum()) {
424424
signature = "(Ljava.lang.String;I" + signature.substring(1); //$NON-NLS-1$
425425
}
426426
}
427-
if (!type.isBinary()) {
427+
if (!type.isBinary() && lambdaMethodName == null) {
428428
signature = resolveMethodSignature(member);
429429
if (signature == null) {
430430
BreakpointToggleUtils.report(ActionMessages.ManageMethodBreakpointActionDelegate_methodNonAvailable, part);
@@ -1601,7 +1601,7 @@ private void toggleFieldOrMethodBreakpoints(IWorkbenchPart part, ISelection sele
16011601
return;
16021602
}
16031603
ITextSelection textSelection = new TextSelection(document, firstLambda.getNodeOffset(), firstLambda.getNodeLength());
1604-
toggleLambdaEntryMethodBreakpoints(part, textSelection, firstLambda.getLambdaMethodName());
1604+
toggleLambdaEntryMethodBreakpoints(part, textSelection, firstLambda.getLambdaMethodName(), firstLambda.getfLambdaMethodSignature());
16051605
} catch (BadLocationException e) {
16061606
BreakpointToggleUtils.report(ActionMessages.LambdaEntryBreakpointToggleAction_Unavailable, part);
16071607
}

org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/FirstLambdaLocationLocator.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class FirstLambdaLocationLocator extends ASTVisitor {
2323
private int fLineOffset = -1;
2424
private int fLineEndPosition = -1;
2525
private String fLambdaMethodName;
26+
private String fLambdaMethodSignature;
2627
private boolean fLocationFound = false;
2728

2829
public FirstLambdaLocationLocator(int lineOffset, int lineEndPosition) {
@@ -37,6 +38,15 @@ public String getLambdaMethodName() {
3738
return fLambdaMethodName;
3839
}
3940

41+
/**
42+
* Return of the signature of the lambda method where the valid location is.
43+
* The signature is computed to be compatible with the final lambda method with
44+
* method arguments and outer local variables.
45+
*/
46+
public String getfLambdaMethodSignature() {
47+
return fLambdaMethodSignature;
48+
}
49+
4050
public int getNodeLength() {
4151
return fNodeLength;
4252
}
@@ -57,15 +67,10 @@ public boolean visit(LambdaExpression node) {
5767
fNodeOffset = node.getStartPosition();
5868
IMethodBinding methodBinding = node.resolveMethodBinding();
5969
if (methodBinding != null) {
60-
fLambdaMethodName = toMethodName(methodBinding);
70+
fLambdaMethodName = LambdaLocationLocatorHelper.toMethodName(methodBinding);
71+
fLambdaMethodSignature = LambdaLocationLocatorHelper.toMethodSignature(methodBinding);
6172
fLocationFound = true;
6273
}
6374
return false;
6475
}
65-
66-
private String toMethodName(IMethodBinding methodBinding) {
67-
String key = methodBinding.getKey();
68-
return key.substring(key.indexOf('.') + 1, key.indexOf('('));
69-
}
70-
7176
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 Gayan Perera and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Gayan Perera - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.jdt.internal.debug.core.breakpoints;
15+
16+
import java.util.stream.Collectors;
17+
import java.util.stream.Stream;
18+
19+
import org.eclipse.jdt.core.Signature;
20+
import org.eclipse.jdt.core.dom.IMethodBinding;
21+
import org.eclipse.jdt.core.dom.ITypeBinding;
22+
23+
public final class LambdaLocationLocatorHelper {
24+
25+
private LambdaLocationLocatorHelper() {
26+
}
27+
28+
/**
29+
* Return of the signature of the lambda method. The signature is computed to
30+
* be compatible with the final lambda method with method arguments and outer
31+
* local variables in debugger.
32+
*/
33+
public static String toMethodSignature(IMethodBinding methodBinding) {
34+
StringBuilder builder = new StringBuilder();
35+
builder.append('(');
36+
if (methodBinding.getParameterTypes().length > 0 || methodBinding.getSyntheticOuterLocals().length > 0) {
37+
builder.append(Stream.of(methodBinding.getSyntheticOuterLocals())
38+
.map(b -> Signature.createTypeSignature(qualifiedName(b.getType()), true))
39+
.collect(Collectors.joining()));
40+
41+
builder.append(Stream.of(methodBinding.getParameterTypes())
42+
.map(b -> Signature.createTypeSignature(qualifiedName(b), true))
43+
.collect(Collectors.joining()));
44+
}
45+
builder.append(')');
46+
builder.append(Signature.createTypeSignature(qualifiedName(methodBinding.getReturnType()), true));
47+
return builder.toString();
48+
}
49+
50+
/**
51+
* Return the lambda method name from the given method binding.
52+
*/
53+
public static String toMethodName(IMethodBinding methodBinding) {
54+
String key = methodBinding.getKey();
55+
return key.substring(key.indexOf('.') + 1, key.indexOf('('));
56+
}
57+
58+
private static String qualifiedName(ITypeBinding binding) {
59+
return binding.getQualifiedName().replace('.', '/');
60+
}
61+
}

org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/ValidBreakpointLocationLocator.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class ValidBreakpointLocationLocator extends ASTVisitor {
140140
private boolean fLocationFound;
141141
private boolean fLambdaVisited;
142142
private String fLambdaMethodName;
143+
private String fLambdaMethodSignature;
143144
private String fTypeName;
144145
private int fLineLocation;
145146
private int fMemberOffset;
@@ -227,6 +228,16 @@ public String getFullyQualifiedTypeName() {
227228
public String getLambdaMethodName() {
228229
return fLambdaMethodName;
229230
}
231+
232+
/**
233+
* Return of the signature of the lambda method where the valid location is.
234+
* The signature is computed to be compatible with the final lambda method with
235+
* method arguments and outer local variables.
236+
*/
237+
public String getfLambdaMethodSignature() {
238+
return fLambdaMethodSignature;
239+
}
240+
230241
/**
231242
* Return the line number of the computed valid location
232243
*/
@@ -1024,7 +1035,8 @@ public boolean visit(LambdaExpression node) {
10241035
if (methodBinding != null) {
10251036
fLambdaVisited = true;
10261037
fLocationType = LOCATION_LAMBDA_METHOD;
1027-
fLambdaMethodName = toMethodName(methodBinding);
1038+
fLambdaMethodName = LambdaLocationLocatorHelper.toMethodName(methodBinding);
1039+
fLambdaMethodSignature = LambdaLocationLocatorHelper.toMethodSignature(methodBinding);
10281040
fLocationFound = true;
10291041
return false;
10301042
}
@@ -1062,11 +1074,6 @@ public boolean visit(LambdaExpression node) {
10621074
return visit(node, true);
10631075
}
10641076

1065-
private String toMethodName(IMethodBinding methodBinding) {
1066-
String key = methodBinding.getKey();
1067-
return key.substring(key.indexOf('.') + 1, key.indexOf('('));
1068-
}
1069-
10701077
/*
10711078
* (non-Javadoc)
10721079
*

0 commit comments

Comments
 (0)