GP-1307 data type resolution conflict handling improvements

This commit is contained in:
ghidra1 2022-12-16 18:42:46 -05:00
parent 7f9de4251d
commit a0a4ea67f8
6 changed files with 581 additions and 227 deletions

View file

@ -540,7 +540,7 @@ class CategoryDB extends DatabaseObject implements Category {
return;
}
if (existing != null) {
ConflictResult result = mgr.resolveConflict(handler, movedDataType, existing);
ConflictResult result = handler.resolveConflict(movedDataType, existing);
if (result == ConflictResult.REPLACE_EXISTING) { // replace existing dt with new dt.
mgr.replaceDataType(existing, movedDataType, true);
}

View file

@ -1049,16 +1049,15 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
else if (sourceArchive == null || dataType.getUniversalID() == null) {
// if the dataType has no source or it has no ID (datatypes with no ID are
// always local i.e. pointers)
resolvedDataType = resolveNoSourceDataType(dataType, currentHandler);
resolvedDataType = resolveDataTypeNoSource(dataType, currentHandler);
}
else if (!sourceArchive.getSourceArchiveID().equals(getUniversalID()) &&
sourceArchive.getArchiveType() == ArchiveType.PROGRAM) {
// dataTypes from a different program don't carry over their identity.
resolvedDataType = resolveNoSourceDataType(dataType, currentHandler);
resolvedDataType = resolveDataTypeNoSource(dataType, currentHandler);
}
else {
resolvedDataType =
resolveDataTypeWithSource(dataType, sourceArchive, currentHandler);
resolvedDataType = resolveDataTypeWithSource(dataType, currentHandler);
}
cacheResolvedDataType(dataType, resolvedDataType);
if (resolvedDataType instanceof DataTypeDB) {
@ -1083,6 +1082,12 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
private DataType resolveBuiltIn(DataType dataType, DataTypeConflictHandler handler) {
if (dataType instanceof Pointer) {
// treat built-in pointers like other datatypes without a source
return resolveDataTypeNoSource(dataType, currentHandler);
}
// can't do this check now because Pointers from the BuiltinDataTypeManager are
// not instances of BuiltInDataType because the BuiltInDataTypeManger converts
// pointers from BuiltIns to PointerDBs (Probably shouldn't, but the
@ -1094,7 +1099,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
return existingDataType;
}
// oops a non-builtin dataType exists with the same name. Only option is to rename existing
String dtName = getUnusedConflictName(dataType.getCategoryPath(), dataType.getName());
String dtName = getUnusedConflictName(dataType);
try {
existingDataType.setName(dtName);
}
@ -1135,84 +1140,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
}
/**
* Either finds an equivalent dataType with the same categoryPath and name (or
* conflict name) to the given dataType. Otherwise, it creates a new dataType in
* this archive equivalent to the given dataType. If a dataType exists with same
* path and name but is not equivalent, the handler will resolve the problem in
* one of 3 ways. 1) A new dataType will be created, but with a .conflict name
* 2) The existing dataType will be replaced by a resolved copy of the given
* dataType. 3) The existing dataType will be returned instead of a resolved
* version of the given dataType.
*
* @param dataType the dataType for which to return an equivalent dataType in
* this manager
* @param handler Used to handle collisions with dataTypes with same path and
* name that is
* @return resolved datatype
*/
private DataType resolveNoSourceDataType(DataType dataType, DataTypeConflictHandler handler) {
DataType existingDataType = findEquivalentDataTypeSameLocation(dataType, handler);
if (existingDataType != null) {
return existingDataType;
}
existingDataType = getDataType(dataType.getCategoryPath(), dataType.getName());
if (existingDataType == null) {
return createDataType(dataType, dataType.getName(), null, handler);
}
// So we have a dataType with the same path and name, but not equivalent, so use
// the conflictHandler to decide what to do.
ConflictResult result = resolveConflict(handler, dataType, existingDataType);
switch (result) {
case REPLACE_EXISTING: // new type replaces old conflicted type
try {
if (updateExistingDataType(existingDataType, dataType)) {
return existingDataType;
}
renameToUnusedConflictName(existingDataType);
DataType newDataType =
createDataType(dataType, dataType.getName(), null, handler);
try {
replace(existingDataType, newDataType);
}
catch (DataTypeDependencyException e) {
throw new IllegalArgumentException(
"Invalid datatype replacement: " + newDataType.getName(), e);
}
return newDataType;
}
catch (DataTypeDependencyException e) {
// new type refers to old type - fallthrough to RENAME_AND_ADD
// TODO: alternatively we could throw an exception
}
case RENAME_AND_ADD: // default handler behavior
String dtName =
getUnusedConflictName(dataType.getCategoryPath(), dataType.getName());
DataType newDataType = createDataType(dataType, dtName, null, handler);
// resolving child data types could result in another copy of dataType in the
// manager depending upon the conflict handler - check again
existingDataType = findEquivalentDataTypeSameLocation(dataType, handler);
// If there is an equivalent datatype, remove the added type and return the existing
if (existingDataType != null && existingDataType != newDataType) {
removeInternal(newDataType, TaskMonitor.DUMMY);
return existingDataType;
}
return newDataType;
case USE_EXISTING: // new type is discarded and old conflicted type is returned
return existingDataType;
}
return null;
}
private void renameToUnusedConflictName(DataType dataType) {
String dtName = dataType.getName();
String name = getUnusedConflictName(dataType.getCategoryPath(), dtName);
String name = getUnusedConflictName(dataType);
try {
dataType.setName(name);
}
@ -1232,15 +1161,14 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
*
* @param existingDataType existing datatype
* @param dataType new datatype
* @param sourceArchive source archive associated with new type (may be null).
* If not null the existingDataType will be updated with source info.
* @return true if replacement approach was successful, else false
* @throws DataTypeDependencyException if datatype contains dependency issues
* during resolve process
*/
private boolean updateExistingDataType(DataType existingDataType, DataType dataType)
throws DataTypeDependencyException {
// TODO: this approach could be added to other DB datatypes to avoid
// unnecessary creation and removal.
private boolean updateExistingDataType(DataType existingDataType, DataType dataType,
SourceArchive sourceArchive) throws DataTypeDependencyException {
try {
if (existingDataType instanceof StructureDB) {
@ -1249,7 +1177,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
StructureDB existingStruct = (StructureDB) existingDataType;
existingStruct.doReplaceWith((StructureInternal) dataType, true);
return true;
}
else if (existingDataType instanceof UnionDB) {
if (!(dataType instanceof UnionInternal)) {
@ -1257,8 +1184,37 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
UnionDB existingUnion = (UnionDB) existingDataType;
existingUnion.doReplaceWith((UnionInternal) dataType, true);
return true;
}
else if (existingDataType instanceof FunctionDefinitionDB) {
if (!(dataType instanceof FunctionDefinition)) {
return false;
}
existingDataType.replaceWith(dataType);
}
else if (existingDataType instanceof EnumDB) {
if (!(dataType instanceof Enum)) {
return false;
}
existingDataType.replaceWith(dataType);
}
else if (existingDataType instanceof TypedefDB) {
if (!(dataType instanceof TypeDef)) {
return false;
}
existingDataType.replaceWith(dataType);
}
else {
return false;
}
if (sourceArchive != null) {
existingDataType.setSourceArchive(sourceArchive);
((DataTypeDB) existingDataType).setUniversalID(dataType.getUniversalID());
long lastChangeTime = dataType.getLastChangeTime();
existingDataType.setLastChangeTime(lastChangeTime);
existingDataType.setLastChangeTimeInSourceArchive(lastChangeTime);
}
return true;
}
catch (IOException e) {
dbError(e);
@ -1266,6 +1222,21 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
return false;
}
/**
* This method gets a ".conflict" name that is not currently used by any data
* types in the indicated category of the data type manager.
* @param dt datatype who name is used to establish non-conflict base name
* @return the unused conflict name or original name for datatypes whose name is automatic
*/
public String getUnusedConflictName(DataType dt) {
String name = dt.getName();
if ((dt instanceof Array) || (dt instanceof Pointer) || (dt instanceof BuiltInDataType)) {
// name not used - anything will do
return name;
}
return getUnusedConflictName(dt.getCategoryPath(), name);
}
/**
* This method gets a ".conflict" name that is not currently used by any data
* types in the indicated category of the data type manager.
@ -1283,20 +1254,59 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
if (index > 0) {
name = name.substring(0, index);
}
// Name sequence: <baseName>, <baseName>.conflict, <basename>.conflict1, ...
String baseName = name + DataType.CONFLICT_SUFFIX;
String testName = baseName;
String testName = name;
int count = 0;
while (getDataType(path, testName) != null) {
count++;
testName = baseName + count;
String countSuffix = "";
if (count != 0) {
countSuffix = Integer.toString(count);
}
testName = baseName + countSuffix;
++count;
}
return testName;
}
private boolean isEquivalentDataType(DataType addedDataType, DataType existingDataType,
DataTypeConflictHandler handler) {
return existingDataType.isEquivalent(addedDataType) ||
handler.resolveConflict(addedDataType, existingDataType) == ConflictResult.USE_EXISTING;
private List<DataType> findDataTypesSameLocation(DataType dataType) {
Category category = getCategory(dataType.getCategoryPath());
if (category == null) {
return List.of();
}
if (!(dataType instanceof Pointer) && !(dataType instanceof Array)) {
return category.getDataTypesByBaseName(dataType.getName());
}
// Handle pointers and arrays
DataType existingDataType = category.getDataType(dataType.getName());
DataType baseDataType = DataTypeUtilities.getBaseDataType(dataType);
if (baseDataType == null) {
return existingDataType != null ? List.of(existingDataType) : List.of();
}
SourceArchive sourceArchive = baseDataType.getSourceArchive();
if (sourceArchive != null && sourceArchive.getArchiveType() == ArchiveType.BUILT_IN) {
return existingDataType != null ? List.of(existingDataType) : List.of();
}
String baseTypeName = baseDataType.getName();
String decorations = dataType.getName().substring(baseTypeName.length());
List<DataType> list = new ArrayList<>();
for (DataType existingBaseDt : category.getDataTypesByBaseName(baseTypeName)) {
String name = existingBaseDt.getName() + decorations;
DataType dt = category.getDataType(name);
if (dt != null) {
list.add(dt);
}
}
return list;
}
/**
@ -1304,75 +1314,188 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
* categoryPath and has either the same name or a conflict variation of that
* name.
*
* @param dataType the dataType for which to find an equivalent existing
* dataType
* @param dataType the dataType for which to find an equivalent existing dataType
*/
private DataType findEquivalentDataTypeSameLocation(DataType dataType,
DataTypeConflictHandler handler) {
private DataType findEquivalentDataTypeSameLocation(DataType dataType) {
// first see if an exact match exists
String dtName = dataType.getName();
DataType existingDataType = getDataType(dataType.getCategoryPath(), dtName);
// Check exact name match
DataType existingDataType = getDataType(dataType.getCategoryPath(), dataType.getName());
// If the existing Data type is currently being resolved, its isEquivalent
// method is short circuited such that it will return true. So it is important
// to call the isEquivalent on the existing datatype and not the dataType.
if (existingDataType != null && isEquivalentDataType(dataType, existingDataType, handler)) {
if (existingDataType != null && existingDataType.isEquivalent(dataType)) {
return existingDataType;
}
Category category = getCategory(dataType.getCategoryPath());
if (category == null) {
return null;
}
List<DataType> relatedByName = category.getDataTypesByBaseName(dtName);
List<DataType> relatedByName = findDataTypesSameLocation(dataType);
for (DataType candidate : relatedByName) {
if (candidate != existingDataType &&
isEquivalentDataType(dataType, candidate, handler)) {
if (candidate != existingDataType && candidate.isEquivalent(dataType)) {
return candidate;
}
}
return null;
}
private DataType resolveDataTypeWithSource(DataType dataType, SourceArchive sourceArchive,
DataTypeConflictHandler handler) {
private DataType findDataTypeSameLocation(DataType dataType) {
// Check exact name match which is similar
DataType existingDataType = getDataType(dataType.getCategoryPath(), dataType.getName());
if (existingDataType != null &&
DataTypeUtilities.isSameKindDataType(dataType, existingDataType)) {
return existingDataType;
}
// check all conflict types
List<DataType> relatedByName = findDataTypesSameLocation(dataType);
for (DataType candidate : relatedByName) {
if (existingDataType == null) {
existingDataType = candidate;
}
if (DataTypeUtilities.isSameKindDataType(dataType, candidate)) {
return candidate;
}
}
return existingDataType;
}
/**
* Either finds an equivalent dataType with the same categoryPath and name (or
* conflict name) to the given dataType. Otherwise, it creates a new dataType in
* this archive equivalent to the given dataType. If a dataType exists with same
* path and name but is not equivalent, the handler will resolve the problem in
* one of 3 ways. 1) A new dataType will be created, but with a .conflict name
* 2) The existing dataType will be replaced by a resolved copy of the given
* dataType. 3) The existing dataType will be returned instead of a resolved
* version of the given dataType.
*
* @param dataType the dataType for which to return an equivalent dataType in
* this manager
* @param handler Used to handle collisions with dataTypes with same path and
* name that is
* @return resolved datatype
*/
private DataType resolveDataTypeNoSource(DataType dataType, DataTypeConflictHandler handler) {
DataType existingDataType = findEquivalentDataTypeSameLocation(dataType);
if (existingDataType != null) {
return existingDataType;
}
return resolveNoEquivalentFound(dataType, null, handler);
}
/**
* Perform datatype resolution for types originating from a source archive (excludes
* programs and built-in datatypes).
*
* @param dataType the dataType for which to return an equivalent dataType in
* this manager
* @param handler Used to handle collisions with dataTypes with same path and
* name that is
* @return resolved datatype
*/
private DataType resolveDataTypeWithSource(DataType dataType, DataTypeConflictHandler handler) {
SourceArchive sourceArchive = dataType.getSourceArchive();
// Do we have that dataType already resolved and associated with the source archive?
DataType existingDataType = getDataType(sourceArchive, dataType.getUniversalID());
if (existingDataType != null) {
if (!existingDataType.isEquivalent(dataType)) {
if (handler.shouldUpdate(dataType, existingDataType)) {
existingDataType.replaceWith(dataType);
existingDataType.setLastChangeTime(dataType.getLastChangeTime());
}
if (!existingDataType.isEquivalent(dataType) &&
handler.shouldUpdate(dataType, existingDataType)) {
existingDataType.replaceWith(dataType);
existingDataType.setLastChangeTime(dataType.getLastChangeTime());
}
return existingDataType;
}
// Do we have the same named data type in the same category already?
existingDataType = getDataType(dataType.getCategoryPath(), dataType.getName());
if (existingDataType == null) {
// Don't have a data type with this path name, so can create it.
return createDataType(dataType, dataType.getName(), sourceArchive, handler);
}
// If we have the same path name and the existing data type is a local data type
// and is equivalent to this one, then associate it with the source archive
if (isLocalSource(existingDataType) &&
isEquivalentDataType(dataType, existingDataType, handler)) {
return replaceEquivalentLocalWithSourceDataType(dataType, sourceArchive,
existingDataType);
existingDataType = findEquivalentDataTypeSameLocation(dataType);
if (existingDataType != null) {
if (isLocalSource(existingDataType)) {
// If we have an equivalent local data type associate it with the source archive
replaceEquivalentLocalWithSourceDataType(dataType, sourceArchive, existingDataType);
}
return existingDataType;
}
// Otherwise, we need to create a new Data type associated with the archive
// and it will possibly have a conflict name.
String dtName = getUnusedConflictName(dataType.getCategoryPath(), dataType.getName());
return createDataType(dataType, dtName, sourceArchive, handler);
return resolveNoEquivalentFound(dataType, sourceArchive, handler);
}
private DataType replaceEquivalentLocalWithSourceDataType(DataType dataType,
/**
* Complete datatype resolution after having attempted to find an existing equivalent type.
* An attempt is made to identify a conflicting datatype and determine a conflict resolution
* using the specified conflict handler.
* @param dataType datatype being resolved
* @param sourceArchive source archive associated with new type (may be null)
* @param handler datatype conflict handler
* @return resolved datatype (may be existing or newly added datatype)
*/
private DataType resolveNoEquivalentFound(DataType dataType, SourceArchive sourceArchive,
DataTypeConflictHandler handler) {
// If not found, do we have the same named data type in the same category already?
// (preference is given to similar kind of datatype when checking existing conflict types)
DataType existingDataType = findDataTypeSameLocation(dataType);
if (existingDataType == null) {
return createDataType(dataType, handler);
}
// So we have a dataType with the same path and name, but not equivalent, so use
// the conflictHandler to decide what to do.
ConflictResult result = handler.resolveConflict(dataType, existingDataType);
switch (result) {
case REPLACE_EXISTING: // new type replaces old conflicted type
try {
if (updateExistingDataType(existingDataType, dataType, sourceArchive)) {
return existingDataType;
}
renameToUnusedConflictName(existingDataType);
DataType newDataType =
createDataType(dataType, dataType.getName(), sourceArchive, handler);
try {
replace(existingDataType, newDataType);
}
catch (DataTypeDependencyException e) {
throw new IllegalArgumentException(
"Invalid datatype replacement: " + newDataType.getName(), e);
}
return newDataType;
}
catch (DataTypeDependencyException e) {
// new type refers to old type - fallthrough to RENAME_AND_ADD
// TODO: alternatively we could throw an exception
}
case RENAME_AND_ADD: // default handler behavior
return createDataType(dataType, handler);
default: // USE_EXISTING - new type is discarded and old conflicted type is returned
return existingDataType;
}
}
private DataType createDataType(DataType dataType, DataTypeConflictHandler handler) {
SourceArchive sourceArchive = dataType.getSourceArchive();
String dtName = getUnusedConflictName(dataType);
DataType newDataType = createDataType(dataType, dtName, sourceArchive, handler);
// resolving child data types could result in another copy of dataType in the
// manager depending upon the conflict handler - check again
DataType existingDataType = findEquivalentDataTypeSameLocation(dataType);
// If there is an equivalent datatype, remove the added type and return the existing
if (existingDataType != null && existingDataType != newDataType) {
removeInternal(newDataType, TaskMonitor.DUMMY);
return existingDataType;
}
return newDataType;
}
private void replaceEquivalentLocalWithSourceDataType(DataType dataType,
SourceArchive sourceArchive, DataType existingDataType) {
// Since it's equivalent, set its source, ID, and replace its components.
// TODO: Need a better way to do this.
@ -1383,7 +1506,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
existingDataType.setLastChangeTime(lastChangeTime);
existingDataType.setLastChangeTimeInSourceArchive(lastChangeTime);
dataTypeChanged(existingDataType, false);
return existingDataType;
}
private boolean isLocalSource(DataType dataType) {
@ -1986,8 +2108,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
// Set the datatype's universal ID to a newly generated universal ID,
// since we no longer want the source archive data type's universal ID.
if (dataType instanceof DataTypeDB) {
DataTypeDB dt = (DataTypeDB) dataType;
if (dataType instanceof DataTypeDB dt) {
dt.setUniversalID(UniversalIdGenerator.nextID());
}
@ -2038,8 +2159,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
if (dataType == null) {
return;
}
if (dataType instanceof DataTypeDB) {
((DataTypeDB) dataType).notifyDeleted();
if (dataType instanceof DataTypeDB dt) {
dt.notifyDeleted();
}
else {
buildSortedDataTypeList();
@ -2159,8 +2280,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
// otherwise, it probably belongs to this dataTypeManager, but it could a
// leftover after an undo. So make sure it really is there.
if (dataType instanceof DataTypeDB) {
DataTypeDB dtDb = (DataTypeDB) dataType;
if (dataType instanceof DataTypeDB dtDb) {
return dtCache.get(dtDb.getKey()) == dataType && !dtDb.isDeleted();
}
return builtIn2IdMap.containsKey(dataType);
@ -2599,46 +2719,37 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
DataType newDataType = null;
if (dt instanceof Array) {
Array array = (Array) dt;
if (dt instanceof Array array) {
newDataType = createArray(array.getDataType(), array.getNumElements(),
array.getElementLength(), cat, handler);
}
else if (dt instanceof Pointer) {
Pointer ptr = (Pointer) dt;
else if (dt instanceof Pointer ptr) {
int len = ptr.hasLanguageDependantLength() ? -1 : ptr.getLength();
newDataType = createPointer(ptr.getDataType(), cat, (byte) len, handler);
}
else if (dt instanceof BuiltInDataType) {
BuiltInDataType builtInDataType = (BuiltInDataType) dt;
else if (dt instanceof BuiltInDataType builtInDataType) {
newDataType = createBuiltIn(builtInDataType, cat);
}
else if (dt instanceof StructureInternal) {
StructureInternal structure = (StructureInternal) dt;
else if (dt instanceof StructureInternal structure) {
newDataType = createStructure(structure, name, cat, sourceArchiveIdValue,
id.getValue());
}
else if (dt instanceof TypeDef) {
TypeDef typedef = (TypeDef) dt;
else if (dt instanceof TypeDef typedef) {
newDataType =
createTypeDef(typedef, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof UnionInternal) {
UnionInternal union = (UnionInternal) dt;
else if (dt instanceof UnionInternal union) {
newDataType =
createUnion(union, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof Enum) {
Enum enumm = (Enum) dt;
else if (dt instanceof Enum enumm) {
newDataType = createEnum(enumm, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof FunctionDefinition) {
FunctionDefinition funDef = (FunctionDefinition) dt;
else if (dt instanceof FunctionDefinition funDef) {
newDataType = createFunctionDefinition(funDef, name, cat, sourceArchiveIdValue,
id.getValue());
}
else if (dt instanceof MissingBuiltInDataType) {
MissingBuiltInDataType missingBuiltInDataType = (MissingBuiltInDataType) dt;
else if (dt instanceof MissingBuiltInDataType missingBuiltInDataType) {
newDataType = createMissingBuiltIn(missingBuiltInDataType, cat);
}
else {
@ -3391,8 +3502,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
@Override
public Set<DataType> getDataTypesContaining(DataType dataType) {
if (dataType instanceof DataTypeDB) {
DataTypeDB dataTypeDb = (DataTypeDB) dataType;
if (dataType instanceof DataTypeDB dataTypeDb) {
if (dataTypeDb.getDataTypeManager() != this) {
return Set.of();
}

View file

@ -205,7 +205,7 @@ public class DataTypeUtilities {
}
/**
* Returns true if the two dataTypes have the same sourceArchive and the same UniversalID OR are
* Returns true if two dataTypes have the same sourceArchive and the same UniversalID OR are
* equivalent
*
* @param dataType1 first data type (if invoked by DB object or manager, this argument must
@ -223,6 +223,79 @@ public class DataTypeUtilities {
return dataType1.isEquivalent(dataType2);
}
/**
* Determine if two dataTypes are the same kind of datatype without considering naming or
* component makeup. The use of Typedefs is ignored and stripped away for comparison.
* This method also ignores details about most built-in types, pointers and arrays
* (e.g., number of elements or size). Implementations of the following abstract classes
* will be treated as the same kind as another datatype which extends the same abstract
* class:
* <ul>
* <li>{@link AbstractIntegerDataType}</li>
* <li>{@link AbstractFloatDataType}</li>
* <li>{@link AbstractStringDataType}</li>
* </ul>
* Other uses of {@link BuiltInDataType} must match the specific implementation class.
* @param dataType1 first data type
* @param dataType2 second data type
* @return true if the two dataTypes are the same basic kind else false
*/
public static boolean isSameKindDataType(DataType dataType1, DataType dataType2) {
while (true) {
if (dataType1 == dataType2) {
return true;
}
// Ignore the use of typedefs - strip away
if (dataType1 instanceof TypeDef td1) {
dataType1 = td1.getBaseDataType();
}
if (dataType2 instanceof TypeDef td2) {
dataType2 = td2.getBaseDataType();
}
if (dataType1 instanceof Pointer p1 && dataType2 instanceof Pointer p2) {
dataType1 = p1.getDataType();
dataType2 = p2.getDataType();
}
else if (dataType2 instanceof Array a1 && dataType2 instanceof Array a2) {
dataType1 = a1.getDataType();
dataType2 = a2.getDataType();
}
else if (dataType1 instanceof Enum) {
return dataType2 instanceof Enum;
}
else if (dataType1 instanceof Structure) {
return dataType2 instanceof Structure;
}
else if (dataType1 instanceof Union) {
return dataType2 instanceof Union;
}
else if (dataType1 instanceof BuiltInDataType dt1) {
return isSameKindBuiltInDataType(dt1, dataType2);
}
else {
return false;
}
}
}
private static boolean isSameKindBuiltInDataType(BuiltInDataType dataType1,
DataType dataType2) {
if (dataType1 instanceof BuiltIn) {
// Same kind if both types share a common BuiltIn implementation
Class<?> baseClass = dataType1.getClass().getSuperclass();
Class<?> superClass;
while ((superClass = baseClass.getSuperclass()) != BuiltIn.class) {
baseClass = superClass;
}
return baseClass.isAssignableFrom(dataType2.getClass());
}
// Ensure built-in implementation class is the same
return dataType1.getClass().equals(dataType2.getClass());
}
/**
* Get the name of a data type with all conflict naming patterns removed.
*

View file

@ -90,54 +90,54 @@ public class SourceArchiveUpgradeMap {
return new String[] { "short", "int", "long", "longlong", "wchar_t", "bool" };
}
}
private static class SourceArchiveImpl implements SourceArchive {
class SourceArchiveImpl implements SourceArchive {
private final UniversalID id;
private final String archiveName;
private final UniversalID id;
private final String archiveName;
public SourceArchiveImpl(UniversalID id, String archiveName) {
this.id = id;
this.archiveName = archiveName;
}
public SourceArchiveImpl(UniversalID id, String archiveName) {
this.id = id;
this.archiveName = archiveName;
}
public SourceArchiveImpl() {
id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID;
archiveName = "";
}
public SourceArchiveImpl() {
id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID;
archiveName = "";
}
public ArchiveType getArchiveType() {
return ArchiveType.FILE;
}
public ArchiveType getArchiveType() {
return ArchiveType.FILE;
}
public String getDomainFileID() {
return null;
}
public String getDomainFileID() {
return null;
}
public long getLastSyncTime() {
return 0;
}
public long getLastSyncTime() {
return 0;
}
public String getName() {
return archiveName;
}
public String getName() {
return archiveName;
}
public UniversalID getSourceArchiveID() {
return id;
}
public UniversalID getSourceArchiveID() {
return id;
}
public boolean isDirty() {
return false;
}
public boolean isDirty() {
return false;
}
public void setDirtyFlag(boolean dirty) {
}
public void setDirtyFlag(boolean dirty) {
}
public void setLastSyncTime(long time) {
}
public void setLastSyncTime(long time) {
}
public void setName(String name) {
}
public void setName(String name) {
}
}