Skip to content

Commit a59b48d

Browse files
SougandhSjukzi
authored andcommitted
Support for Primitives #268
This commit provides support for Primitive types and Primitive arrays in Detail Formatter for variables view. And includes missing annotation for isVirtual() method in ThreadReferenceImpl class Fixes : #268
1 parent ff239f3 commit a59b48d

17 files changed

Lines changed: 580 additions & 41 deletions

File tree

org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ void assert15Project() {
405405
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug329294WithGenerics"));
406406
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug403028"));
407407
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug484686"));
408+
cfgs.add(createLaunchConfiguration(jp, "a.b.c.PrimitivesTest"));
408409
cfgs.add(createLaunchConfiguration(jp, "a.b.c.GenericMethodEntryTest"));
409410
cfgs.add(createLaunchConfiguration(jp, "org.eclipse.debug.tests.targets.HcrClass", true));
410411
cfgs.add(createLaunchConfiguration(jp, "a.b.c.Bug570988"));

org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/DetailFormatterTests.java

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,131 @@ public void testHoverWithNoTypeArguments() throws Exception {
340340
removeAllBreakpoints();
341341
}
342342
}
343+
344+
public void testFormatterForPrimitivesInt() throws Exception {
345+
IJavaThread thread = null;
346+
DetailFormatter formatter = null;
347+
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
348+
try {
349+
String typename = "a.b.c.PrimitivesTest";
350+
createLineBreakpoint(26, typename);
351+
thread = launchToBreakpoint(typename);
352+
assertNotNull("The program did not suspend", thread);
353+
String snippet = "this + 12";
354+
formatter = new DetailFormatter("int", snippet, true);
355+
jdfm.setAssociatedDetailFormatter(formatter);
356+
IJavaVariable var = thread.findVariable("x");
357+
assertNotNull("the variable 'x' must exist in the frame", var);
358+
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
359+
waitForListenerValue();
360+
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
361+
assertEquals("24", fListener.result.toString());
362+
363+
} finally {
364+
jdfm.removeAssociatedDetailFormatter(formatter);
365+
terminateAndRemove(thread);
366+
removeAllBreakpoints();
367+
}
368+
}
369+
370+
public void testFormatterForPrimitivesfloat() throws Exception {
371+
IJavaThread thread = null;
372+
DetailFormatter formatter = null;
373+
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
374+
try {
375+
String typename = "a.b.c.PrimitivesTest";
376+
createLineBreakpoint(26, typename);
377+
thread = launchToBreakpoint(typename);
378+
assertNotNull("The program did not suspend", thread);
379+
String snippet = "this + 10";
380+
formatter = new DetailFormatter("float", snippet, true);
381+
jdfm.setAssociatedDetailFormatter(formatter);
382+
IJavaVariable var = thread.findVariable("f");
383+
assertNotNull("the variable 'f' must exist in the frame", var);
384+
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
385+
waitForListenerValue();
386+
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
387+
assertEquals("20.0", fListener.result.toString());
388+
} finally {
389+
jdfm.removeAssociatedDetailFormatter(formatter);
390+
terminateAndRemove(thread);
391+
removeAllBreakpoints();
392+
}
393+
}
394+
395+
public void testFormatterForPrimitivesIntArrays() throws Exception {
396+
IJavaThread thread = null;
397+
DetailFormatter formatter = null;
398+
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
399+
try {
400+
String typename = "a.b.c.PrimitivesTest";
401+
createLineBreakpoint(26, typename);
402+
thread = launchToBreakpoint(typename);
403+
assertNotNull("The program did not suspend", thread);
404+
String snippet = "this[1]";
405+
formatter = new DetailFormatter("int[]", snippet, true);
406+
jdfm.setAssociatedDetailFormatter(formatter);
407+
IJavaVariable var = thread.findVariable("arInt");
408+
assertNotNull("the variable 'arInt' must exist in the frame", var);
409+
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
410+
waitForListenerValue();
411+
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
412+
assertEquals("2", fListener.result.toString());
413+
} finally {
414+
jdfm.removeAssociatedDetailFormatter(formatter);
415+
terminateAndRemove(thread);
416+
removeAllBreakpoints();
417+
}
418+
}
419+
420+
public void testFormatterForPrimitivesIntArraysMulti() throws Exception {
421+
IJavaThread thread = null;
422+
DetailFormatter formatter = null;
423+
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
424+
try {
425+
String typename = "a.b.c.PrimitivesTest";
426+
createLineBreakpoint(26, typename);
427+
thread = launchToBreakpoint(typename);
428+
assertNotNull("The program did not suspend", thread);
429+
String snippet = "this[0][0]";
430+
formatter = new DetailFormatter("int[][]", snippet, true);
431+
jdfm.setAssociatedDetailFormatter(formatter);
432+
IJavaVariable var = thread.findVariable("mul");
433+
assertNotNull("the variable 'mul' must exist in the frame", var);
434+
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
435+
waitForListenerValue();
436+
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
437+
assertEquals("1", fListener.result.toString());
438+
} finally {
439+
jdfm.removeAssociatedDetailFormatter(formatter);
440+
terminateAndRemove(thread);
441+
removeAllBreakpoints();
442+
}
443+
}
444+
445+
public void testFormatterForPrimitivesCharArray() throws Exception {
446+
IJavaThread thread = null;
447+
DetailFormatter formatter = null;
448+
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
449+
try {
450+
String typename = "a.b.c.PrimitivesTest";
451+
createLineBreakpoint(26, typename);
452+
thread = launchToBreakpoint(typename);
453+
assertNotNull("The program did not suspend", thread);
454+
String snippet = "new String(this)";
455+
formatter = new DetailFormatter("char[]", snippet, true);
456+
jdfm.setAssociatedDetailFormatter(formatter);
457+
IJavaVariable var = thread.findVariable("aCh");
458+
assertNotNull("the variable 'aCh' must exist in the frame", var);
459+
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
460+
waitForListenerValue();
461+
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
462+
assertEquals("ab", fListener.result.toString());
463+
} finally {
464+
jdfm.removeAssociatedDetailFormatter(formatter);
465+
terminateAndRemove(thread);
466+
removeAllBreakpoints();
467+
}
468+
}
469+
343470
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation 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+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
package a.b.c;
15+
16+
public class PrimitivesTest {
17+
public static void main(String[] args) {
18+
Double xd = Double.valueOf(1);
19+
int x = 12;
20+
float f = 10;
21+
int[] arInt = { 1, 2, 3 };
22+
char[] aCh = { 'a', 'b' };
23+
boolean b = false;
24+
double[] d = { 1, 3, 4 };
25+
int[][] mul = { { 1, 3, 4 }, { 1, 3, 4 } };
26+
int p1 = 120;
27+
}
28+
}

org.eclipse.jdt.debug.ui/plugin.xml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -753,22 +753,12 @@
753753
id="org.eclipse.jdt.debug.ui.FilteredJavaVariableActions">
754754
<visibility>
755755
<and>
756-
<objectState
757-
name="PrimitiveVariableActionFilter"
758-
value="isValuePrimitive">
759-
</objectState>
760756
<not>
761757
<objectState
762758
name="DetailFormatterFilter"
763759
value="isDefined">
764760
</objectState>
765761
</not>
766-
<not>
767-
<objectState
768-
name="PrimitiveVariableActionFilter"
769-
value="isArray">
770-
</objectState>
771-
</not>
772762
<not>
773763
<objectState
774764
name="JavaVariableFilter"
@@ -812,15 +802,8 @@
812802
name="DetailFormatterFilter"
813803
value="inSuperclass"/>
814804
</or>
815-
<not>
816-
<objectState
817-
name="PrimitiveVariableActionFilter"
818-
value="isArray">
819-
</objectState>
820-
</not>
821805
</and>
822806
</visibility>
823-
824807
</objectContribution>
825808
<objectContribution
826809
id="org.eclipse.jdt.debug.ui.FilteredJavaVariableActions"

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ public class DebugUIMessages extends NLS {
308308
public static String DetailFormatterDialog_Associated_code_must_not_be_empty_3;
309309
public static String DetailFormatterDialog_Detail_formatter__code_snippet__1;
310310
public static String DetailFormatterDialog_17;
311+
public static String DetailFormatterPrimitiveSelect;
312+
public static String DetailFormatterPrimitiveSelectionLabel;
311313

312314
public static String No_type_with_the_given_name_found_in_the_workspace__1;
313315
public static String JavaDetailFormattersManager_Detail_formatter_error___1;

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ DetailFormatterDialog_Add_Detail_Formatter_2=Add Detail Formatter
254254
DetailFormatterDialog_Associated_code_must_not_be_empty_3=Detail formatter code snippet must not be empty
255255
DetailFormatterDialog_Detail_formatter__code_snippet__1=Detail formatter &code snippet:
256256
DetailFormatterDialog_17=Detail formatter &code snippet ({0} for code assist):
257+
DetailFormatterPrimitiveSelect=Select primitives
258+
DetailFormatterPrimitiveSelectionLabel=Choose a primitive
257259

258260
No_type_with_the_given_name_found_in_the_workspace__1=No type with the given name found in the workspace.
259261
JavaDetailFormattersManager_Detail_formatter_error___1=Detail formatter error:

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

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2015 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -51,6 +51,9 @@
5151
import org.eclipse.jface.text.IDocumentListener;
5252
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
5353
import org.eclipse.jface.text.source.ISourceViewer;
54+
import org.eclipse.jface.viewers.ArrayContentProvider;
55+
import org.eclipse.jface.viewers.LabelProvider;
56+
import org.eclipse.jface.window.Window;
5457
import org.eclipse.osgi.util.NLS;
5558
import org.eclipse.swt.SWT;
5659
import org.eclipse.swt.events.ModifyEvent;
@@ -67,6 +70,7 @@
6770
import org.eclipse.ui.IWorkbench;
6871
import org.eclipse.ui.IWorkbenchCommandConstants;
6972
import org.eclipse.ui.PlatformUI;
73+
import org.eclipse.ui.dialogs.ListDialog;
7074
import org.eclipse.ui.dialogs.SelectionDialog;
7175
import org.eclipse.ui.handlers.IHandlerActivation;
7276
import org.eclipse.ui.handlers.IHandlerService;
@@ -168,11 +172,10 @@ protected Control createDialogArea(Composite parent) {
168172
Font font = parent.getFont();
169173
Composite container = (Composite)super.createDialogArea(parent);
170174

171-
SWTFactory.createLabel(container, DebugUIMessages.DetailFormatterDialog_Qualified_type__name__2, 1);
175+
SWTFactory.createLabel(container, DebugUIMessages.DetailFormatterDialog_Qualified_type__name__2, 2);
172176

173177
Composite innerContainer = SWTFactory.createComposite(container, font, 2, 1, GridData.FILL_HORIZONTAL);
174-
175-
fTypeNameText = SWTFactory.createSingleText(innerContainer, 1);
178+
fTypeNameText = SWTFactory.createSingleText(innerContainer, 2);
176179
fTypeNameText.setEditable(fEditTypeName);
177180
fTypeNameText.setText(fDetailFormatter.getTypeName());
178181
fTypeNameText.addModifyListener(new ModifyListener() {
@@ -182,16 +185,31 @@ public void modifyText(ModifyEvent e) {
182185
checkValues();
183186
}
184187
});
188+
Button primitiveSearchButton = SWTFactory.createPushButton(innerContainer, DebugUIMessages.DetailFormatterPrimitiveSelect, null);
189+
primitiveSearchButton.setEnabled(fEditTypeName);
190+
191+
GridData gridLayout = new GridData(GridData.FILL_HORIZONTAL);
192+
gridLayout.horizontalSpan = 1;
193+
gridLayout.grabExcessHorizontalSpace = true;
194+
primitiveSearchButton.setLayoutData(gridLayout);
195+
primitiveSearchButton.addListener(SWT.Selection, new Listener() {
196+
@Override
197+
public void handleEvent(Event e) {
198+
selectPrimitiveType();
199+
}
200+
});
185201

186202
Button typeSearchButton = SWTFactory.createPushButton(innerContainer, DebugUIMessages.DetailFormatterDialog_Select__type_4, null);
187203
typeSearchButton.setEnabled(fEditTypeName);
204+
typeSearchButton.setLayoutData(gridLayout);
188205
typeSearchButton.addListener(SWT.Selection, new Listener() {
189206
@Override
190207
public void handleEvent(Event e) {
191208
selectType();
192209
}
193210
});
194211

212+
195213
String labelText = null;
196214
IBindingService bindingService = workbench.getAdapter(IBindingService.class);
197215
String binding = bindingService.getBestActiveBindingFormattedFor(IWorkbenchCommandConstants.EDIT_CONTENT_ASSIST);
@@ -281,7 +299,7 @@ private void checkValues() {
281299
status.setError(DebugUIMessages.DetailFormatterDialog_A_detail_formatter_is_already_defined_for_this_type_2);
282300
} else if (fSnippetViewer.getDocument().get().trim().length() == 0) {
283301
status.setError(DebugUIMessages.DetailFormatterDialog_Associated_code_must_not_be_empty_3);
284-
} else if (fType == null && fTypeSearched) {
302+
} else if (fType == null && fTypeSearched && !getPrimitiveTypes().contains(typeName)) {
285303
status.setWarning(DebugUIMessages.No_type_with_the_given_name_found_in_the_workspace__1);
286304
}
287305
updateStatus(status);
@@ -306,15 +324,13 @@ private void selectType() {
306324
Shell shell= getShell();
307325
SelectionDialog dialog= null;
308326
try {
309-
dialog= JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(),
310-
SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText());
327+
dialog = JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(), SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText());
311328
} catch (JavaModelException jme) {
312329
String title= DebugUIMessages.DetailFormatterDialog_Select_type_6;
313330
String message= DebugUIMessages.DetailFormatterDialog_Could_not_open_type_selection_dialog_for_detail_formatters_7;
314331
ExceptionHandler.handle(jme, title, message);
315332
return;
316333
}
317-
318334
dialog.setTitle(DebugUIMessages.DetailFormatterDialog_Select_type_8);
319335
dialog.setMessage(DebugUIMessages.DetailFormatterDialog_Select_a_type_to_format_when_displaying_its_detail_9);
320336
if (dialog.open() == IDialogConstants.CANCEL_ID) {
@@ -329,6 +345,43 @@ private void selectType() {
329345
}
330346
}
331347

348+
/**
349+
* Open the 'select type' dialog, and set the primitive into the formatter.
350+
*/
351+
private void selectPrimitiveType() {
352+
Shell shell = getShell();
353+
ListDialog listDialog = new ListDialog(shell);
354+
listDialog.setTitle(DebugUIMessages.DetailFormatterDialog_Select_type_8);
355+
listDialog.setMessage(DebugUIMessages.DetailFormatterPrimitiveSelectionLabel);
356+
listDialog.setInput(getPrimitiveTypes().toArray());
357+
listDialog.setContentProvider(ArrayContentProvider.getInstance());
358+
listDialog.setLabelProvider(new LabelProvider() {
359+
@Override
360+
public String getText(Object element) {
361+
return (String) element;
362+
}
363+
});
364+
if (listDialog.open() == Window.CANCEL) {
365+
return;
366+
}
367+
Object[] types = listDialog.getResult();
368+
if (types != null && types.length > 0) {
369+
String s = (String) types[0];
370+
fTypeNameText.setText(s);
371+
fTypeSearched = true;
372+
}
373+
}
374+
375+
/**
376+
* Returns a List of available primitives and arrays
377+
*
378+
* @return List primitives and arrays
379+
*/
380+
@SuppressWarnings("nls")
381+
private List<String> getPrimitiveTypes() {
382+
return List.of("int", "long", "short", "float", "double", "boolean", "char", "byte", "int[]", "long[]", "short[]", "float[]", "double[]", "boolean[]", "char[]", "byte[]");
383+
}
384+
332385
/**
333386
* Use the Java search engine to find the type which corresponds
334387
* to the given name.

0 commit comments

Comments
 (0)