GP-1445 fixing issue with renaming a datatype that has the same name as a category at the same level

This commit is contained in:
ghidravore
2021-11-15 11:38:19 -05:00
parent 513c9beb9d
commit 9f2679a9f7
6 changed files with 80 additions and 21 deletions

View File

@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +15,6 @@
*/
package ghidra.app.plugin.core.datamgr.actions;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
import ghidra.app.plugin.core.datamgr.tree.*;
import javax.swing.tree.TreePath;
import docking.ActionContext;
@@ -27,6 +22,9 @@ import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.tree.GTree;
import docking.widgets.tree.GTreeNode;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
import ghidra.app.plugin.core.datamgr.tree.*;
public class RenameAction extends DockingAction {
@@ -76,7 +74,7 @@ public class RenameAction extends DockingAction {
void rename(final DataTypeArchiveGTree tree) {
TreePath path = tree.getSelectionPath();
final GTreeNode node = (GTreeNode) path.getLastPathComponent();
tree.startEditing(node.getParent(), node.getName());
tree.startEditing(node);
}
}

View File

@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +15,13 @@
*/
package ghidra.app.plugin.core.symboltree.actions;
import ghidra.app.plugin.core.symboltree.SymbolTreeActionContext;
import ghidra.app.plugin.core.symboltree.SymbolTreePlugin;
import ghidra.app.plugin.core.symboltree.nodes.SymbolNode;
import javax.swing.tree.TreePath;
import docking.action.MenuData;
import docking.widgets.tree.GTreeNode;
import ghidra.app.plugin.core.symboltree.SymbolTreeActionContext;
import ghidra.app.plugin.core.symboltree.SymbolTreePlugin;
import ghidra.app.plugin.core.symboltree.nodes.SymbolNode;
public class RenameAction extends SymbolTreeContextAction {
@@ -47,7 +45,7 @@ public class RenameAction extends SymbolTreeContextAction {
public void actionPerformed(SymbolTreeActionContext context) {
TreePath[] selectionPaths = context.getSelectedSymbolTreePaths();
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
context.getSymbolTree().startEditing(node.getParent(), node.getName());
context.getSymbolTree().startEditing(node);
}
}

View File

@@ -377,6 +377,45 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
assertNotNull(programNode.getChild(newCategoryName));
}
@Test
public void testRenameDataTypeWithSameNameAsCategory() throws Exception {
// select a category
expandNode(programNode);
String miscNodeName = "MISC";
final CategoryNode miscNode = (CategoryNode) programNode.getChild(miscNodeName);
assertNotNull(miscNode);
StructureDataType struct = new StructureDataType("MISC", 0);
struct.add(new DWordDataType());
builder.addDataType(struct);
waitForTree();
DataType resolved = program.getDataTypeManager().resolve(struct, null);
DataTypeNode node = programNode.getNode(resolved);
selectNode(node);
final DockingActionIf action = getAction(plugin, "Rename");
assertTrue(action.isEnabledForContext(treeContext));
// select "Rename" action
final String newDatatypeName = "ItWorked";
DataTypeTestUtils.performAction(action, tree);
waitForTree();
runSwing(() -> {
int rowForPath = jTree.getRowForPath(miscNode.getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, miscNode,
true, true, true, rowForPath);
JTextField textField = (JTextField) container.getComponent(0);
textField.setText(newDatatypeName);
jTree.stopEditing();
});
waitForProgram();
waitForTree();
assertEquals("ItWorked", resolved.getName());
}
@Test
public void testRenameCategoryDuplicate() throws Exception {
expandNode(programNode);

View File

@@ -943,13 +943,12 @@ public class GTree extends JPanel implements BusyListener {
}
/**
* Requests that the node with the given name, in the given parent, be edited. <b>This
* operation (as with many others on this tree) is asynchronous.</b> This request will be
* buffered as needed to wait for the given node to be added to the parent, up to a timeout
* period.
* Requests that the node with the given name, in the given parent, be edited. This
* operation is asynchronous. This request will be buffered as needed to wait for
* the given node to be added to the parent, up to a timeout period.
*
* @param parent the parent node
* @param childName the child node name
* @param childName the name of the child to edit
*/
public void startEditing(GTreeNode parent, final String childName) {
@@ -972,6 +971,21 @@ public class GTree extends JPanel implements BusyListener {
});
}
/**
* Requests that the node be edited. This operation is asynchronous.
*
* @param child the node to edit
*/
public void startEditing(GTreeNode child) {
// we call this here, even though the JTree will do this for us, so that we will trigger
// a load call before this task is run, in case lazy nodes are involved in this tree,
// which must be loaded before we can edit
expandPath(child.getParent());
runTask(new GTreeStartEditingTask(GTree.this, tree, child));
}
@Override
public synchronized void addMouseListener(MouseListener listener) {
mouseListenerDelegate.addMouseListener(listener);

View File

@@ -36,6 +36,7 @@ public class GTreeStartEditingTask extends GTreeTask {
private final GTreeNode parent;
private final String childName;
private GTreeNode editNode;
public GTreeStartEditingTask(GTree gTree, JTree jTree, GTreeNode parent, String childName) {
super(gTree);
@@ -43,6 +44,13 @@ public class GTreeStartEditingTask extends GTreeTask {
this.childName = childName;
}
public GTreeStartEditingTask(GTree gTree, JTree jTree, GTreeNode editNode) {
super(gTree);
this.parent = editNode.getParent();
this.childName = editNode.getName();
this.editNode = editNode;
}
@Override
public void run(final TaskMonitor monitor) throws CancelledException {
runOnSwingThread(() -> {
@@ -66,10 +74,12 @@ public class GTreeStartEditingTask extends GTreeTask {
return;
}
GTreeNode editNode = parent.getChild(childName);
if (editNode == null) {
Msg.debug(this, "Can't find node \"" + childName + "\" to edit.");
return;
editNode = parent.getChild(childName);
if (editNode == null) {
Msg.debug(this, "Can't find node \"" + childName + "\" to edit.");
return;
}
}
TreePath path = editNode.getTreePath();

View File

@@ -66,7 +66,7 @@ public class ProjectDataRenameAction extends FrontendProjectTreeAction {
DataTree tree = (DataTree) component;
GTreeNode node = (GTreeNode) context.getContextObject();
tree.setEditable(true);
tree.startEditing(node.getParent(), node.getName());
tree.startEditing(node);
}
else if (component instanceof GTable) {
GTable table = (GTable) component;