Skip to content

Commit a077106

Browse files
committed
Refactor lambda breakpoint handling and remove deprecated
LambdaLocationLocator
1 parent d4c38a7 commit a077106

File tree

7 files changed

+135
-261
lines changed

7 files changed

+135
-261
lines changed

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/BreakpointMarkerUpdater.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
3333
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
3434
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint;
35-
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaMethodBreakpoint;
36-
import org.eclipse.jdt.internal.debug.core.breakpoints.LambdaLocationLocator;
3735
import org.eclipse.jdt.internal.debug.core.breakpoints.ValidBreakpointLocationLocator;
3836
import org.eclipse.jface.text.BadLocationException;
3937
import org.eclipse.jface.text.IDocument;
@@ -115,25 +113,15 @@ public boolean updateMarker(IMarker marker, IDocument document, Position positio
115113
}
116114
try {
117115
ValidBreakpointLocationLocator loc;
118-
if (breakpoint instanceof IJavaMethodBreakpoint methodBreakpoint && methodBreakpoint.isEntry()) {
116+
if (breakpoint instanceof IJavaMethodBreakpoint && ((IJavaMethodBreakpoint) breakpoint).isEntry()) {
119117
IMarker m = breakpoint.getMarker();
120118
if (m != null) {
121119
int charStart = m.getAttribute(IMarker.CHAR_START, -1);
122120
int charEnd = m.getAttribute(IMarker.CHAR_END, -1);
123121
int length = charEnd - charStart + 1;
124-
if (methodBreakpoint.isLambdaBreakpoint()) {
125-
LambdaLocationLocator currentLambda = new LambdaLocationLocator(charStart, charEnd, JavaMethodBreakpoint.LAMBDA_ALREADY_CALCULATED);
126-
unit.accept(currentLambda);
127-
String existingLamda = methodBreakpoint.getLambdaName();
128-
String selectedLambda = currentLambda.getSelectedLambda();
129-
if (existingLamda != null && selectedLambda != null) {
130-
if (existingLamda.equals(selectedLambda)) {
131-
methodBreakpoint.setLambdaName(selectedLambda);
132-
}
133-
}
134-
}
135122
loc = new ValidBreakpointLocationLocator(unit, document.getLineOfOffset(position.getOffset())
136123
+ 1, true, true, position.getOffset(), length);
124+
137125
} else {
138126
loc = new ValidBreakpointLocationLocator(unit, document.getLineOfOffset(position.getOffset()) + 1, true, true);
139127
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ public class ActionMessages extends NLS {
176176
public static String Override_Dependencies_label1;
177177
public static String Override_Dependencies_label2;
178178

179-
public static String lambdaSelection;
180-
public static String lambdaSelect;
181-
public static String lambdaClose;
179+
public static String LambdaSelectionDialog_title;
182180

183181
static {
184182
// load message values from bundle file

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,4 @@ Override_Dependencies_button=&Override
155155
Override_Dependencies_button1=&Override Dependencies...
156156
Override_Dependencies_label1=Dependencies derived from the Java Build Path:
157157
Override_Dependencies_label2=Dependencies for launching:
158-
lambdaSelection=Select lambda
159-
lambdaSelect=Select
160-
lambdaClose=Close
158+
LambdaSelectionDialog_title=Select lambda

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

Lines changed: 128 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import java.util.ArrayList;
1717
import java.util.Collections;
18+
import java.util.Comparator;
1819
import java.util.HashMap;
1920
import java.util.Iterator;
2021
import java.util.List;
@@ -65,6 +66,7 @@
6566
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
6667
import org.eclipse.jdt.core.dom.CompilationUnit;
6768
import org.eclipse.jdt.core.dom.IBinding;
69+
import org.eclipse.jdt.core.dom.IMethodBinding;
6870
import org.eclipse.jdt.core.dom.ITypeBinding;
6971
import org.eclipse.jdt.core.dom.LambdaExpression;
7072
import org.eclipse.jdt.core.dom.NodeFinder;
@@ -84,7 +86,7 @@
8486
import org.eclipse.jdt.internal.corext.template.java.JavaContextType;
8587
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
8688
import org.eclipse.jdt.internal.debug.core.breakpoints.LambdaCollector;
87-
import org.eclipse.jdt.internal.debug.core.breakpoints.LambdaLocationLocator;
89+
import org.eclipse.jdt.internal.debug.core.breakpoints.LambdaLocationLocatorHelper;
8890
import org.eclipse.jdt.internal.debug.core.breakpoints.ValidBreakpointLocationLocator;
8991
import org.eclipse.jdt.internal.debug.ui.BreakpointUtils;
9092
import org.eclipse.jdt.internal.debug.ui.DebugWorkingCopyManager;
@@ -115,24 +117,21 @@
115117
import org.eclipse.jface.text.templates.TemplateException;
116118
import org.eclipse.jface.viewers.ISelection;
117119
import org.eclipse.jface.viewers.IStructuredSelection;
120+
import org.eclipse.jface.viewers.LabelProvider;
118121
import org.eclipse.jface.viewers.StructuredSelection;
122+
import org.eclipse.jface.window.Window;
119123
import org.eclipse.swt.SWT;
120-
import org.eclipse.swt.events.MouseAdapter;
121-
import org.eclipse.swt.events.MouseEvent;
122124
import org.eclipse.swt.graphics.Point;
123-
import org.eclipse.swt.layout.GridData;
124-
import org.eclipse.swt.layout.GridLayout;
125-
import org.eclipse.swt.widgets.Button;
126125
import org.eclipse.swt.widgets.Composite;
127126
import org.eclipse.swt.widgets.Display;
128127
import org.eclipse.swt.widgets.Event;
129128
import org.eclipse.swt.widgets.Shell;
130-
import org.eclipse.swt.widgets.Table;
131-
import org.eclipse.swt.widgets.TableItem;
132129
import org.eclipse.ui.IEditorInput;
133130
import org.eclipse.ui.IEditorPart;
134131
import org.eclipse.ui.IWorkbenchPart;
135132
import org.eclipse.ui.PlatformUI;
133+
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
134+
import org.eclipse.ui.dialogs.FilteredList;
136135
import org.eclipse.ui.dialogs.PreferencesUtil;
137136
import org.eclipse.ui.texteditor.IDocumentProvider;
138137
import org.eclipse.ui.texteditor.ITextEditor;
@@ -146,6 +145,10 @@
146145
public class ToggleBreakpointAdapter implements IToggleBreakpointsTargetExtension2 {
147146

148147
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
148+
private static final String TRUNCATION_SIGN = "... "; //$NON-NLS-1$
149+
private static final String LAMBDA_SEPARATOR = " "; //$NON-NLS-1$
150+
private static final int MAX_LAMBDA_LINE_LENGTH = 25;
151+
private static final int MAX_TOTAL_LAMBDA_LINE_LENGTH = MAX_LAMBDA_LINE_LENGTH * 2;
149152

150153
/**
151154
* Constructor
@@ -1698,30 +1701,31 @@ private void toggleFieldOrMethodBreakpoints(IWorkbenchPart part, ISelection sele
16981701
IDocument document = documentProvider.getDocument(editorInput);
16991702
try {
17001703
IRegion region = document.getLineInformation(ts.getStartLine());
1701-
CompilationUnit unitForLambdas = parseCompilationUnit(editor);
1702-
LambdaCollector lambdas = new LambdaCollector(region.getOffset(), region.getOffset() + region.getLength());
1703-
unitForLambdas.accept(lambdas);
1704-
List<LambdaExpression> lambdaExpresions = lambdas.getLambdaExpressions();
1705-
int selected = -1;
1706-
if (lambdaExpresions.size() > 1) {
1707-
selected = selectLambda(lambdaExpresions);
1708-
if (selected == -1) {
1704+
List<LambdaExpression> lambdaExpresions = findLambdaExpressions(editor, region);
1705+
if (lambdaExpresions.isEmpty()) {
1706+
return;
1707+
}
1708+
int lambdaPosition;
1709+
if (lambdaExpresions.size() == 1) {
1710+
lambdaPosition = 0;
1711+
} else {
1712+
lambdaPosition = selectLambda(lambdaExpresions);
1713+
if (lambdaPosition == -1) {
17091714
return;
17101715
}
17111716
}
1712-
1713-
LambdaLocationLocator selectedLambda = new LambdaLocationLocator(region.getOffset(), region.getOffset()
1714-
+ region.getLength(), selected == -1 ? selected = 0 : selected);
1715-
unit.accept(selectedLambda);
1716-
if (selectedLambda.getNodeLength() == -1 || selectedLambda.getNodeOffset() == -1) {
1717+
LambdaExpression selectedLambda = lambdaExpresions.get(lambdaPosition);
1718+
IMethodBinding methodBinding = selectedLambda.resolveMethodBinding();
1719+
if (methodBinding == null) {
17171720
BreakpointToggleUtils.report(ActionMessages.LambdaEntryBreakpointToggleAction_Unavailable, part);
17181721
return;
17191722
}
1720-
ITextSelection textSelection = new TextSelection(document, selectedLambda.getNodeOffset(), selectedLambda.getNodeLength());
1721-
LambdaBreakpoint lambdaBp = new LambdaBreakpoint(lambdaExpresions.get(selected).toString(), selected, lambdaExpresions.size() > 1
1722-
? true
1723-
: false);
1724-
toggleLambdaEntryMethodBreakpoints(part, textSelection, selectedLambda.getLambdaMethodName(), selectedLambda.getfLambdaMethodSignature(), lambdaBp);
1723+
String lambdaMethodName = LambdaLocationLocatorHelper.toMethodName(methodBinding);
1724+
String lambdaMethodSignature = LambdaLocationLocatorHelper.toMethodSignature(methodBinding);
1725+
ITextSelection textSelection = new TextSelection(document, selectedLambda.getStartPosition(), selectedLambda.getLength());
1726+
boolean inline = lambdaExpresions.size() > 1 ? true : false;
1727+
LambdaBreakpoint lambdaBp = new LambdaBreakpoint(lambdaExpresions.get(lambdaPosition).toString(), lambdaPosition, inline);
1728+
toggleLambdaEntryMethodBreakpoints(part, textSelection, lambdaMethodName, lambdaMethodSignature, lambdaBp);
17251729
} catch (BadLocationException e) {
17261730
BreakpointToggleUtils.report(ActionMessages.LambdaEntryBreakpointToggleAction_Unavailable, part);
17271731
}
@@ -1732,9 +1736,16 @@ private void toggleFieldOrMethodBreakpoints(IWorkbenchPart part, ISelection sele
17321736
}
17331737
}
17341738

1735-
private record LambdaBreakpoint(String lambdaName, int lambdaPosition, boolean isInline) {
1739+
private static List<LambdaExpression> findLambdaExpressions(ITextEditor editor, IRegion region) {
1740+
LambdaCollector lambdas = new LambdaCollector(region.getOffset(), region.getOffset() + region.getLength());
1741+
CompilationUnit unitForLambdas = parseCompilationUnit(editor);
1742+
unitForLambdas.accept(lambdas);
1743+
return lambdas.getLambdaExpressions();
1744+
}
1745+
1746+
private static record LambdaBreakpoint(String lambdaName, int lambdaPosition, boolean isInline) {
17361747
public String getLambdaName() {
1737-
return shortenExpression(lambdaName);
1748+
return shortenLambdaExpression(lambdaName);
17381749
}
17391750
}
17401751

@@ -1953,109 +1964,110 @@ private static ICompilationUnit getCompilationUnit(ITextEditor editor) {
19531964
}
19541965

19551966
public int selectLambda(List<LambdaExpression> lambdaExps) {
1956-
if (lambdaExps.isEmpty()) {
1957-
return -1;
1967+
List<String> lambdaNames = lambdaExps.stream().map(expr -> shortenLambdaExpression(expr.toString())).toList();
1968+
LambdaLabelProvider lambdaLabelProvider = new LambdaLabelProvider(lambdaExps, lambdaNames);
1969+
ElementListSelectionDialog dialog = new ElementListSelectionDialog(DebugUIPlugin.getShellForModalDialog(), lambdaLabelProvider) {
1970+
@Override
1971+
protected FilteredList createFilteredList(Composite parent) {
1972+
FilteredList filteredList = super.createFilteredList(parent);
1973+
// Disable default sorting to keep the original order
1974+
filteredList.setComparator(new LambdaPositionComparator(lambdaNames));
1975+
return filteredList;
1976+
}
1977+
1978+
@Override
1979+
protected void setShellStyle(int newShellStyle) {
1980+
super.setShellStyle(newShellStyle & ~SWT.APPLICATION_MODAL);
1981+
}
1982+
};
1983+
dialog.setMultipleSelection(false);
1984+
dialog.setTitle(ActionMessages.LambdaSelectionDialog_title);
1985+
dialog.setElements(lambdaExps.toArray());
1986+
dialog.open();
1987+
if (dialog.getReturnCode() == Window.OK) {
1988+
Object result = dialog.getFirstResult();
1989+
return lambdaExps.indexOf(result);
1990+
}
1991+
return -1;
1992+
}
1993+
1994+
private static class LambdaPositionComparator implements Comparator<Object> {
1995+
private List<String> lambdaNames;
1996+
1997+
public LambdaPositionComparator(List<String> lambdaNames) {
1998+
this.lambdaNames = lambdaNames;
19581999
}
19592000

1960-
int[] selection = { -1 };
1961-
Shell parentShell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1962-
Shell popup = new Shell(parentShell, SWT.TOOL | SWT.RESIZE);
1963-
popup.setText(ActionMessages.lambdaSelection);
1964-
GridLayout popupLayout = new GridLayout(1, false);
1965-
popupLayout.marginWidth = 10;
1966-
popupLayout.marginHeight = 10;
1967-
popupLayout.verticalSpacing = 10;
1968-
popup.setLayout(popupLayout);
2001+
@Override
2002+
public int compare(Object o1, Object o2) {
2003+
int index1 = lambdaNames.indexOf(o1);
2004+
int index2 = lambdaNames.indexOf(o2);
2005+
return index1 - index2;
2006+
}
2007+
}
19692008

1970-
Table table = new Table(popup, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
1971-
GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true);
1972-
table.setLayoutData(tableData);
1973-
List<String> itemsName = toLambdaEntries(lambdaExps);
2009+
private static class LambdaLabelProvider extends LabelProvider {
2010+
private List<LambdaExpression> lambdaExps;
2011+
private List<String> lambdaNames;
19742012

1975-
for (String item : itemsName) {
1976-
new TableItem(table, SWT.NONE).setText(item);
2013+
public LambdaLabelProvider(List<LambdaExpression> lambdaExps, List<String> lambdaNames) {
2014+
this.lambdaExps = lambdaExps;
2015+
this.lambdaNames = lambdaNames;
19772016
}
19782017

1979-
table.addMouseListener(new MouseAdapter() {
1980-
@Override
1981-
public void mouseDoubleClick(MouseEvent e) {
1982-
int ind = table.getSelectionIndex();
1983-
if (ind >= 0) {
1984-
selection[0] = ind;
1985-
popup.close();
2018+
@Override
2019+
public String getText(Object element) {
2020+
if (element instanceof LambdaExpression) {
2021+
int index = lambdaExps.indexOf(element);
2022+
if (index != -1) {
2023+
return lambdaNames.get(index);
19862024
}
19872025
}
1988-
});
1989-
1990-
Composite buttonBar = new Composite(popup, SWT.NONE);
1991-
GridLayout buttonLayout = new GridLayout(2, true);
1992-
buttonLayout.marginWidth = 0;
1993-
buttonLayout.marginHeight = 0;
1994-
buttonLayout.horizontalSpacing = 10;
1995-
buttonBar.setLayout(buttonLayout);
1996-
buttonBar.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
1997-
Button selectButton = new Button(buttonBar, SWT.PUSH);
1998-
selectButton.setText(ActionMessages.lambdaSelect);
1999-
selectButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
2000-
2001-
selectButton.addListener(SWT.Selection, e -> {
2002-
int index = table.getSelectionIndex();
2003-
if (index >= 0) {
2004-
selection[0] = index;
2005-
popup.close();
2006-
}
2007-
});
2008-
Button closeButton = new Button(buttonBar, SWT.PUSH);
2009-
closeButton.setText(ActionMessages.lambdaClose);
2010-
closeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
2011-
closeButton.addListener(SWT.Selection, e -> popup.close());
2012-
int tableHeight = Math.min(lambdaExps.size(), 10) * table.getItemHeight() + 80;
2013-
popup.setSize(300, tableHeight);
2014-
Point location = Display.getDefault().getCursorLocation();
2015-
popup.setLocation(location);
2016-
popup.addListener(SWT.Deactivate, e -> popup.close());
2017-
popup.open();
2018-
while (!popup.isDisposed()) {
2019-
if (!Display.getDefault().readAndDispatch()) {
2020-
Display.getDefault().sleep();
2021-
}
2022-
}
2023-
if (!popup.isDisposed()) {
2024-
popup.dispose();
2025-
}
2026-
return selection[0];
2026+
return super.getText(element);
2027+
}
20272028
}
20282029

2029-
public static String shortenExpression(String input) {
2030+
/**
2031+
* Shorten and &quot;flatten&quot; the (possible multi-line) lambda expression
2032+
*
2033+
* @param input
2034+
* non null
2035+
* @return shortened and flattened lambda expression
2036+
*/
2037+
static String shortenLambdaExpression(String input) {
2038+
input = input.strip();
2039+
StringBuilder result = new StringBuilder();
20302040
if (!input.contains("\n")) { //$NON-NLS-1$
2031-
return input;
2032-
}
2033-
String singleLine = new String(input);
2034-
StringBuilder shortened = new StringBuilder();
2035-
for (String token : singleLine.split("\n")) { //$NON-NLS-1$
2036-
token = token.trim();
2037-
if (token.length() > 20) {
2038-
shortened.append(token, 0, 14).append(".. "); //$NON-NLS-1$
2041+
if (input.length() > MAX_TOTAL_LAMBDA_LINE_LENGTH) {
2042+
result.append(input, 0, MAX_TOTAL_LAMBDA_LINE_LENGTH).append(TRUNCATION_SIGN);
20392043
} else {
2040-
shortened.append(token).append(" "); //$NON-NLS-1$
2044+
result.append(input);
20412045
}
2046+
return result.toString();
20422047
}
2043-
return shortened.toString().trim();
2044-
}
2045-
2046-
private List<String> toLambdaEntries(List<LambdaExpression> lambdaExps) {
2047-
List<String> itemsName = lambdaExps.stream().map(LambdaExpression::toString).toList();
2048-
itemsName = itemsName.stream().map(item -> item.trim().replaceAll("\\n+$", "")).toList(); //$NON-NLS-1$ //$NON-NLS-2$
2049-
if (Platform.getOS().equals(Platform.OS_MACOSX)) { // If an expression is of multiline then we should shorten it to single line.
2050-
itemsName = itemsName.stream().map(ToggleBreakpointAdapter::shortenExpression).toList();
2048+
boolean shortened = false;
2049+
for (String line : input.split("\n")) { //$NON-NLS-1$
2050+
if (result.length() > 0) {
2051+
result.append(LAMBDA_SEPARATOR);
2052+
}
2053+
line = line.strip();
2054+
if (line.length() > MAX_LAMBDA_LINE_LENGTH) {
2055+
line = line.substring(0, MAX_LAMBDA_LINE_LENGTH) + TRUNCATION_SIGN;
2056+
shortened = true;
2057+
}
2058+
result.append(line);
2059+
if (result.length() > MAX_TOTAL_LAMBDA_LINE_LENGTH) {
2060+
shortened = true;
2061+
break;
2062+
}
20512063
}
2052-
itemsName = itemsName.stream().map(item -> {
2053-
if (!item.isEmpty() && item.charAt(item.length() - 1) == '\n') {
2054-
int newLength = Math.max(0, item.length() - 2);
2055-
return item.substring(0, newLength).trim();
2064+
2065+
if (shortened) {
2066+
if (result.lastIndexOf(TRUNCATION_SIGN) != result.length() - TRUNCATION_SIGN.length()) {
2067+
result.append(TRUNCATION_SIGN);
20562068
}
2057-
return item;
2058-
}).toList();
2059-
return itemsName;
2069+
}
2070+
return result.toString().trim();
20602071
}
2072+
20612073
}

0 commit comments

Comments
 (0)