mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-21 19:42:14 +00:00
Merge remote-tracking branch 'origin/GP-4853_dev747368_datatype_select_nodups'
This commit is contained in:
commit
ad86d2d65a
@ -128,8 +128,8 @@ public class DataTypeTableCellEditor extends AbstractCellEditor
|
||||
|
||||
protected void init(int row, int column) {
|
||||
updateService();
|
||||
editor = new DataTypeSelectionEditor(service, getAllowed(row, column));
|
||||
editor.setPreferredDataTypeManager(getPreferredDataTypeManager(row, column));
|
||||
editor = new DataTypeSelectionEditor(getPreferredDataTypeManager(row, column), service,
|
||||
getAllowed(row, column));
|
||||
editor.setTabCommitsEdit(true);
|
||||
editor.setConsumeEnterKeyPress(false);
|
||||
|
||||
|
@ -255,8 +255,8 @@ public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
private JComponent createDataTypeChoiceEditor() {
|
||||
|
||||
dtChoiceEditor =
|
||||
new DataTypeSelectionEditor(dtmService, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||
dtChoiceEditor = new DataTypeSelectionEditor(composite.getDataTypeManager(), dtmService,
|
||||
AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
||||
dtChoiceEditor.setTabCommitsEdit(true);
|
||||
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
||||
|
@ -1201,13 +1201,12 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||
private void init() {
|
||||
|
||||
Plugin plugin = provider.getPlugin();
|
||||
final PluginTool tool = plugin.getTool();
|
||||
editor = new DataTypeSelectionEditor(tool,
|
||||
bitfieldAllowed ? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
||||
PluginTool tool = plugin.getTool();
|
||||
editor = new DataTypeSelectionEditor(model.getViewDataTypeManager(), tool,
|
||||
bitfieldAllowed
|
||||
? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
||||
: AllowedDataTypes.SIZABLE_DYNAMIC);
|
||||
editor.setTabCommitsEdit(true);
|
||||
DataTypeManager originalDataTypeManager = model.getOriginalDataTypeManager();
|
||||
editor.setPreferredDataTypeManager(originalDataTypeManager);
|
||||
editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses
|
||||
|
||||
textField = editor.getDropDownTextField();
|
||||
|
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.datamgr.actions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CellEditorListener;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
@ -56,6 +59,11 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
||||
}
|
||||
|
||||
private JComponent createWorkPanel() {
|
||||
List<DataTypeManager> managers = Arrays.stream(plugin.getDataTypeManagers())
|
||||
.filter(dtm -> !(dtm instanceof BuiltInDataTypeManager))
|
||||
.toList();
|
||||
DataTypeManager defaultDTM = getDefaultDataTypeManager(managers);
|
||||
|
||||
JPanel panel = new JPanel(new PairLayout());
|
||||
|
||||
// category info
|
||||
@ -68,7 +76,9 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
||||
panel.add(nameTextField);
|
||||
|
||||
// data type info
|
||||
dataTypeEditor = new DataTypeSelectionEditor(plugin.getTool(), AllowedDataTypes.ALL);
|
||||
dataTypeEditor = new DataTypeSelectionEditor(
|
||||
null, /* TODO: can't set default dtm for the data type selection field because the dialog allows switching between destination DTMs */
|
||||
plugin.getTool(), AllowedDataTypes.ALL);
|
||||
panel.add(new GLabel("Data type:"));
|
||||
panel.add(dataTypeEditor.getEditorComponent());
|
||||
|
||||
@ -89,29 +99,8 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
||||
dataTypeManagerBox = new GhidraComboBox<>();
|
||||
dataTypeManagerBox
|
||||
.setRenderer(GComboBoxCellRenderer.createDefaultTextRenderer(dtm -> dtm.getName()));
|
||||
|
||||
DataTypeManager[] dataTypeManagers = plugin.getDataTypeManagers();
|
||||
for (DataTypeManager manager : dataTypeManagers) {
|
||||
if (manager instanceof BuiltInDataTypeManager) {
|
||||
continue; // can't add to built-in
|
||||
}
|
||||
dataTypeManagerBox.addToModel(manager);
|
||||
}
|
||||
|
||||
Object itemToSelect = null;
|
||||
|
||||
// select the manager from where the dialog was created
|
||||
Object lastPathComponent = selectedTreePath.getLastPathComponent();
|
||||
if (lastPathComponent instanceof DataTypeTreeNode) {
|
||||
DataTypeTreeNode dataTypeTreeNode = (DataTypeTreeNode) lastPathComponent;
|
||||
ArchiveNode archiveNode = dataTypeTreeNode.getArchiveNode();
|
||||
DataTypeManager manager = archiveNode.getArchive().getDataTypeManager();
|
||||
if (dataTypeManagerBox.containsItem(manager)) {
|
||||
itemToSelect = manager;
|
||||
}
|
||||
}
|
||||
|
||||
dataTypeManagerBox.setSelectedItem(itemToSelect);
|
||||
dataTypeManagerBox.addToModel(managers);
|
||||
dataTypeManagerBox.setSelectedItem(defaultDTM);
|
||||
|
||||
panel.add(new GLabel("Archive:"));
|
||||
panel.add(dataTypeManagerBox);
|
||||
@ -121,6 +110,19 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
||||
return panel;
|
||||
}
|
||||
|
||||
private DataTypeManager getDefaultDataTypeManager(List<DataTypeManager> mgrs) {
|
||||
// select the manager from where the dialog was created
|
||||
Object lastPathComponent = selectedTreePath.getLastPathComponent();
|
||||
if (lastPathComponent instanceof DataTypeTreeNode dataTypeTreeNode) {
|
||||
ArchiveNode archiveNode = dataTypeTreeNode.getArchiveNode();
|
||||
DataTypeManager manager = archiveNode.getArchive().getDataTypeManager();
|
||||
if (mgrs.contains(manager)) {
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void okCallback() {
|
||||
// are we valid?
|
||||
|
@ -759,8 +759,8 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod
|
||||
getSelectionModel().addListSelectionListener(selectionListener);
|
||||
// set the preferred viewport height smaller that the button panel, otherwise it is huge!
|
||||
setPreferredScrollableViewportSize(new Dimension(600, 100));
|
||||
setDefaultEditor(DataType.class,
|
||||
new ParameterDataTypeCellEditor(FunctionEditorDialog.this, service));
|
||||
setDefaultEditor(DataType.class, new ParameterDataTypeCellEditor(
|
||||
FunctionEditorDialog.this, service, model.getProgram().getDataTypeManager()));
|
||||
setDefaultRenderer(DataType.class, new ParameterDataTypeCellRenderer());
|
||||
setDefaultEditor(VariableStorage.class, new StorageTableCellEditor(model));
|
||||
setDefaultRenderer(VariableStorage.class, new VariableStorageCellRenderer());
|
||||
|
@ -30,6 +30,7 @@ import docking.widgets.table.FocusableEditor;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.util.MessageType;
|
||||
import ghidra.util.data.DataTypeParser;
|
||||
|
||||
@ -43,27 +44,29 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor
|
||||
private JPanel editorPanel;
|
||||
private DataTypeManagerService service;
|
||||
private DialogComponentProvider dialog;
|
||||
private DataTypeManager dtm;
|
||||
|
||||
ParameterDataTypeCellEditor(DialogComponentProvider dialog, DataTypeManagerService service) {
|
||||
ParameterDataTypeCellEditor(DialogComponentProvider dialog, DataTypeManagerService service,
|
||||
DataTypeManager dtm) {
|
||||
this.dialog = dialog;
|
||||
this.service = service;
|
||||
|
||||
this.dtm = dtm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(JTable table1, Object value, boolean isSelected,
|
||||
int row, int column) {
|
||||
init();
|
||||
|
||||
dt = (DataType) value;
|
||||
|
||||
init();
|
||||
|
||||
editor.setCellEditorValue(dt);
|
||||
|
||||
return editorPanel;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
editor = new DataTypeSelectionEditor(service, DataTypeParser.AllowedDataTypes.ALL);
|
||||
editor = new DataTypeSelectionEditor(dtm, service, DataTypeParser.AllowedDataTypes.ALL);
|
||||
editor.setTabCommitsEdit(true);
|
||||
editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses
|
||||
|
||||
|
@ -172,7 +172,8 @@ public class StorageAddressEditorDialog extends DialogComponentProvider
|
||||
|
||||
panel.add(new GLabel("Datatype: "));
|
||||
|
||||
dataTypeEditor = new ParameterDataTypeCellEditor(this, service);
|
||||
dataTypeEditor =
|
||||
new ParameterDataTypeCellEditor(this, service, model.getProgram().getDataTypeManager());
|
||||
|
||||
dataTypeEditor.addCellEditorListener(new CellEditorListener() {
|
||||
|
||||
|
@ -23,11 +23,14 @@ import javax.swing.*;
|
||||
import docking.widgets.DropDownSelectionTextField;
|
||||
import docking.widgets.DropDownTextFieldDataModel;
|
||||
import docking.widgets.list.GListCellRenderer;
|
||||
import ghidra.app.plugin.core.compositeeditor.CompositeViewerDataTypeManager;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.ToolTipUtils;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.UniversalID;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
@ -36,13 +39,25 @@ import ghidra.util.exception.AssertException;
|
||||
*/
|
||||
public class DataTypeDropDownSelectionDataModel implements DropDownTextFieldDataModel<DataType> {
|
||||
|
||||
private final DataTypeManager dtm; // preferred data type manager
|
||||
private final DataTypeManagerService dataTypeService;
|
||||
|
||||
public DataTypeDropDownSelectionDataModel(ServiceProvider serviceProvider) {
|
||||
this.dtm = null;
|
||||
this.dataTypeService = getDataTypeService(serviceProvider);
|
||||
}
|
||||
|
||||
public DataTypeDropDownSelectionDataModel(DataTypeManagerService dataTypeService) {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param dtm the preferred {@link DataTypeManager}. Data types that are found in multiple
|
||||
* data type managers will be pruned to just the ones already in the preferred data type
|
||||
* manager.
|
||||
* @param dataTypeService {@link DataTypeManagerService}
|
||||
*/
|
||||
public DataTypeDropDownSelectionDataModel(DataTypeManager dtm,
|
||||
DataTypeManagerService dataTypeService) {
|
||||
this.dtm = dtm;
|
||||
this.dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
@ -84,16 +99,57 @@ public class DataTypeDropDownSelectionDataModel implements DropDownTextFieldData
|
||||
* Remove any unwanted data type items, like arrays.
|
||||
*/
|
||||
private List<DataType> filterDataTypeList(List<DataType> dataTypeList) {
|
||||
List<DataType> matchingList = new ArrayList<>(dataTypeList.size());
|
||||
for (DataType dataType : dataTypeList) {
|
||||
if (!(dataType instanceof Array)) {
|
||||
matchingList.add(dataType);
|
||||
// build lookups for data types that are in the preferred dtm, but may have come from
|
||||
// another DTM. In the second step, duplicate data types will be omitted from the
|
||||
// final results, in favor of the data type that is already in the preferred dtm.
|
||||
Set<UniversalID> preferredUIDs = new HashSet<>();
|
||||
Set<Class<?>> preferredBuiltins = new HashSet<>();
|
||||
for (DataType dt : dataTypeList) {
|
||||
DataType baseDT = DataTypeUtilities.getBaseDataType(dt);
|
||||
if (isFromPreferredDTM(baseDT)) {
|
||||
if (baseDT instanceof BuiltInDataType) {
|
||||
preferredBuiltins.add(baseDT.getClass());
|
||||
}
|
||||
else if (baseDT.getUniversalID() != null) {
|
||||
preferredUIDs.add(baseDT.getUniversalID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DataType> matchingList = new ArrayList<>(dataTypeList.size());
|
||||
for (DataType dataType : dataTypeList) {
|
||||
if (dataType instanceof Array) {
|
||||
continue;
|
||||
}
|
||||
DataType baseDT = DataTypeUtilities.getBaseDataType(dataType);
|
||||
if (dtm != null && !isFromPreferredDTM(baseDT)) {
|
||||
if (baseDT instanceof BuiltInDataType &&
|
||||
preferredBuiltins.contains(baseDT.getClass())) {
|
||||
continue;
|
||||
}
|
||||
if (baseDT.getUniversalID() != null &&
|
||||
preferredUIDs.contains(baseDT.getUniversalID())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
matchingList.add(dataType);
|
||||
}
|
||||
|
||||
return matchingList;
|
||||
}
|
||||
|
||||
private boolean isFromPreferredDTM(DataType dt) {
|
||||
if (dtm != null) {
|
||||
DataTypeManager altDTM = dtm instanceof CompositeViewerDataTypeManager compDTM
|
||||
? compDTM.getOriginalDataTypeManager()
|
||||
: null;
|
||||
DataTypeManager dtDTM = dt.getDataTypeManager();
|
||||
return dtDTM == dtm || dtDTM == altDTM;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfFirstMatchingEntry(List<DataType> data, String text) {
|
||||
|
||||
|
@ -66,7 +66,6 @@ public class DataTypeSelectionDialog extends DialogComponentProvider {
|
||||
removeWorkPanel();
|
||||
|
||||
editor = createEditor(pluginTool, allowedTypes);
|
||||
editor.setPreferredDataTypeManager(dtm);
|
||||
editor.setConsumeEnterKeyPress(false); // we want to handle Enter key presses
|
||||
editor.addCellEditorListener(new CellEditorListener() {
|
||||
@Override
|
||||
@ -110,7 +109,7 @@ public class DataTypeSelectionDialog extends DialogComponentProvider {
|
||||
|
||||
protected DataTypeSelectionEditor createEditor(PluginTool tool,
|
||||
AllowedDataTypes allowedDataTypes) {
|
||||
return new DataTypeSelectionEditor(tool, allowedDataTypes);
|
||||
return new DataTypeSelectionEditor(dtm, tool, allowedDataTypes);
|
||||
}
|
||||
|
||||
protected JComponent createEditorPanel(DataTypeSelectionEditor dtEditor) {
|
||||
|
@ -29,6 +29,7 @@ import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.data.DataTypeParser;
|
||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
||||
/**
|
||||
@ -68,14 +69,34 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||
// optional path to initially select in the data type chooser tree
|
||||
private TreePath initiallySelectedTreePath;
|
||||
|
||||
public DataTypeSelectionEditor(ServiceProvider serviceProvider,
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param dtm the preferred {@link DataTypeManager}. Extra copies of data types that are
|
||||
* already in the preferred DTM will be suppressed.
|
||||
* @param serviceProvider {@link ServiceProvider}
|
||||
* @param allowedDataTypes {@link AllowedDataTypes} option enum, controls what kind of
|
||||
* data types that will be shown
|
||||
*/
|
||||
public DataTypeSelectionEditor(DataTypeManager dtm, ServiceProvider serviceProvider,
|
||||
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
||||
this(serviceProvider.getService(DataTypeManagerService.class), allowedDataTypes);
|
||||
this(dtm, serviceProvider.getService(DataTypeManagerService.class), allowedDataTypes);
|
||||
}
|
||||
|
||||
public DataTypeSelectionEditor(DataTypeManagerService service,
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param dtm the preferred {@link DataTypeManager}. Extra copies of data types that are
|
||||
* already in the preferred DTM will be suppressed.
|
||||
* @param service {@link DataTypeManagerService}
|
||||
* @param allowedDataTypes {@link AllowedDataTypes} option enum, controls what kind of
|
||||
* data types that will be shown
|
||||
*/
|
||||
public DataTypeSelectionEditor(DataTypeManager dtm, DataTypeManagerService service,
|
||||
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
||||
|
||||
this.dataTypeManager = dtm;
|
||||
|
||||
if (service == null) {
|
||||
throw new NullPointerException("DataTypeManagerService cannot be null");
|
||||
}
|
||||
@ -86,19 +107,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link DataTypeManager} to use when the chooser is forced to parse the given
|
||||
* data type text to resolve the data type. If the users chooses a type, then this value
|
||||
* is not used. Note that setting this value does not restrict the parser to just the
|
||||
* given value, but rather the given value is the preferred manager and is thus searched
|
||||
* first.
|
||||
*
|
||||
* @param dataTypeManager the preferred data type manager
|
||||
*/
|
||||
public void setPreferredDataTypeManager(DataTypeManager dataTypeManager) {
|
||||
this.dataTypeManager = dataTypeManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this editor should consumer Enter key presses
|
||||
* @see DropDownSelectionTextField#setConsumeEnterKeyPress(boolean)
|
||||
@ -116,7 +124,7 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||
|
||||
private void init() {
|
||||
selectionField = createDropDownSelectionTextField(
|
||||
new DataTypeDropDownSelectionDataModel(dataTypeManagerService));
|
||||
new DataTypeDropDownSelectionDataModel(dataTypeManager, dataTypeManagerService));
|
||||
selectionField.addCellEditorListener(new CellEditorListener() {
|
||||
@Override
|
||||
public void editingCanceled(ChangeEvent e) {
|
||||
|
@ -125,7 +125,7 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
||||
@Override
|
||||
protected DataTypeSelectionEditor createEditor(PluginTool pluginTool,
|
||||
AllowedDataTypes allowedDataTypes) {
|
||||
return new DataTypeSelectionEditor(pluginTool, allowedDataTypes) {
|
||||
return new DataTypeSelectionEditor(null, pluginTool, allowedDataTypes) {
|
||||
|
||||
@Override
|
||||
protected DropDownSelectionTextField<DataType> createDropDownSelectionTextField(
|
||||
@ -1207,8 +1207,8 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
||||
new DefaultHighlighter.DefaultHighlightPainter(Palette.YELLOW));
|
||||
|
||||
JPanel editorPanel = new JPanel(new BorderLayout());
|
||||
DataTypeSelectionEditor editor = new DataTypeSelectionEditor(tool, AllowedDataTypes.ALL);
|
||||
editor.setPreferredDataTypeManager(program.getDataTypeManager());
|
||||
DataTypeSelectionEditor editor =
|
||||
new DataTypeSelectionEditor(program.getDataTypeManager(), tool, AllowedDataTypes.ALL);
|
||||
|
||||
editorPanel.add(panelUpdateField, BorderLayout.SOUTH);
|
||||
editorPanel.add(editor.getEditorComponent(), BorderLayout.NORTH);
|
||||
|
Loading…
Reference in New Issue
Block a user