Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Primitives in Detail Formatter #586

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are this lines removed intantionally?

Copy link
Contributor Author

@SougandhS SougandhS Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.. to get detail formatter option in variables view

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
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* Copyright (c) 2000, 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 @@ -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 @@ -306,15 +324,13 @@ private void selectType() {
Shell shell= getShell();
SelectionDialog dialog= null;
try {
dialog= JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(),
SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText());
dialog = JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(), 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 +345,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[]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it work with arrays of multiple dimensions? for example char[][]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it works.. added test case for that too

}

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