Initial implementation for Bug 321411 - [hierarchy] Replace OTTypeHierarchy with adapting the original TypeHierarchy
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index b516c02..1dea119 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -119,6 +119,20 @@
this.hierarchy.addRootClass(focusType);
}
}
+ /** Wrapper method as hook for OTTypeHierarchies. */
+ public void hookableConnect(
+ ReferenceBinding focusType,
+ ReferenceBinding typeBinding,
+ IGenericType type,
+ IType typeHandle,
+ boolean isPhantom,
+ IType superclassHandle,
+ IType[] tsuperclassHandles,
+ boolean[] arePhantoms,
+ IType[] superinterfaceHandles)
+ {
+ connect(type, typeHandle, superclassHandle, superinterfaceHandles);
+ }
/**
* Connect the supplied type to its superclass & superinterfaces.
* The superclass & superinterfaces are the identical binary or source types as
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 0628bea..0a64b30 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -37,8 +37,11 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
@@ -169,9 +172,14 @@
this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)sourceType).getHandle().getCompilationUnit();
+//{ObjectTeams: swap order so rememberAllTypes catches also copy-inherited roles:
+/* orig:
rememberAllTypes(unit, cu, false);
-
+ */
this.lookupEnvironment.completeTypeBindings(unit, true/*build constructor only*/);
+// :giro
+ rememberAllTypes(unit, cu, false);
+// SH}
} catch (AbortCompilation e) {
// missing 'java.lang' package: ignore
}
@@ -429,7 +437,12 @@
this.typeBindings[this.typeIndex] = typeBinding;
}
private void remember(IType type, ReferenceBinding typeBinding) {
+//{ObjectTeams: for phantom roles avoid hitting the JME (phantom has no info) but proceed into else as to record what we have
+/* orig:
if (((CompilationUnit)type.getCompilationUnit()).isOpen()) {
+ :giro */
+ if (((CompilationUnit)type.getCompilationUnit()).isOpen() && !isPurelyCopiedRole(typeBinding)) {
+// SH}
try {
IGenericType genericType = (IGenericType)((JavaElement)type).getElementInfo();
remember(genericType, typeBinding);
@@ -483,6 +496,13 @@
}
}
+//{ObjectTeams: helper for above:
+private boolean isPurelyCopiedRole(ReferenceBinding typeBinding) {
+ if (typeBinding == null || typeBinding.roleModel == null)
+ return false;
+ return typeBinding.roleModel.isPurelyCopied();
+}
+// SH}
/*
* Remembers all type bindings defined in the given parsed unit, adding local/anonymous types if specified.
*/
@@ -628,6 +648,24 @@
typeBinding = typeBinding.roleModel.getClassPartBinding();
}
}
+ if (typeBinding.isSynthInterface())
+ continue; // don't report synthetic ifc parts
+
+ // prepare additional info to pass to the builder (viz. the OTTypeHierarchies team)
+ IType[] tsuperClasses = new IType[0];
+ boolean[] arePhantoms = new boolean[0]; // one flag for each role in tsuperClasses
+ if (typeBinding.isSourceRole()) {
+ ReferenceBinding[] tsuperBindings = typeBinding.roleModel.getTSuperRoleBindings();
+ if (tsuperBindings.length > 0) {
+ tsuperClasses = new IType[tsuperBindings.length];
+ arePhantoms = new boolean[tsuperBindings.length];
+ for (int i = 0; i < tsuperBindings.length; i++) {
+ tsuperClasses[i] = getHandle(tsuperBindings[i]);
+ arePhantoms[i] = tsuperBindings[i].roleModel.isPurelyCopied();
+ }
+ }
+ }
+ boolean isPhantom = typeBinding.roleModel != null && typeBinding.roleModel.isPurelyCopied();
// SH}
if (typeBinding.isInterface()){ // do not connect interfaces to Object
superclass = null;
@@ -636,7 +674,12 @@
}
IType[] superinterfaces = findSuperInterfaces(suppliedType, typeBinding);
+//{ObjectTeams: also announce tsuper classes and info about phantomness:
+/* orig:
this.builder.connect(suppliedType, this.builder.getHandle(suppliedType, typeBinding), superclass, superinterfaces);
+ :giro */
+ this.builder.hookableConnect(this.focusType, typeBinding, suppliedType, this.builder.getHandle(suppliedType, typeBinding), isPhantom, superclass, tsuperClasses, arePhantoms, superinterfaces);
+// SH}
}
// add java.lang.Object only if the super class is not missing
if (objectIndex > -1 && (!this.hasMissingSuperClass || this.focusType == null)) {
@@ -644,6 +687,17 @@
this.builder.connect(objectType, this.builder.getHandle(objectType, this.typeBindings[objectIndex]), null, null);
}
}
+//{ObjectTeams:
+private IType getHandle(ReferenceBinding typeBinding) {
+ for (int t = this.typeIndex; t >= 0; t--) {
+ if (this.typeBindings[t] == typeBinding) {
+ return this.builder.getHandle(this.typeModels[t], typeBinding);
+ }
+ }
+ JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Inconsistency between typeIndex and typeBindings")); //$NON-NLS-1$
+ return null;
+}
+// SH}
private void reset(){
this.lookupEnvironment.reset();
@@ -1013,61 +1067,17 @@
// if (superclass != null && superclass.id == TypeIds.T_JavaLangObject && subType.isHierarchyInconsistent()) return false;
if (subTypeOfType(superclass, typeBinding)) return true;
ReferenceBinding[] superInterfaces = subType.superInterfaces();
+// {ObjectTeams: check implicit inheritance:
+ if (subType.isSourceRole())
+ for (ReferenceBinding tsuperBinding : subType.roleModel.getTSuperRoleBindings())
+ if (subTypeOfType(tsuperBinding, typeBinding))
+ return true;
+// SH}
if (superInterfaces != null) {
-// {OTDTUI: Subtype check for roles and non-roles:
- if (subType.isRole())
- {
- // Role interface -> check superinterfaces
- if (subType.isRegularInterface())
- {
- for (int i = 0, length = superInterfaces.length; i < length; i++)
- {
- if (subTypeOfType(superInterfaces[i], typeBinding)) return true;
- }
- }
- // Interface part of roles -> check superinterfaces, class part
- else if (subType.isSynthInterface())
- {
- for (int i = 0, length = superInterfaces.length; i < length; i++)
- {
- if (superInterfaces[i].isSynthInterface())
- {
- // Ignore (tsuper's) synthetic.
- // I don't know why ak skipped them in earlier revisions,
- // but it seems like we don't need to consider implicit
- // inheritance here.
- continue;
- }
- if (subTypeOfType(superInterfaces[i], typeBinding)) return true;
- }
- if (typeBinding.isClass())
- {
- ReferenceBinding classPart = subType.roleModel.getClassPartBinding();
- if (subTypeOfType(classPart, typeBinding)) return true;
- }
- }
- // role class -> check superinterfaces
- else
- {
- if (typeBinding.isInterface())
- {
- for (int i = 0, length = superInterfaces.length; i < length; i++)
- {
- if (subTypeOfType(superInterfaces[i], typeBinding)) return true;
- }
- }
- }
- }
- // non role types -> check superinterfaces
- else {
-// orig:
for (int i = 0, length = superInterfaces.length; i < length; i++) {
ReferenceBinding superInterface = (ReferenceBinding) superInterfaces[i].erasure();
if (subTypeOfType(superInterface, typeBinding)) return true;
}
-// :giro
- }
-// mkr}
}
return false;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index bf54a70..ff59b38 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -24,6 +24,7 @@
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
@@ -38,6 +39,8 @@
import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern;
import org.eclipse.jdt.internal.core.util.HandleFactory;
import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.core.IRoleType;
+import org.eclipse.objectteams.otdt.core.OTModelManager;
public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants {
public static final int MAXTICKS = 800; // heuristic so that there still progress for deep hierachies
@@ -487,6 +490,9 @@
&& !foundSuperNames.containsKey(typeName)){
foundSuperNames.put(typeName, typeName);
queue.add(typeName);
+//{ObjectTeams: check if we need additional traversal role->enclosing team in order to cover implicit inheritance, too.
+ reportIndexMatch(record, queue, foundSuperNames);
+// SH}
}
return true;
}
@@ -509,6 +515,12 @@
int ticks = 0;
queue.add(type.getElementName().toCharArray());
+//{ObjectTeams: additional traversal role->enclosing team in order to cover implicit inheritance, too.
+ while (OTModelManager.isRole(type)) {
+ type = ((IRoleType)OTModelManager.getOTElement(type)).getTeamJavaType();
+ queue.add(type.getElementName().toCharArray());
+ }
+// SH}
try {
while (queue.start <= queue.end) {
if (progressMonitor != null && progressMonitor.isCanceled()) return;
@@ -544,4 +556,25 @@
job.finished();
}
}
+//{ObjectTeams: additional traversal role->enclosing team in order to cover implicit inheritance, too.
+static void reportIndexMatch(SuperTypeReferencePattern record, Queue q, HashtableOfObject foundSuperNames) {
+ if ((record.modifiers & ExtraCompilerModifiers.AccRole) != 0) {
+ char[][] enclosingNames = CharOperation.splitOn('$', record.enclosingTypeName);
+ char[] teamSimpleName;
+ if (enclosingNames.length > 0) {
+ teamSimpleName = enclosingNames[enclosingNames.length-1];
+ } else {
+ char[][] packageNames = CharOperation.splitOn('$', record.pkgName);
+ if (packageNames.length > 0)
+ teamSimpleName = packageNames[packageNames.length-1];
+ else
+ return; // no success (enclosing team name not found)
+ }
+ if (!foundSuperNames.containsKey(teamSimpleName)) {
+ q.add(teamSimpleName);
+ foundSuperNames.put(teamSimpleName, teamSimpleName);
+ }
+ }
+}
+// SH}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
index 742d915..dd4003d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
@@ -33,6 +33,7 @@
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.core.IOTType;
/**
* @see ITypeHierarchy
@@ -154,6 +155,10 @@
* Creates a TypeHierarchy on the given type.
*/
public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) {
+//{ObjectTeams: always unwrap OTTypes, hierarchy only stores plain java types (SourceType, BinaryType):
+ if (type instanceof IOTType)
+ type = (IType) ((IOTType) type).getCorrespondingJavaElement();
+// SH}
this.focusType = type == null ? null : (IType) ((JavaElement) type).unresolved(); // unsure the focus type is unresolved (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92357)
this.workingCopies = workingCopies;
this.computeSubtypes = computeSubtypes;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
index cc256b6..dba3104 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
@@ -51,7 +51,7 @@
/* orig:
public static final String SIGNATURE= "INDEX VERSION 1.126"; //$NON-NLS-1$
:giro */
-public static final String SIGNATURE= "INDEX VERSION 1.126 OT1"; //$NON-NLS-1$
+public static final String SIGNATURE= "INDEX VERSION 1.126 OT2"; //$NON-NLS-1$
// SH}
private static final char[] SIGNATURE_CHARS = SIGNATURE.toCharArray();
public static boolean DEBUG = false;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
index 8d568e9..76a6bac 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
@@ -116,7 +116,12 @@
int simpleLength = simpleName == null ? 0 : simpleName.length;
int enclosingLength = enclosingTypeName == null ? 0 : enclosingTypeName.length;
int packageLength = packageName == null ? 0 : packageName.length;
+//{ObjectTeams: one more char for modifiers
+/* orig:
char[] result = new char[superLength + superQLength + simpleLength + enclosingLength + typeParametersLength + packageLength + 9];
+ :giro */
+ char[] result = new char[superLength + superQLength + simpleLength + enclosingLength + typeParametersLength + packageLength + 10];
+// SH}
int pos = 0;
if (superLength > 0) {
System.arraycopy(superSimpleName, 0, result, pos, superLength);
@@ -150,7 +155,13 @@
result[pos++] = SEPARATOR;
result[pos++] = superClassOrInterface;
result[pos++] = classOrInterface;
+//{ObjectTeams: expand to also cover AccRole:
+/* orig:
result[pos] = (char) modifiers;
+ :giro */
+ result[pos++] = (char) modifiers;
+ result[pos] = (char) (modifiers>>16);
+// SH}
return result;
}
@@ -232,7 +243,12 @@
this.superClassOrInterface = key[slash + 1];
this.classOrInterface = key[slash + 2];
+//{ObjectTeams: expanded to also cover AccRole:
+/* orig:
this.modifiers = key[slash + 3]; // implicit cast to int type
+ :giro */
+ this.modifiers = key[slash + 3] + (key[slash + 4]<<16);
+// SH}
}
public SearchPattern getBlankPattern() {
return new SuperTypeReferencePattern(R_EXACT_MATCH | R_CASE_SENSITIVE);