mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 13:42:06 +00:00
Merge remote-tracking branch 'origin/GT-3222-dragonmacher-dt-history-issue'
This commit is contained in:
commit
90854a01a6
@ -205,9 +205,9 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Add project pathname to recently opened list.
|
||||
* @param projectName
|
||||
* @param pathname
|
||||
* Add project archive name to recently opened list
|
||||
* @param projectName the project name
|
||||
* @param pathname the pathname
|
||||
*/
|
||||
public void addRecentlyOpenedProjectArchive(String projectName, String pathname) {
|
||||
String projectPathname = DataTypeManagerHandler.getProjectPathname(projectName, pathname);
|
||||
@ -239,8 +239,8 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||
|
||||
/**
|
||||
* Get a project archive file by project name and pathname
|
||||
* @param projectName
|
||||
* @param pathname
|
||||
* @param projectName the project name
|
||||
* @param pathname the project pathname
|
||||
* @return project archive domain file or null if it does not exist
|
||||
* or can not be found (e.g., projectName is not the active project)
|
||||
*/
|
||||
@ -272,10 +272,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||
dataTypeManagerHandler.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the Plugin to read its data-independant (preferences)
|
||||
* properties from the input stream.
|
||||
*/
|
||||
@Override
|
||||
public void readConfigState(SaveState saveState) {
|
||||
dataTypeManagerHandler.restore(saveState);
|
||||
@ -311,10 +307,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||
dataTypePropertyManager.programClosed(program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Program was opened.
|
||||
* @param program
|
||||
*/
|
||||
@Override
|
||||
protected void programActivated(Program program) {
|
||||
program.addListener(this);
|
||||
@ -574,7 +566,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||
openDialog.addOkActionListener(listener);
|
||||
}
|
||||
tool.showDialog(openDialog);
|
||||
// updateActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,7 +42,7 @@ import ghidra.app.plugin.core.datamgr.archive.*;
|
||||
import ghidra.app.plugin.core.datamgr.tree.*;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.util.ToolTipUtils;
|
||||
import ghidra.app.util.datatype.DataTypeIdUrl;
|
||||
import ghidra.app.util.datatype.DataTypeUrl;
|
||||
import ghidra.framework.main.datatree.ArchiveProvider;
|
||||
import ghidra.framework.main.datatree.VersionControlDataTypeArchiveUndoCheckoutAction;
|
||||
import ghidra.framework.main.projectdata.actions.*;
|
||||
@ -83,7 +83,8 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
private HelpLocation helpLocation;
|
||||
private DataTypeManagerPlugin plugin;
|
||||
|
||||
private HistoryList<DataType> navigationHistory = new HistoryList<>(15, dt -> {
|
||||
private HistoryList<DataTypeUrl> navigationHistory = new HistoryList<>(15, url -> {
|
||||
DataType dt = url.getDataType(plugin);
|
||||
setDataTypeSelected(dt);
|
||||
});
|
||||
private MultiActionDockingAction nextAction;
|
||||
@ -462,39 +463,16 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
private DataType locateDataType(HyperlinkEvent event) {
|
||||
String href = event.getDescription();
|
||||
|
||||
DataTypeIdUrl url = null;
|
||||
DataTypeUrl url = null;
|
||||
try {
|
||||
url = new DataTypeIdUrl(href);
|
||||
url = new DataTypeUrl(href);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
Msg.debug(this, "Could not parse Data Type ID URL '" + href + "'");
|
||||
catch (IllegalArgumentException e) {
|
||||
Msg.debug(this, "Could not parse Data Type URL '" + href + "'", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
DataTypeManager manager = getManager(url);
|
||||
if (manager == null) {
|
||||
// this shouldn't be possible, unless the url is old and the manager has been closed
|
||||
Msg.debug(this, "Could not find data type for " + event.getDescription());
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType dt = manager.findDataTypeForID(url.getDataTypeId());
|
||||
return dt;
|
||||
}
|
||||
|
||||
private DataTypeManager getManager(DataTypeIdUrl url) {
|
||||
UniversalID id = url.getDataTypeManagerId();
|
||||
return getManager(id);
|
||||
}
|
||||
|
||||
private DataTypeManager getManager(UniversalID id) {
|
||||
DataTypeManager[] mgs = plugin.getDataTypeManagers();
|
||||
for (DataTypeManager dtm : mgs) {
|
||||
if (dtm.getUniversalID().equals(id)) {
|
||||
return dtm;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return url.getDataType(plugin);
|
||||
}
|
||||
|
||||
private void updatePreviewPane() {
|
||||
@ -551,6 +529,7 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
void dispose() {
|
||||
previewUpdateManager.dispose();
|
||||
archiveGTree.dispose();
|
||||
navigationHistory.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -862,6 +841,10 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
return conflictMode.getHandler();
|
||||
}
|
||||
|
||||
DataTypeManagerPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
private DataType getDataTypeFrom(TreePath path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
@ -877,7 +860,7 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
return dt;
|
||||
}
|
||||
|
||||
HistoryList<DataType> getNavigationHistory() {
|
||||
HistoryList<DataTypeUrl> getNavigationHistory() {
|
||||
return navigationHistory;
|
||||
}
|
||||
|
||||
@ -899,7 +882,12 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||
return; // Ignore events from the GTree's housekeeping
|
||||
}
|
||||
|
||||
navigationHistory.add(dt);
|
||||
// the data type is null when a non-data type node is selected, like a category node
|
||||
if (dt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigationHistory.add(new DataTypeUrl(dt));
|
||||
contextChanged();
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import javax.swing.Icon;
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import docking.menu.MultiActionDockingAction;
|
||||
import ghidra.app.util.datatype.DataTypeUrl;
|
||||
import ghidra.base.actions.HorizontalRuleAction;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
@ -38,7 +39,7 @@ class NextPreviousDataTypeAction extends MultiActionDockingAction {
|
||||
private boolean isNext;
|
||||
private String owner;
|
||||
private DataTypesProvider provider;
|
||||
private HistoryList<DataType> history;
|
||||
private HistoryList<DataTypeUrl> history;
|
||||
|
||||
public NextPreviousDataTypeAction(DataTypesProvider provider, String owner, boolean isNext) {
|
||||
super(isNext ? "Next Data Type in History" : "Previous Data Type in History", owner);
|
||||
@ -65,22 +66,17 @@ class NextPreviousDataTypeAction extends MultiActionDockingAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
if (isNext) {
|
||||
history.goForward();
|
||||
}
|
||||
else {
|
||||
history.goBack();
|
||||
}
|
||||
// rely on the individual actions to navigate, as they know them item that is being
|
||||
// navigated to, allowing them to skip through the list
|
||||
List<DockingActionIf> actions = getActionList(context);
|
||||
DockingActionIf action = actions.get(0);
|
||||
action.actionPerformed(context);
|
||||
provider.contextChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
|
||||
if (isNext) {
|
||||
return history.hasNext();
|
||||
}
|
||||
return history.hasPrevious();
|
||||
return !getActionList(context).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,19 +88,25 @@ class NextPreviousDataTypeAction extends MultiActionDockingAction {
|
||||
|
||||
DataTypeManager lastDtm = null;
|
||||
List<DockingActionIf> results = new ArrayList<>();
|
||||
List<DataType> types =
|
||||
List<DataTypeUrl> types =
|
||||
isNext ? history.getNextHistoryItems() : history.getPreviousHistoryItems();
|
||||
|
||||
for (DataType dt : types) {
|
||||
for (DataTypeUrl url : types) {
|
||||
|
||||
DataType dt = url.getDataType(provider.getPlugin());
|
||||
if (dt == null) {
|
||||
// The type may have been removed; maybe an undo happened. Leave the item in
|
||||
// the list in case a redo is performed
|
||||
continue;
|
||||
}
|
||||
|
||||
DataTypeManager dtm = dt.getDataTypeManager();
|
||||
|
||||
if (dtm != lastDtm && !results.isEmpty()) {
|
||||
// add a separator to show the user they are navigating across managers
|
||||
results.add(createHorizontalRule(lastDtm, dtm));
|
||||
}
|
||||
|
||||
results.add(new NavigationAction(dt));
|
||||
results.add(new NavigationAction(url, dt));
|
||||
lastDtm = dtm;
|
||||
}
|
||||
|
||||
@ -122,8 +124,11 @@ class NextPreviousDataTypeAction extends MultiActionDockingAction {
|
||||
|
||||
private class NavigationAction extends DockingAction {
|
||||
|
||||
private NavigationAction(DataType dt) {
|
||||
private DataTypeUrl url;
|
||||
|
||||
private NavigationAction(DataTypeUrl url, DataType dt) {
|
||||
super("DataTypeNavigationAction_" + ++navigationActionIdCount, owner);
|
||||
this.url = url;
|
||||
|
||||
setMenuBarData(new MenuData(new String[] { dt.getDisplayName() }));
|
||||
setEnabled(true);
|
||||
@ -132,11 +137,15 @@ class NextPreviousDataTypeAction extends MultiActionDockingAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
|
||||
// note: we use 'goBackTo()' and 'goForwardTo()' since items in the history list
|
||||
// may not have been added to the multi-action; we have to tell the list
|
||||
// to skip those items.
|
||||
if (isNext) {
|
||||
history.goForward();
|
||||
history.goForwardTo(url);
|
||||
}
|
||||
else {
|
||||
history.goBack();
|
||||
history.goBackTo(url);
|
||||
}
|
||||
provider.contextChanged();
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ public class ArchiveNode extends CategoryNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
CategoryNode node = findCategoryNode(parentCategory);
|
||||
CategoryNode node = findCategoryNode(parentCategory, loadChildren);
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.datatype;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.UniversalID;
|
||||
|
||||
/**
|
||||
* A class to produce and parse URLs of the form:
|
||||
* <pre>
|
||||
* datatype:/12345678/12345678
|
||||
* </pre>
|
||||
* where the first number is the ID of the {@link DataTypeManager} and the second number is
|
||||
* the {@link DataType} ID.
|
||||
*/
|
||||
public class DataTypeIdUrl {
|
||||
|
||||
private static String PROTOCOL = "datatype";
|
||||
private static Pattern URL_PATTERN = Pattern.compile(PROTOCOL + ":/(\\d+)/(\\d+)");
|
||||
|
||||
private UniversalID dataTypeManagerId;
|
||||
private UniversalID dataTypeId;
|
||||
|
||||
public DataTypeIdUrl(DataType dt) {
|
||||
DataTypeManager dtm = dt.getDataTypeManager();
|
||||
if (dtm == null) {
|
||||
Msg.debug(this, "");
|
||||
}
|
||||
dataTypeManagerId = dtm.getUniversalID();
|
||||
dataTypeId = dt.getUniversalID();
|
||||
}
|
||||
|
||||
public DataTypeIdUrl(String url) {
|
||||
|
||||
Matcher matcher = URL_PATTERN.matcher(url);
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalArgumentException("Invalid data type URL '" + url + "'");
|
||||
}
|
||||
|
||||
String dtmId = matcher.group(1);
|
||||
String dtId = matcher.group(2);
|
||||
dataTypeManagerId = new UniversalID(Long.parseLong(dtmId));
|
||||
dataTypeId = new UniversalID(Long.parseLong(dtId));
|
||||
}
|
||||
|
||||
public UniversalID getDataTypeManagerId() {
|
||||
return dataTypeManagerId;
|
||||
}
|
||||
|
||||
public UniversalID getDataTypeId() {
|
||||
return dataTypeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return PROTOCOL + ":/" + dataTypeManagerId.toString() + '/' + dataTypeId.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.datatype;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.UniversalID;
|
||||
|
||||
/**
|
||||
* A class to produce and parse URLs of the form:
|
||||
* <pre>
|
||||
* datatype:/12345678?uid=12345678&name=Bob
|
||||
* </pre>
|
||||
* where the first number is the ID of the {@link DataTypeManager} and the second number is
|
||||
* the {@link DataType} ID.
|
||||
*/
|
||||
public class DataTypeUrl {
|
||||
|
||||
// see javadoc for format
|
||||
private static String PROTOCOL = "datatype";
|
||||
private static Pattern URL_PATTERN =
|
||||
Pattern.compile(PROTOCOL + ":/(\\d+)\\?uid=(\\d*)&name=(\\w+)");
|
||||
|
||||
private UniversalID dataTypeManagerId;
|
||||
private UniversalID dataTypeId;
|
||||
private String dataTypeName;
|
||||
|
||||
/**
|
||||
* Constructs a url from the given data type
|
||||
* @param dt the data type; cannot be null
|
||||
*/
|
||||
public DataTypeUrl(DataType dt) {
|
||||
DataTypeManager dtm = dt.getDataTypeManager();
|
||||
dataTypeManagerId = Objects.requireNonNull(dtm.getUniversalID());
|
||||
dataTypeId = dt.getUniversalID();
|
||||
dataTypeName = Objects.requireNonNull(dt.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a url from the given url string
|
||||
*
|
||||
* @param url the url
|
||||
* @throws IllegalArgumentException if the url does not match the expected {@link #URL_PATTERN}
|
||||
* or if there is an issue parsing the id within the given url
|
||||
*/
|
||||
public DataTypeUrl(String url) throws IllegalArgumentException {
|
||||
|
||||
Matcher matcher = URL_PATTERN.matcher(url);
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalArgumentException("Invalid data type URL '" + url + "'");
|
||||
}
|
||||
|
||||
String dtmId = matcher.group(1);
|
||||
String dtId = matcher.group(2);
|
||||
dataTypeName = matcher.group(3);
|
||||
|
||||
dataTypeManagerId = new UniversalID(Long.parseLong(dtmId));
|
||||
|
||||
if (!dtId.isBlank()) {
|
||||
dataTypeId = new UniversalID(Long.parseLong(dtId));
|
||||
}
|
||||
}
|
||||
|
||||
public UniversalID getDataTypeManagerId() {
|
||||
return dataTypeManagerId;
|
||||
}
|
||||
|
||||
public UniversalID getDataTypeId() {
|
||||
return dataTypeId;
|
||||
}
|
||||
|
||||
public String getDataTypeName() {
|
||||
return dataTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the given service and its {@link DataTypeManager}s to find the data type
|
||||
* represented by this url
|
||||
*
|
||||
* @param service the service
|
||||
* @return the data type; null if there was an error restoring the type, such as if the
|
||||
* parent {@link DataTypeManager} has been closed
|
||||
*/
|
||||
public DataType getDataType(DataTypeManagerService service) {
|
||||
|
||||
DataTypeManager manager = findManager(service);
|
||||
if (manager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dataTypeId == null) {
|
||||
// The ID will be null for built-in types. In that case, the name will not be
|
||||
// null. Further, built-in types live at the root, so we can just ask for the
|
||||
// type by name.
|
||||
return manager.getDataType(new DataTypePath(CategoryPath.ROOT, dataTypeName));
|
||||
}
|
||||
|
||||
DataType dt = manager.findDataTypeForID(dataTypeId);
|
||||
return dt;
|
||||
}
|
||||
|
||||
private DataTypeManager findManager(DataTypeManagerService service) {
|
||||
return getManagerById(service);
|
||||
}
|
||||
|
||||
private DataTypeManager getManagerById(DataTypeManagerService service) {
|
||||
DataTypeManager[] mgs = service.getDataTypeManagers();
|
||||
for (DataTypeManager dtm : mgs) {
|
||||
if (dtm.getUniversalID().equals(dataTypeManagerId)) {
|
||||
return dtm;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dataTypeId == null) ? 0 : dataTypeId.hashCode());
|
||||
result = prime * result + ((dataTypeManagerId == null) ? 0 : dataTypeManagerId.hashCode());
|
||||
result = prime * result + ((dataTypeName == null) ? 0 : dataTypeName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DataTypeUrl other = (DataTypeUrl) obj;
|
||||
if (!Objects.equals(dataTypeId, other.dataTypeId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(dataTypeManagerId, other.dataTypeManagerId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(dataTypeName, other.dataTypeName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return PROTOCOL + ":/" + dataTypeManagerId.toString() + "?uid=" +
|
||||
Objects.toString(dataTypeId, "") + "&name=" + dataTypeName;
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ import static ghidra.util.HTMLUtilities.friendlyEncodeHTML;
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.datatype.DataTypeIdUrl;
|
||||
import ghidra.app.util.datatype.DataTypeUrl;
|
||||
import ghidra.app.util.html.diff.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
@ -283,7 +283,7 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
|
||||
// Markup the name with info for later hyperlink capability, as needed by the client
|
||||
//
|
||||
DataType dt = line.getDataType();
|
||||
DataTypeIdUrl url = new DataTypeIdUrl(dt);
|
||||
DataTypeUrl url = new DataTypeUrl(dt);
|
||||
String wrapped = HTMLUtilities.wrapWithLinkPlaceholder(type, url.toString());
|
||||
return wrapped;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package ghidra.app.util.html;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.datatype.DataTypeIdUrl;
|
||||
import ghidra.app.util.datatype.DataTypeUrl;
|
||||
import ghidra.app.util.html.diff.DataTypeDiff;
|
||||
import ghidra.app.util.html.diff.DataTypeDiffBuilder;
|
||||
import ghidra.program.model.data.*;
|
||||
@ -185,7 +185,7 @@ public class FunctionDataTypeHTMLRepresentation extends HTMLDataTypeRepresentati
|
||||
// Markup the name with info for later hyperlink capability, as needed by the client
|
||||
//
|
||||
DataType dataType = line.getDataType();
|
||||
DataTypeIdUrl url = new DataTypeIdUrl(dataType);
|
||||
DataTypeUrl url = new DataTypeUrl(dataType);
|
||||
String wrapped = HTMLUtilities.wrapWithLinkPlaceholder(type, url.toString());
|
||||
return wrapped;
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@ -39,10 +40,6 @@ import docking.action.DockingActionIf;
|
||||
import docking.action.ToggleDockingActionIf;
|
||||
import docking.actions.KeyBindingUtils;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.combobox.GhidraComboBox;
|
||||
import docking.widgets.dialogs.InputWithChoicesDialog;
|
||||
import docking.widgets.fieldpanel.support.Highlight;
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
import docking.widgets.tree.GTreeNode;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
import ghidra.app.plugin.core.datamgr.actions.CreateTypeDefDialog;
|
||||
@ -50,23 +47,15 @@ import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
|
||||
import ghidra.app.plugin.core.datamgr.tree.*;
|
||||
import ghidra.app.plugin.core.function.EditFunctionSignatureDialog;
|
||||
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesPlugin;
|
||||
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesProvider;
|
||||
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
||||
import ghidra.app.services.CodeViewerService;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.app.util.HighlightProvider;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||
import ghidra.app.util.viewer.field.*;
|
||||
import ghidra.app.util.viewer.format.FormatManager;
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.data.ProgramDataTypeManager;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.test.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassFilter;
|
||||
@ -856,85 +845,6 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||
return builtinNode;
|
||||
}
|
||||
|
||||
private void findReferencesToField(String choice) {
|
||||
DockingActionIf searchAction = getAction(plugin, "Find Uses of Field");
|
||||
assertTrue(searchAction.isEnabledForContext(treeContext));
|
||||
DataTypeTestUtils.performAction(searchAction, tree, false);
|
||||
|
||||
InputWithChoicesDialog d = waitForDialogComponent(InputWithChoicesDialog.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
GhidraComboBox<String> combo = (GhidraComboBox<String>) getInstanceField("combo", d);
|
||||
setComboBoxSelection(combo, choice);
|
||||
pressButtonByText(d, "OK");
|
||||
|
||||
waitForSearchResults();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private LocationReferencesProvider getLocationReferencesProvider() {
|
||||
LocationReferencesPlugin locationRefsPlugin =
|
||||
getPlugin(tool, LocationReferencesPlugin.class);
|
||||
|
||||
List<LocationReferencesProvider> providerList =
|
||||
(List<LocationReferencesProvider>) getInstanceField("providerList", locationRefsPlugin);
|
||||
if (providerList.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return providerList.get(0);
|
||||
}
|
||||
|
||||
private ThreadedTableModel<?, ?> getTableModel() {
|
||||
|
||||
waitForCondition(() -> getLocationReferencesProvider() != null);
|
||||
|
||||
LocationReferencesProvider refsProvider = getLocationReferencesProvider();
|
||||
Object referencesPanel = getInstanceField("referencesPanel", refsProvider);
|
||||
return (ThreadedTableModel<?, ?>) getInstanceField("tableModel", referencesPanel);
|
||||
}
|
||||
|
||||
private void waitForSearchResults() {
|
||||
ThreadedTableModel<?, ?> model = getTableModel();
|
||||
waitForTableModel(model);
|
||||
}
|
||||
|
||||
private HighlightProvider getHighlightProvider() {
|
||||
CodeViewerService service = tool.getService(CodeViewerService.class);
|
||||
FormatManager fm = (FormatManager) getInstanceField("formatMgr", service);
|
||||
return (HighlightProvider) getInstanceField("highlightProvider", fm);
|
||||
}
|
||||
|
||||
private void assertOperandHighlight(String rep, Address addr) {
|
||||
assertHighlight(OperandFieldFactory.class, rep, addr);
|
||||
}
|
||||
|
||||
private void assertFieldNameHighlight(String rep, Address addr) {
|
||||
assertHighlight(FieldNameFieldFactory.class, rep, addr);
|
||||
}
|
||||
|
||||
private void assertHighlight(Class<? extends FieldFactory> clazz, String rep, Address addr) {
|
||||
Listing listing = program.getListing();
|
||||
CodeUnit cu = listing.getCodeUnitContaining(addr);
|
||||
if (cu instanceof Data) {
|
||||
Data data = (Data) cu;
|
||||
Address minAddress = data.getMinAddress();
|
||||
long offset = addr.subtract(minAddress);
|
||||
if (offset != 0) {
|
||||
Data subData = data.getComponentAt((int) offset);
|
||||
cu = subData;
|
||||
}
|
||||
}
|
||||
HighlightProvider highlighter = getHighlightProvider();
|
||||
Highlight[] highlights = highlighter.getHighlights(rep, cu, clazz, -1);
|
||||
assertNotNull(highlights);
|
||||
assertTrue(highlights.length != 0);
|
||||
}
|
||||
|
||||
private Address addr(long offset) {
|
||||
AddressFactory addrMap = program.getAddressFactory();
|
||||
AddressSpace space = addrMap.getDefaultAddressSpace();
|
||||
return space.getAddress(offset);
|
||||
}
|
||||
|
||||
private void assertSingleFilterMatch(String[] path) {
|
||||
GTreeNode rootNode = tree.getViewRoot();
|
||||
|
||||
|
@ -31,6 +31,7 @@ import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
@ -52,12 +53,12 @@ public class DataTypeTestUtils {
|
||||
}
|
||||
|
||||
// copies the default test archive into a local version
|
||||
static File createArchive(String filename) throws Exception {
|
||||
public static File createArchive(String filename) throws Exception {
|
||||
return createLocalArchiveFromExistingArchive(filename, "TestArchive.gdt");
|
||||
}
|
||||
|
||||
// copies the archive from the given filename to a local version
|
||||
static File copyArchive(String filename) throws Exception {
|
||||
public static File copyArchive(String filename) throws Exception {
|
||||
return createLocalArchiveFromExistingArchive(filename, filename);
|
||||
}
|
||||
|
||||
@ -92,8 +93,8 @@ public class DataTypeTestUtils {
|
||||
return scratchFile;
|
||||
}
|
||||
|
||||
static ArchiveNode openArchive(String archiveDirPath, String archiveName, boolean checkout,
|
||||
DataTypeManagerPlugin plugin) throws Exception {
|
||||
public static ArchiveNode openArchive(String archiveDirPath, String archiveName,
|
||||
boolean checkout, DataTypeManagerPlugin plugin) throws Exception {
|
||||
|
||||
File file = new File(archiveDirPath, archiveName);
|
||||
DataTypeManagerHandler dataTypeManagerHandler = plugin.getDataTypeManagerHandler();
|
||||
@ -107,7 +108,7 @@ public class DataTypeTestUtils {
|
||||
return (ArchiveNode) rootNode.getChild(trimFullArchiveName(archiveName));
|
||||
}
|
||||
|
||||
static ArchiveNode openArchive(String archiveName, boolean checkout,
|
||||
public static ArchiveNode openArchive(String archiveName, boolean checkout,
|
||||
DataTypeManagerPlugin plugin) throws Exception {
|
||||
ArchiveNode openArchive = openArchive(archiveName, checkout, false, plugin);
|
||||
waitForTree(plugin);
|
||||
@ -127,8 +128,8 @@ public class DataTypeTestUtils {
|
||||
AbstractGenericTest.waitForPostedSwingRunnables();
|
||||
}
|
||||
|
||||
static ArchiveNode openArchive(String archiveName, boolean checkout, boolean isUserAction,
|
||||
DataTypeManagerPlugin plugin) throws Exception {
|
||||
public static ArchiveNode openArchive(String archiveName, boolean checkout,
|
||||
boolean isUserAction, DataTypeManagerPlugin plugin) throws Exception {
|
||||
|
||||
File tempDir = getTempDir();
|
||||
File file = new File(tempDir, archiveName);
|
||||
@ -143,23 +144,21 @@ public class DataTypeTestUtils {
|
||||
return (ArchiveNode) rootNode.getChild(trimFullArchiveName(archiveName));
|
||||
}
|
||||
|
||||
static void closeArchive(final ArchiveNode archiveNode, final boolean deleteFile)
|
||||
public static void closeArchive(final ArchiveNode archiveNode, final boolean deleteFile)
|
||||
throws Exception {
|
||||
|
||||
final Exception[] container = new Exception[1];
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
Exception exception = Swing.runNow(() -> {
|
||||
try {
|
||||
doCloseArchive(archiveNode, deleteFile);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
container[0] = e;
|
||||
return e;
|
||||
}
|
||||
});
|
||||
|
||||
if (container[0] != null) {
|
||||
throw new RuntimeException("Exception closing archive on Swing thread!: ",
|
||||
container[0]);
|
||||
if (exception != null) {
|
||||
throw new RuntimeException("Exception closing archive on Swing thread!: ", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,8 +190,8 @@ public class DataTypeTestUtils {
|
||||
* @return The archive node associated with the open archive
|
||||
* @throws Exception If there is any problem finding or opening the archive for the given name
|
||||
*/
|
||||
static ArchiveNode checkOutArchive(String archiveName, final DataTypeManagerPlugin plugin)
|
||||
throws Exception {
|
||||
public static ArchiveNode checkOutArchive(String archiveName,
|
||||
final DataTypeManagerPlugin plugin) throws Exception {
|
||||
|
||||
String archiveNodeName = trimFullArchiveName(archiveName);
|
||||
GTree tree = plugin.getProvider().getGTree();
|
||||
@ -222,14 +221,14 @@ public class DataTypeTestUtils {
|
||||
return archiveName;
|
||||
}
|
||||
|
||||
static ArchiveNode createOpenAndCheckoutArchive(String archiveName,
|
||||
public static ArchiveNode createOpenAndCheckoutArchive(String archiveName,
|
||||
DataTypeManagerPlugin plugin) throws Exception {
|
||||
createArchive(archiveName);
|
||||
return openArchive(archiveName, true, plugin);
|
||||
}
|
||||
|
||||
static ArchiveNode copyOpenAndCheckoutArchive(String archiveName, DataTypeManagerPlugin plugin)
|
||||
throws Exception {
|
||||
public static ArchiveNode copyOpenAndCheckoutArchive(String archiveName,
|
||||
DataTypeManagerPlugin plugin) throws Exception {
|
||||
copyArchive(archiveName);
|
||||
return openArchive(archiveName, true, plugin);
|
||||
}
|
||||
@ -238,7 +237,8 @@ public class DataTypeTestUtils {
|
||||
performAction(action, program, tree, true);
|
||||
}
|
||||
|
||||
static void performAction(DockingActionIf action, Program program, GTree tree, boolean wait) {
|
||||
public static void performAction(DockingActionIf action, Program program, GTree tree,
|
||||
boolean wait) {
|
||||
AbstractGenericTest.runSwing(() -> {
|
||||
ActionContext context =
|
||||
new DataTypesActionContext(null, program, (DataTypeArchiveGTree) tree, null, true);
|
||||
@ -266,7 +266,7 @@ public class DataTypeTestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
static void createCategory(Category parent, String categoryName) throws Exception {
|
||||
public static void createCategory(Category parent, String categoryName) throws Exception {
|
||||
DataTypeManager dtm = parent.getDataTypeManager();
|
||||
int id = dtm.startTransaction("create category");
|
||||
try {
|
||||
|
@ -15,23 +15,24 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.datamgr.util;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.plugin.core.datamgr.archive.SourceArchive;
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
import ghidra.program.model.data.*;
|
||||
import generic.test.AbstractGTest;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeComparator;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.program.model.data.TestDoubleDataType;
|
||||
import ghidra.util.UniversalIdGenerator;
|
||||
|
||||
public class DataTypeUtilsTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
UniversalIdGenerator.initialize();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataSearch() throws Exception {
|
||||
|
||||
@ -43,7 +44,7 @@ public class DataTypeUtilsTest {
|
||||
final List<DataType> data = new ArrayList<>();
|
||||
|
||||
for (String element : TEST_DATA) {
|
||||
data.add(new DataTypeDummy(element));
|
||||
data.add(new FakeDataType(element));
|
||||
}
|
||||
|
||||
// sort them how our data will be sorted
|
||||
@ -110,266 +111,18 @@ public class DataTypeUtilsTest {
|
||||
List<DataType> actualMatches =
|
||||
DataTypeUtils.getMatchingSubList(text, text + endChar, sourceData);
|
||||
|
||||
AbstractGenericTest.assertListEqualUnordered(null, expectedMatches, actualMatches);
|
||||
AbstractGTest.assertListEqualUnordered(null, expectedMatches, actualMatches);
|
||||
}
|
||||
|
||||
private class DataTypeDummy implements DataType {
|
||||
private class FakeDataType extends TestDoubleDataType {
|
||||
|
||||
String wrappedString;
|
||||
UniversalID id;
|
||||
|
||||
DataTypeDummy(String wrappedString) {
|
||||
this.wrappedString = wrappedString;
|
||||
id = UniversalIdGenerator.nextID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return wrappedString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager getDataTypeManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "This is a wrapper for: " + wrappedString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return wrappedString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotYetDefined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamicallySized() {
|
||||
return false;
|
||||
FakeDataType(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathName() {
|
||||
return "/" + wrappedString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingsDefinition[] getSettingsDefinitions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getDefaultSettings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CategoryPath getCategoryPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypePath getDataTypePath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCategoryPath(CategoryPath path) throws DuplicateNameException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndCategory(CategoryPath path, String name)
|
||||
throws InvalidNameException, DuplicateNameException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMnemonic(Settings settings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDescription(String description) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() + " doesn't allow the description to be changed.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getDocs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalent(DataType dt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeSizeChanged(DataType dt) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeDeleted(DataType dt) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeReplaced(DataType oldDt, DataType newDt) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultSettings(Settings settings) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParent(DataType dt) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeParent(DataType dt) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeNameChanged(DataType dt, String oldName) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOn(DataType dt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLabelPrefix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultAbbreviatedLabelPrefix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options, int offcutLength) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastChangeTimeInSourceArchive() {
|
||||
return DataType.NO_SOURCE_SYNC_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastChangeTime() {
|
||||
return DataType.NO_LAST_CHANGE_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceArchive getSourceArchive() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniversalID getUniversalID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceWith(DataType dataType) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastChangeTime(long lastChangeTime) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastChangeTimeInSourceArchive(long lastChangeTimeInSourceArchive) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceArchive(SourceArchive archive) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlignment() {
|
||||
return 1;
|
||||
return "/" + getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.services;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||
import ghidra.app.plugin.core.datamgr.archive.DuplicateIdException;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.DataTypeArchive;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* A stub of the {@link DataTypeManagerService} interface. This can be used to supply a test values
|
||||
* or to spy on system internals by overriding methods as needed.
|
||||
*/
|
||||
public class TestDoubleDataTypeManagerService implements DataTypeManagerService {
|
||||
|
||||
@Override
|
||||
public DataTypeManager[] getDataTypeManagers() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataType> getSortedDataTypeList() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(String filterText) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager getBuiltInDataTypesManager() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataType> getFavorites() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDataTypeManagerChangeListener(DataTypeManagerChangeListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDataTypeManagerChangeListener(DataTypeManagerChangeListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecentlyUsed(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getRecentlyUsed() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getEditorHelpLocation(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEditable(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void edit(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeArchive(DataTypeManager dtm) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager openDataTypeArchive(String archiveName)
|
||||
throws IOException, DuplicateIdException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive openArchive(DataTypeArchive dataTypeArchive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive openArchive(File file, boolean acquireWriteLock)
|
||||
throws IOException, DuplicateIdException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataTypeSelected(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(TreePath selectedPath) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPossibleEquateNames(long value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -0,0 +1,279 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.datatype;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.services.TestDoubleDataTypeManagerService;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.UniversalID;
|
||||
import ghidra.util.UniversalIdGenerator;
|
||||
|
||||
public class DataTypeUrlTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
UniversalIdGenerator.initialize();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_FromDataType() throws Exception {
|
||||
|
||||
String name = "string";
|
||||
FakeDataType dt = new FakeDataType(name);
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(dt);
|
||||
|
||||
assertNotNull(dtUrl.getDataTypeManagerId());
|
||||
assertNotNull(dtUrl.getDataTypeId());
|
||||
assertEquals(name, dtUrl.getDataTypeName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_FromUrlString_AllDataIncluded() throws Exception {
|
||||
|
||||
String dtmId = "3295333330922457057";
|
||||
String dtId = "3295333330922457056";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(urlString);
|
||||
assertNotNull(dtUrl.getDataTypeManagerId());
|
||||
assertNotNull(dtUrl.getDataTypeId());
|
||||
assertEquals(name, dtUrl.getDataTypeName());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructor_FromUrlString_AllDataIncluded_BadDataTypeManagerId()
|
||||
throws Exception {
|
||||
|
||||
String dtmId = "123bad_id123";
|
||||
String dtId = "3295333330922457056";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
new DataTypeUrl(urlString);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructor_FromUrlString_AllDataIncluded_BadDataTypeId() throws Exception {
|
||||
|
||||
String dtmId = "3295333330922457057";
|
||||
String dtId = "bad_id";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
new DataTypeUrl(urlString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_FromUrlString_NoDataTypeId() throws Exception {
|
||||
|
||||
String dtmId = "3295333330922457057";
|
||||
String dtId = "";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(urlString);
|
||||
assertNotNull(dtUrl.getDataTypeManagerId());
|
||||
assertNull(dtUrl.getDataTypeId());
|
||||
assertEquals(name, dtUrl.getDataTypeName());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructor_FromUrlString_NoDataTypeManagerId() throws Exception {
|
||||
|
||||
String dtmId = "";
|
||||
String dtId = "3295333330922457056";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
new DataTypeUrl(urlString);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructor_FromUrlString_NoDataTypeName() throws Exception {
|
||||
|
||||
String dtmId = "3295333330922457057";
|
||||
String dtId = "3295333330922457056";
|
||||
String name = " ";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
new DataTypeUrl(urlString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataType() {
|
||||
|
||||
String name = "string";
|
||||
String dtmId = "3295333330922457057";
|
||||
FakeDataTypeManager manager = new FakeDataTypeManager(dtmId);
|
||||
FakeDataType dt = new FakeDataType(name, manager);
|
||||
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(dt);
|
||||
|
||||
DataTypeManagerService service = new FakeDataTypeManagerService(manager);
|
||||
DataType actualDt = dtUrl.getDataType(service);
|
||||
assertEquals(dt, actualDt);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataType_ByName() {
|
||||
|
||||
String name = "string";
|
||||
String dtmId = "3295333330922457057";
|
||||
FakeDataTypeManager manager = new FakeDataTypeManager(dtmId);
|
||||
FakeDataType dt = new FakeDataType(name, manager);
|
||||
|
||||
String dtId = ""; // no id; name only
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(urlString);
|
||||
|
||||
DataTypeManagerService service = new FakeDataTypeManagerService(manager);
|
||||
DataType actualDt = dtUrl.getDataType(service);
|
||||
assertEquals(dt, actualDt);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
|
||||
String name = "string";
|
||||
FakeDataType dt = new FakeDataType(name);
|
||||
|
||||
DataTypeUrl dtUrl1 = new DataTypeUrl(dt);
|
||||
DataTypeUrl dtUrl2 = new DataTypeUrl(dt);
|
||||
assertEquals(dtUrl1, dtUrl2);
|
||||
|
||||
FakeDataType otherDt = new FakeDataType("otherType");
|
||||
DataTypeUrl otherDtUrl = new DataTypeUrl(otherDt);
|
||||
assertNotEquals(dtUrl1, otherDtUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
|
||||
String name = "string";
|
||||
FakeDataType dt = new FakeDataType(name);
|
||||
|
||||
DataTypeUrl dtUrl1 = new DataTypeUrl(dt);
|
||||
DataTypeUrl dtUrl2 = new DataTypeUrl(dt);
|
||||
assertEquals(dtUrl1.hashCode(), dtUrl2.hashCode());
|
||||
|
||||
FakeDataType otherDt = new FakeDataType("otherType");
|
||||
DataTypeUrl otherDtUrl = new DataTypeUrl(otherDt);
|
||||
assertNotEquals(dtUrl1.hashCode(), otherDtUrl.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
|
||||
String dtmId = "3295333330922457057";
|
||||
String dtId = "3295333330922457056";
|
||||
String name = "string";
|
||||
String urlString = "datatype:/" + dtmId + "?uid=" + dtId + "&name=" + name;
|
||||
|
||||
DataTypeUrl dtUrl = new DataTypeUrl(urlString);
|
||||
assertEquals(urlString, dtUrl.toString());
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private class FakeDataType extends TestDoubleDataType {
|
||||
|
||||
private DataTypeManager manager = new FakeDataTypeManager();
|
||||
|
||||
FakeDataType(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
FakeDataType(String name, FakeDataTypeManager manager) {
|
||||
super(name);
|
||||
this.manager = manager;
|
||||
manager.addDataType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager getDataTypeManager() {
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeDataTypeManager extends TestDoubleDataTypeManager {
|
||||
|
||||
private UniversalID id;
|
||||
private List<DataType> types = new ArrayList<>();
|
||||
|
||||
FakeDataTypeManager() {
|
||||
id = UniversalIdGenerator.nextID();
|
||||
}
|
||||
|
||||
FakeDataTypeManager(String idString) {
|
||||
id = new UniversalID(Long.parseLong(idString));
|
||||
}
|
||||
|
||||
void addDataType(DataType dt) {
|
||||
types.add(dt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniversalID getUniversalID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(DataTypePath path) {
|
||||
for (DataType dt : types) {
|
||||
if (dt.getName().equals(path.getDataTypeName())) {
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType findDataTypeForID(UniversalID datatypeID) {
|
||||
for (DataType dt : types) {
|
||||
if (dt.getUniversalID().equals(datatypeID)) {
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeDataTypeManagerService extends TestDoubleDataTypeManagerService {
|
||||
|
||||
private DataTypeManager manager;
|
||||
|
||||
FakeDataTypeManagerService(DataTypeManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager[] getDataTypeManagers() {
|
||||
return new DataTypeManager[] { manager };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -82,6 +82,10 @@ public class HistoryList<T> {
|
||||
* True signals that this list will allow duplicate entries. False signals to not only not
|
||||
* allow duplicates, but to also move the position of an item if it is re-added to the
|
||||
* list.
|
||||
*
|
||||
* <p>For correct behavior when not allowing duplicates, ensure you have defined an
|
||||
* <code>equals</code> method to work as you expect. If two different items are considered
|
||||
* equal, then this class will only remove the duplicate if the equals method returns true.
|
||||
*
|
||||
* <p>The default is false
|
||||
*
|
||||
@ -162,7 +166,6 @@ public class HistoryList<T> {
|
||||
* <p>No action is taken if the current pointer is already at the beginning of the list.
|
||||
*/
|
||||
public void goBack() {
|
||||
|
||||
if (historyIndex == 0) {
|
||||
return;
|
||||
}
|
||||
@ -172,6 +175,18 @@ public class HistoryList<T> {
|
||||
broadcast(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link #goBack()} until the given item becomes the current item. This is
|
||||
* useful if you wish to go backward to a specific item in the list.
|
||||
*
|
||||
* @param t the item
|
||||
*/
|
||||
public void goBackTo(T t) {
|
||||
while (!getCurrentHistoryItem().equals(t) && hasPrevious()) {
|
||||
goBack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves this history list's current item pointer forward one and then calls the user-provided
|
||||
* callback to signal the newly selected item.
|
||||
@ -187,6 +202,18 @@ public class HistoryList<T> {
|
||||
broadcast(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link #goForward()} until the given item becomes the current item. This is
|
||||
* useful if you wish to go forward to a specific item in the list.
|
||||
*
|
||||
* @param t the item
|
||||
*/
|
||||
public void goForwardTo(T t) {
|
||||
while (!getCurrentHistoryItem().equals(t) && hasNext()) {
|
||||
goForward();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item currently pointed to within the list of items. When an item is
|
||||
* added, this will be that item. Otherwise, it will be the last item navigated.
|
||||
@ -217,7 +244,7 @@ public class HistoryList<T> {
|
||||
|
||||
/**
|
||||
* Get all items in the history that come after the current history item. They are
|
||||
* returned in navigation order, as traversed if {@link #goForward() is called.
|
||||
* returned in navigation order, as traversed if {@link #goForward()} is called.
|
||||
*
|
||||
* @return the items
|
||||
*/
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package util;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@ -425,6 +425,32 @@ public class HistoryListTest {
|
||||
assertNextItems();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackToItem() {
|
||||
|
||||
addHistory(A);
|
||||
addHistory(B);
|
||||
addHistory(C);
|
||||
|
||||
historyList.goBackTo(A);
|
||||
assertCurrentItem(A);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForwardToItem() {
|
||||
|
||||
addHistory(A);
|
||||
addHistory(B);
|
||||
addHistory(C);
|
||||
goBack();
|
||||
goBack();
|
||||
goBack();
|
||||
assertCurrentItem(A);
|
||||
|
||||
historyList.goForwardTo(C);
|
||||
assertCurrentItem(C);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
@ -31,8 +31,8 @@ import ghidra.util.task.TaskMonitorAdapter;
|
||||
* DataTypeManager for a file. Can import categories from a file, or export
|
||||
* categories to a packed database.
|
||||
*/
|
||||
public class FileDataTypeManager extends StandAloneDataTypeManager implements
|
||||
FileArchiveBasedDataTypeManager {
|
||||
public class FileDataTypeManager extends StandAloneDataTypeManager
|
||||
implements FileArchiveBasedDataTypeManager {
|
||||
|
||||
public final static String EXTENSION = "gdt"; // Ghidra Data Types
|
||||
/**
|
||||
@ -108,16 +108,15 @@ public class FileDataTypeManager extends StandAloneDataTypeManager implements
|
||||
* @param outputFilename filename for output
|
||||
* @param databaseId new databaseId
|
||||
*/
|
||||
public void saveAs(File saveFile, UniversalID newUniversalId) throws DuplicateFileException,
|
||||
IOException {
|
||||
public void saveAs(File saveFile, UniversalID newUniversalId)
|
||||
throws DuplicateFileException, IOException {
|
||||
ResourceFile resourceSaveFile = new ResourceFile(saveFile);
|
||||
// TODO: this should really be a package method and not public!
|
||||
validateFilename(resourceSaveFile);
|
||||
try {
|
||||
universalID = newUniversalId;
|
||||
packedDB =
|
||||
((PackedDBHandle) dbHandle).saveAs("DTArchive", saveFile.getParentFile(),
|
||||
saveFile.getName(), newUniversalId.getValue(), TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
packedDB = ((PackedDBHandle) dbHandle).saveAs("DTArchive", saveFile.getParentFile(),
|
||||
saveFile.getName(), newUniversalId.getValue(), TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
file = resourceSaveFile;
|
||||
updateRootCategoryName(resourceSaveFile, getRootCategory());
|
||||
}
|
||||
@ -134,9 +133,8 @@ public class FileDataTypeManager extends StandAloneDataTypeManager implements
|
||||
ResourceFile resourceSaveFile = new ResourceFile(saveFile);
|
||||
validateFilename(resourceSaveFile);
|
||||
try {
|
||||
packedDB =
|
||||
((PackedDBHandle) dbHandle).saveAs("DTArchive", saveFile.getParentFile(),
|
||||
saveFile.getName(), TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
packedDB = ((PackedDBHandle) dbHandle).saveAs("DTArchive", saveFile.getParentFile(),
|
||||
saveFile.getName(), TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
file = resourceSaveFile;
|
||||
updateRootCategoryName(resourceSaveFile, getRootCategory());
|
||||
}
|
||||
@ -268,4 +266,8 @@ public class FileDataTypeManager extends StandAloneDataTypeManager implements
|
||||
return ArchiveType.FILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + " - " + getName();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,288 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import ghidra.app.plugin.core.datamgr.archive.SourceArchive;
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* A stub of the {@link DataType} interface. This can be used to supply a test values
|
||||
* or to spy on system internals by overriding methods as needed.
|
||||
*/
|
||||
public class TestDoubleDataType implements DataType {
|
||||
|
||||
private UniversalID id;
|
||||
private String name;
|
||||
|
||||
public TestDoubleDataType(String name) {
|
||||
this.name = name;
|
||||
this.id = UniversalIdGenerator.nextID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamicallySized() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotYetDefined() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingsDefinition[] getSettingsDefinitions() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getDefaultSettings() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CategoryPath getCategoryPath() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypePath getDataTypePath() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCategoryPath(CategoryPath path) throws DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager getDataTypeManager() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Test double data type '" + getName() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndCategory(CategoryPath path, String name)
|
||||
throws InvalidNameException, DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMnemonic(Settings settings) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDescription(String description) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getDocs() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLabelPrefix() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultAbbreviatedLabelPrefix() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options, int offcutOffset) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeleted() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalent(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeSizeChanged(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeDeleted(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeReplaced(DataType oldDt, DataType newDt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultSettings(Settings settings) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParent(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeParent(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeNameChanged(DataType dt, String oldName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlignment() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOn(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceArchive getSourceArchive() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceArchive(SourceArchive archive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastChangeTime() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastChangeTimeInSourceArchive() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniversalID getUniversalID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceWith(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastChangeTime(long lastChangeTime) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastChangeTimeInSourceArchive(long lastChangeTimeInSourceArchive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -0,0 +1,342 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.core.datamgr.archive.SourceArchive;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A stub of the {@link DataTypeManager} interface. This can be used to supply a test values
|
||||
* or to spy on system internals by overriding methods as needed.
|
||||
*/
|
||||
public class TestDoubleDataTypeManager implements DataTypeManager {
|
||||
|
||||
private UniversalID id;
|
||||
|
||||
public TestDoubleDataTypeManager() {
|
||||
this.id = UniversalIdGenerator.nextID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniversalID getUniversalID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCategory(CategoryPath path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueName(CategoryPath path, String baseName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType resolve(DataType dataType, DataTypeConflictHandler handler) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType addDataType(DataType dataType, DataTypeConflictHandler handler) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<DataType> getAllDataTypes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAllDataTypes(List<DataType> list) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Structure> getAllStructures() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Composite> getAllComposites() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findDataTypes(String name, List<DataType> list) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findDataTypes(String name, List<DataType> list, boolean caseSensitive,
|
||||
TaskMonitor monitor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType replaceDataType(DataType existingDt, DataType replacementDt,
|
||||
boolean updateCategoryPath) throws DataTypeDependencyException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(String dataTypePath) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType findDataType(String dataTypePath) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(DataTypePath dataTypePath) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getResolvedID(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getID(DataType dt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(long dataTypeID) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory(long categoryID) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory(CategoryPath path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeChanged(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDataTypeManagerListener(DataTypeManagerChangeListener l) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDataTypeManagerListener(DataTypeManagerChangeListener l) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInvalidatedListener(InvalidatedListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInvalidatedListener(InvalidatedListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(DataType dataType, TaskMonitor monitor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category createCategory(CategoryPath path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(CategoryPath path, String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startTransaction(String description) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransaction(int transactionID, boolean commit) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushEvents() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointer getPointer(DataType datatype) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointer getPointer(DataType datatype, int size) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getRootCategory() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFavorite(DataType datatype) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavorite(DataType datatype, boolean isFavorite) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataType> getFavorites() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCategoryCount() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataTypeCount(boolean includePointersAndArrays) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findEnumValueNames(long value, Set<String> enumValueNames) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(SourceArchive sourceArchive, UniversalID datatypeID) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType findDataTypeForID(UniversalID datatypeID) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastChangeTimeForMyManager() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceArchive getSourceArchive(UniversalID sourceID) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArchiveType getType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataType> getDataTypes(SourceArchive sourceArchive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceArchive getLocalSourceArchive() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void associateDataTypeWithArchive(DataType datatype, SourceArchive archive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disassociate(DataType datatype) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSourceArchiveName(String archiveFileID, String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSourceArchiveName(UniversalID sourceID, String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SourceArchive> getSourceArchives() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSourceArchive(SourceArchive sourceArchive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceArchive resolveSourceArchive(SourceArchive sourceArchive) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<DataType> getDataTypesContaining(DataType dataType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user