Skip to content

Commit

Permalink
This commit provides support for Primitive types and Primitive arrays in
Browse files Browse the repository at this point in the history
Detail Formatter for variables view.

Fixes : #268
  • Loading branch information
SougandhS committed Jan 9, 2025
1 parent 78045e3 commit 5fe49cd
Show file tree
Hide file tree
Showing 13 changed files with 551 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ void assert15Project() {
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug329294WithGenerics"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug403028"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug484686"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.primitivesTest"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.GenericMethodEntryTest"));
cfgs.add(createLaunchConfiguration(jp, "org.eclipse.debug.tests.targets.HcrClass", true));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.Bug570988"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,140 @@ public void testHoverWithNoTypeArguments() throws Exception {
removeAllBreakpoints();
}
}

public void testFormatterForPrimitivesInt() throws Exception {
IJavaThread thread = null;
DetailFormatter formatter = null;
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
try {
String typename = "a.b.c.primitivesTest";
createLineBreakpoint(26, typename);
thread = launchToBreakpoint(typename);
assertNotNull("The program did not suspend", thread);
String snippet = "this + 12";
formatter = new DetailFormatter("int", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
IJavaVariable var = thread.findVariable("x");
assertNotNull("the variable 'x' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("24", fListener.result.toString());

snippet = "new String(this)"; // for char arrays formatter = new DetailFormatter("char[]", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
var = thread.findVariable("aCh");
assertNotNull("the variable 'aCh' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("ab", fListener.result.toString());

} finally {
jdfm.removeAssociatedDetailFormatter(formatter);
terminateAndRemove(thread);
removeAllBreakpoints();
}
}

public void testFormatterForPrimitivesfloat() throws Exception {
IJavaThread thread = null;
DetailFormatter formatter = null;
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
try {
String typename = "a.b.c.primitivesTest";
createLineBreakpoint(26, typename);
thread = launchToBreakpoint(typename);
assertNotNull("The program did not suspend", thread);
String snippet = "this + 10";
formatter = new DetailFormatter("float", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
IJavaVariable var = thread.findVariable("f");
assertNotNull("the variable 'f' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("20", fListener.result.toString());
} finally {
jdfm.removeAssociatedDetailFormatter(formatter);
terminateAndRemove(thread);
removeAllBreakpoints();
}
}

public void testFormatterForPrimitivesIntArrays() throws Exception {
IJavaThread thread = null;
DetailFormatter formatter = null;
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
try {
String typename = "a.b.c.primitivesTest";
createLineBreakpoint(26, typename);
thread = launchToBreakpoint(typename);
assertNotNull("The program did not suspend", thread);
String snippet = "this[1]";
formatter = new DetailFormatter("int[]", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
IJavaVariable var = thread.findVariable("arInt");
assertNotNull("the variable 'arInt' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("2", fListener.result.toString());
} finally {
jdfm.removeAssociatedDetailFormatter(formatter);
terminateAndRemove(thread);
removeAllBreakpoints();
}
}

public void testFormatterForPrimitivesIntArraysMulti() throws Exception {
IJavaThread thread = null;
DetailFormatter formatter = null;
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
try {
String typename = "a.b.c.primitivesTest";
createLineBreakpoint(26, typename);
thread = launchToBreakpoint(typename);
assertNotNull("The program did not suspend", thread);
String snippet = "this[0][0]";
formatter = new DetailFormatter("int[][]", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
IJavaVariable var = thread.findVariable("mul");
assertNotNull("the variable 'mul' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("[1]", fListener.result.toString());
} finally {
jdfm.removeAssociatedDetailFormatter(formatter);
terminateAndRemove(thread);
removeAllBreakpoints();
}
}

public void testFormatterForPrimitivesCharArray() throws Exception {
IJavaThread thread = null;
DetailFormatter formatter = null;
JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
try {
String typename = "a.b.c.primitivesTest";
createLineBreakpoint(26, typename);
thread = launchToBreakpoint(typename);
assertNotNull("The program did not suspend", thread);
String snippet = "new String(this)";
formatter = new DetailFormatter("char[]", snippet, true);
jdfm.setAssociatedDetailFormatter(formatter);
IJavaVariable var = thread.findVariable("aCh");
assertNotNull("the variable 'aCh' must exist in the frame", var);
jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
waitForListenerValue();
assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
assertEquals("ab", fListener.result.toString());
} finally {
jdfm.removeAssociatedDetailFormatter(formatter);
terminateAndRemove(thread);
removeAllBreakpoints();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2025 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package a.b.c;

public class primitivesTest {
public static void main(String[] args) {
Double xd = Double.valueOf(1);
int x = 12;
float f = 10;
int[] arInt = { 1, 2, 3 };
char[] aCh = { 'a', 'b' };
boolean b = false;
double[] d = { 1, 3, 4 };
int[][] mul = { { 1, 3, 4 }, { 1, 3, 4 } };
int p1 = 120;
}
}
19 changes: 1 addition & 18 deletions org.eclipse.jdt.debug.ui/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<!--
Copyright (c) 2005, 2022 IBM Corporation and others.
Copyright (c) 2005, 2025 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -745,22 +745,12 @@
id="org.eclipse.jdt.debug.ui.FilteredJavaVariableActions">
<visibility>
<and>
<objectState
name="PrimitiveVariableActionFilter"
value="isValuePrimitive">
</objectState>
<not>
<objectState
name="DetailFormatterFilter"
value="isDefined">
</objectState>
</not>
<not>
<objectState
name="PrimitiveVariableActionFilter"
value="isArray">
</objectState>
</not>
<not>
<objectState
name="JavaVariableFilter"
Expand Down Expand Up @@ -804,15 +794,8 @@
name="DetailFormatterFilter"
value="inSuperclass"/>
</or>
<not>
<objectState
name="PrimitiveVariableActionFilter"
value="isArray">
</objectState>
</not>
</and>
</visibility>

</objectContribution>
<objectContribution
id="org.eclipse.jdt.debug.ui.FilteredJavaVariableActions"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ public class DebugUIMessages extends NLS {
public static String DetailFormatterDialog_Associated_code_must_not_be_empty_3;
public static String DetailFormatterDialog_Detail_formatter__code_snippet__1;
public static String DetailFormatterDialog_17;
public static String DetailFormatterPrimitiveSelect;
public static String DetailFormatterPrimitiveSelectionLabel;

public static String No_type_with_the_given_name_found_in_the_workspace__1;
public static String JavaDetailFormattersManager_Detail_formatter_error___1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ DetailFormatterDialog_Add_Detail_Formatter_2=Add Detail Formatter
DetailFormatterDialog_Associated_code_must_not_be_empty_3=Detail formatter code snippet must not be empty
DetailFormatterDialog_Detail_formatter__code_snippet__1=Detail formatter &code snippet:
DetailFormatterDialog_17=Detail formatter &code snippet ({0} for code assist):
DetailFormatterPrimitiveSelect=Select Primitives
DetailFormatterPrimitiveSelectionLabel=Choose a primitive

No_type_with_the_given_name_found_in_the_workspace__1=No type with the given name found in the workspace.
JavaDetailFormattersManager_Detail_formatter_error___1=Detail formatter error:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
Expand All @@ -67,6 +70,7 @@
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListDialog;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
Expand Down Expand Up @@ -168,11 +172,10 @@ protected Control createDialogArea(Composite parent) {
Font font = parent.getFont();
Composite container = (Composite)super.createDialogArea(parent);

SWTFactory.createLabel(container, DebugUIMessages.DetailFormatterDialog_Qualified_type__name__2, 1);
SWTFactory.createLabel(container, DebugUIMessages.DetailFormatterDialog_Qualified_type__name__2, 2);

Composite innerContainer = SWTFactory.createComposite(container, font, 2, 1, GridData.FILL_HORIZONTAL);

fTypeNameText = SWTFactory.createSingleText(innerContainer, 1);
fTypeNameText = SWTFactory.createSingleText(innerContainer, 2);
fTypeNameText.setEditable(fEditTypeName);
fTypeNameText.setText(fDetailFormatter.getTypeName());
fTypeNameText.addModifyListener(new ModifyListener() {
Expand All @@ -182,16 +185,31 @@ public void modifyText(ModifyEvent e) {
checkValues();
}
});
Button primitiveSearchButton = SWTFactory.createPushButton(innerContainer, DebugUIMessages.DetailFormatterPrimitiveSelect, null);
primitiveSearchButton.setEnabled(fEditTypeName);

GridData gridLayout = new GridData(GridData.FILL_HORIZONTAL);
gridLayout.horizontalSpan = 1;
gridLayout.grabExcessHorizontalSpace = true;
primitiveSearchButton.setLayoutData(gridLayout);
primitiveSearchButton.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
selectPrimitiveType();
}
});

Button typeSearchButton = SWTFactory.createPushButton(innerContainer, DebugUIMessages.DetailFormatterDialog_Select__type_4, null);
typeSearchButton.setEnabled(fEditTypeName);
typeSearchButton.setLayoutData(gridLayout);
typeSearchButton.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
selectType();
}
});


String labelText = null;
IBindingService bindingService = workbench.getAdapter(IBindingService.class);
String binding = bindingService.getBestActiveBindingFormattedFor(IWorkbenchCommandConstants.EDIT_CONTENT_ASSIST);
Expand Down Expand Up @@ -281,7 +299,7 @@ private void checkValues() {
status.setError(DebugUIMessages.DetailFormatterDialog_A_detail_formatter_is_already_defined_for_this_type_2);
} else if (fSnippetViewer.getDocument().get().trim().length() == 0) {
status.setError(DebugUIMessages.DetailFormatterDialog_Associated_code_must_not_be_empty_3);
} else if (fType == null && fTypeSearched) {
} else if (fType == null && fTypeSearched && !getPrimitiveTypes().contains(typeName)) {
status.setWarning(DebugUIMessages.No_type_with_the_given_name_found_in_the_workspace__1);
}
updateStatus(status);
Expand All @@ -307,14 +325,13 @@ private void selectType() {
SelectionDialog dialog= null;
try {
dialog= JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(),
SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText());
SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText());
} catch (JavaModelException jme) {
String title= DebugUIMessages.DetailFormatterDialog_Select_type_6;
String message= DebugUIMessages.DetailFormatterDialog_Could_not_open_type_selection_dialog_for_detail_formatters_7;
ExceptionHandler.handle(jme, title, message);
return;
}

dialog.setTitle(DebugUIMessages.DetailFormatterDialog_Select_type_8);
dialog.setMessage(DebugUIMessages.DetailFormatterDialog_Select_a_type_to_format_when_displaying_its_detail_9);
if (dialog.open() == IDialogConstants.CANCEL_ID) {
Expand All @@ -329,6 +346,43 @@ private void selectType() {
}
}

/**
* Open the 'select type' dialog, and set the primitive into the formatter.
*/
private void selectPrimitiveType() {
Shell shell = getShell();
ListDialog listDialog = new ListDialog(shell);
listDialog.setTitle(DebugUIMessages.DetailFormatterDialog_Select_type_8);
listDialog.setMessage(DebugUIMessages.DetailFormatterPrimitiveSelectionLabel);
listDialog.setInput(getPrimitiveTypes().toArray());
listDialog.setContentProvider(ArrayContentProvider.getInstance());
listDialog.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
return (String) element;
}
});
if (listDialog.open() == Window.CANCEL) {
return;
}
Object[] types = listDialog.getResult();
if (types != null && types.length > 0) {
String s = (String) types[0];
fTypeNameText.setText(s);
fTypeSearched = true;
}
}

/**
* Returns a List of available primitives and arrays
*
* @return List primitives and arrays
*/
@SuppressWarnings("nls")
private List<String> getPrimitiveTypes() {
return List.of("int", "long", "short", "float", "double", "boolean", "char", "byte", "int[]", "long[]", "short[]", "float[]", "double[]", "boolean[]", "char[]", "byte[]");
}

/**
* Use the Java search engine to find the type which corresponds
* to the given name.
Expand Down
Loading

0 comments on commit 5fe49cd

Please sign in to comment.