Initial implementation for Bug 321411 - [hierarchy] Replace OTTypeHierarchy with adapting the original TypeHierarchy
diff --git a/plugins/org.eclipse.objectteams.otdt/.classpath b/plugins/org.eclipse.objectteams.otdt/.classpath
index 304e861..9b7e6c5 100644
--- a/plugins/org.eclipse.objectteams.otdt/.classpath
+++ b/plugins/org.eclipse.objectteams.otdt/.classpath
@@ -2,6 +2,7 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="OTRE"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/plugins/org.eclipse.objectteams.otdt/.project b/plugins/org.eclipse.objectteams.otdt/.project
index a40a654..7bcffe8 100644
--- a/plugins/org.eclipse.objectteams.otdt/.project
+++ b/plugins/org.eclipse.objectteams.otdt/.project
@@ -6,7 +6,7 @@
</projects>
<buildSpec>
<buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
+ <name>org.eclipse.objectteams.otdt.builder.OTJBuilder</name>
<arguments>
</arguments>
</buildCommand>
@@ -24,5 +24,6 @@
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.objectteams.otdt.OTJavaNature</nature>
</natures>
</projectDescription>
diff --git a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
index 664f29d..70aeb3c 100644
--- a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
@@ -3,9 +3,12 @@
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otdt;singleton:=true
Bundle-Version: 0.7.1.qualifier
+Bundle-ClassPath: otdtcoreext.jar
Bundle-Activator: org.eclipse.objectteams.otdt.core.ext.OTDTPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
+Export-Package: org.eclipse.objectteams.otdt.core.ext,
+ org.eclipse.objectteams.otdt.core.hierarchy
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
org.eclipse.core.resources,
org.eclipse.jdt.core;bundle-version="[3.6.0.v_OTDT_r070,3.6.0.v_OTDT_r080)",
@@ -13,8 +16,7 @@
org.eclipse.debug.core,
org.eclipse.osgi,
org.eclipse.objectteams.otequinox.branding,
- org.eclipse.objectteams.runtime;bundle-version="[0.7.0,0.8.0)"
-Bundle-ActivationPolicy: lazy
-Bundle-ClassPath: otdtcoreext.jar
-Export-Package: org.eclipse.objectteams.otdt.core.ext
+ org.eclipse.objectteams.runtime;bundle-version="[0.7.0,0.8.0)",
+ org.eclipse.objectteams.otequinox
Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt/plugin.xml b/plugins/org.eclipse.objectteams.otdt/plugin.xml
index 84bc547..b1df675 100644
--- a/plugins/org.eclipse.objectteams.otdt/plugin.xml
+++ b/plugins/org.eclipse.objectteams.otdt/plugin.xml
@@ -50,4 +50,19 @@
id="OTRE"
class="org.eclipse.objectteams.otdt.core.ext.OTREContainerInitializer"/>
</extension>
+ <extension
+ point="org.eclipse.objectteams.otequinox.aspectBindings">
+ <aspectBinding
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+ <basePlugin
+ icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.gif"
+ id="org.eclipse.jdt.core">
+ </basePlugin>
+ <team
+ activation="ALL_THREADS"
+ class="org.eclipse.objectteams.otdt.core.hierarchy.OTTypeHierarchies"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+ </team>
+ </aspectBinding>
+ </extension>
</plugin>
diff --git a/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/hierarchy/OTTypeHierarchies.java b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/hierarchy/OTTypeHierarchies.java
new file mode 100644
index 0000000..4de99fb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/hierarchy/OTTypeHierarchies.java
@@ -0,0 +1,667 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2010 GK Software AG
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.core.hierarchy;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.core.JavaModelStatus;
+import org.eclipse.objectteams.otdt.core.IOTType;
+import org.eclipse.objectteams.otdt.core.OTModelManager;
+
+// both base type and directly used:
+import org.eclipse.jdt.core.IType;
+
+import base org.eclipse.jdt.internal.core.BinaryType;
+import base org.eclipse.jdt.internal.core.SourceType;
+import base org.eclipse.jdt.internal.core.hierarchy.HierarchyBuilder;
+import base org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
+import base org.eclipse.objectteams.otdt.core.PhantomType;
+import base org.eclipse.objectteams.otdt.internal.core.OTType;
+
+/**
+ * Adapt the regular Java TypeHierarchy as to handle implicit inheritance, too.
+ *
+ *
+ * @author stephan
+ */
+@SuppressWarnings("restriction")
+public team class OTTypeHierarchies {
+
+ /** How does a given type relate to the focus type? */
+ enum FocusRelation {
+ /** a type is a subtype of the focus type. */
+ BELOW,
+ /** a type is the focus type itself. */
+ EQUAL,
+ /** a type is a supertype of the focus type. */
+ ABOVE,
+ /** a type is neither sub- nor supertype of the focus type. */
+ UNRELATED;
+
+ public static FocusRelation compute(ReferenceBinding focusType, ReferenceBinding typeBinding) {
+ if (focusType.isRole())
+ focusType = focusType.getRealType();
+ if (typeBinding.isRole())
+ typeBinding = typeBinding.getRealType();
+ if (focusType.equals(typeBinding)) return EQUAL;
+ if (focusType.isCompatibleWith(typeBinding)) return ABOVE;
+ if (typeBinding.isCompatibleWith(focusType)) return BELOW;
+ return UNRELATED;
+ }
+ }
+
+ private static final IType[] NO_TYPE = new IType[0];
+
+ // === singleton infrastructure: ===
+
+ private static OTTypeHierarchies instance;
+ public OTTypeHierarchies() {
+ instance = this;
+ }
+ /** Get the singleton instance of this team, which was created and activated by OT/Equinox. */
+ public static OTTypeHierarchies getInstance() { return instance; }
+
+
+ /**
+ * The stateful part of this team, implemented as a nested team.
+ */
+ protected team class OTTypeHierarchy playedBy TypeHierarchy
+ {
+ // === "Imports" (callout) from plain TypeHierarchy: ===
+
+ @SuppressWarnings("decapsulation") IType getFocusType() -> get IType focusType;
+ ConnectedType getSuperclass(IType type) -> IType getSuperclass(IType type);
+ ConnectedType[] getAllSuperclassesUnfiltered(IType type) -> IType[] getAllSuperclasses(IType type);
+ IType[] getSuperInterfaces(IType type) -> IType[] getSuperInterfaces(IType type);
+ IType[] getAllSuperInterfaces(IType type) -> IType[] getAllSuperInterfaces(IType type);
+
+
+ // === Adapt TypeHierarchy (callin bindings): ===
+
+ precedence unwrapping, filtering1, superlinearize; // order: outer callins unwrap and filter, inner callin performs computation
+ precedence filtering2, tsuperadding;
+
+ // --- considure implicit inheritance for some queries: ----
+
+ // make getSuperclass() traverse the superclass linearization of the focus type:
+ superlinearize:
+ ConnectedType getSuperclassLinearized(ConnectedType type) <- replace IType getSuperclass(IType type);
+
+ // augment original queries to capture tsub-types, too:
+ @SuppressWarnings("decapsulation")
+ addTSubs <- replace getSubtypesForType; // adjust internal method as to capture calls from getAllSubtypes(IType), too.
+ tsuperadding:
+ addTSubs <- replace getSubclasses;
+
+ // --- filtering (duplicates and phantoms) and unwrapping (OTTypes): ---
+
+ // make some methods aware of our phantom mode:
+ filtering1:
+ ConnectedType[] phantomFilterWrapper()
+ <- replace
+ IType[] getAllClasses(),
+ IType[] getImplementingClasses(IType type),
+ IType[] getAllSuperclasses(IType type)
+ when (!this.phantomMode);
+
+ // filter intermediate results only at these top-level queries:
+ filtering2:
+ filterDuplicatesAndPhantoms <- replace getSubclasses, getSubtypes, getAllSubtypes, getImplementingClasses; // includes unwrapping of OTTypes
+
+ // all top-level queries unwrap and given OTTypes:
+ unwrapping:
+ ensureJavaType <- replace getAllSuperclasses, getAllSuperInterfaces, getAllSupertypes,
+ getCachedFlags, getExtendingInterfaces,
+ getSuperclass, getSuperInterfaces, getSupertypes;
+
+ /**
+ * This role adds to ITypes the capability of connecting to all direct and indirect tsuper types,
+ * which includes linearization of all super types (implicit & explicit).
+ */
+ @SuppressWarnings("abstractrelevantrole")
+ protected abstract class ConnectedType playedBy IType
+ {
+ /** Is this type a phantom role? */
+ protected boolean isPhantom;
+
+ /** The direct tsuper types of this type. */
+ protected ConnectedType[] directTSupers;
+
+ /** All direct & indirect tsuper classes in a linearized form. All classes in this list have the same simple name. */
+ protected List<ConnectedType> allTSupersLinearized;
+
+ /** This type's relation to the focus type. */
+ private FocusRelation focusRelation;
+
+ // the last item in allTSupersLinearized, used as a token for switching from implicit to explicit supers
+ private ConnectedType lastTSuper = null;
+
+ /** the root of the tsuper chain through which this connected type was reached. */
+ protected ConnectedType tsuperChainRoot;
+
+ /** All known direct tsub types of this type. */
+ protected Set<ConnectedType> knownTSubTypes;
+
+
+ protected ConnectedType(IType type) {
+ this.tsuperChainRoot = this;
+ }
+
+ public void init(boolean isPhantom, ConnectedType[] tsuperclassHandles, FocusRelation focusRelation) {
+ this.isPhantom = isPhantom;
+ this.directTSupers = tsuperclassHandles;
+ this.focusRelation = focusRelation;
+ }
+
+ /** Combine indirect tsuper classes into the list of all linearized tsuper types. */
+ @SuppressWarnings("ambiguouslowering") // method contains takes an Object argument
+ public void combineTSupers(ConnectedType focusLayerType, ConnectedType[] tsuperclassHandles) {
+ this.tsuperChainRoot = focusLayerType.tsuperChainRoot;
+ if (this.allTSupersLinearized == null)
+ this.allTSupersLinearized = new LinkedList<ConnectedType>();
+ for (ConnectedType type : tsuperclassHandles)
+ if (!this.allTSupersLinearized.contains(type))
+ this.allTSupersLinearized.add(type);
+ }
+
+ /** Get the next type in the tsuper linearization. */
+ protected ConnectedType getTSuperType() {
+ if (this.focusRelation == FocusRelation.BELOW) {
+ // only follow the path towards the focus type:
+ if (this.directTSupers != null)
+ for (ConnectedType directTSuper : this.directTSupers)
+ if (directTSuper.focusRelation == FocusRelation.EQUAL || directTSuper.focusRelation == FocusRelation.BELOW)
+ return directTSuper;
+ return null; // no tsuper leading to focus
+ }
+ // shortcut if no tsupers:
+ if (this.allTSupersLinearized == null || this.allTSupersLinearized.size() == 0)
+ return null;
+ // when starting from the focus layer return the first tsuper role:
+ if (isInFocusLayer(this))
+ return this.allTSupersLinearized.get(0);
+ // when type is contained in the list of tsuperRoles return the next tsuper role from the list
+ for (int i = 0; i < this.allTSupersLinearized.size()-1; i++)
+ if (this.allTSupersLinearized.get(i) == this)
+ return this.allTSupersLinearized.get(i+1);
+ return null; // end reached
+ }
+
+ /** Is this the last element in the list of tsuper roles? */
+ protected boolean isLastTSuper() {
+ if (this.allTSupersLinearized == null || this.allTSupersLinearized.size() == 0) // optimize: don's store empty list?
+ return false;
+ if (this.lastTSuper == null)
+ this.lastTSuper = this.allTSupersLinearized.get(this.allTSupersLinearized.size()-1);
+ return this.lastTSuper == this;
+ }
+
+ /** If this is a phantom type, get the real tsuper class that this is derived (copied) from. */
+ protected ConnectedType getRealTSuper() throws JavaModelException {
+ if (!isPhantom)
+ return this;
+ if (this.allTSupersLinearized != null)
+ for(ConnectedType other : this.allTSupersLinearized)
+ if (!other.isPhantom)
+ return other;
+ throw new JavaModelException(new JavaModelStatus(JavaModelStatus.ERROR, this, "no non-phantom type found in allTSupersLinearized")); //$NON-NLS-1$
+ }
+
+ /** Get all tsuper types yet respecting phantom mode. */
+ protected ConnectedType[] getAllTSuperTypes()
+ {
+ if (this.focusRelation == FocusRelation.BELOW && this.directTSupers != null) {
+ // special handling for types below the focus: transitively collect tsupers:
+ ConnectedType direct = getTSuperType(); // only the one path towards focus
+ if (direct == null)
+ return new ConnectedType[0];
+ ConnectedType[] indirect = direct.getAllTSuperTypes(); // NB: recursion may enter the focus cone
+ if (indirect == null)
+ return new ConnectedType[] {direct};
+ // merge direct and indirect:
+ int len = indirect.length;
+ ConnectedType[] result = new ConnectedType[len+1];
+ result[0] = direct;
+ System.arraycopy(indirect, 0, result, 1, len);
+ return result;
+ }
+
+ int size;
+ if (this.allTSupersLinearized != null && (size = this.allTSupersLinearized.size()) > 0)
+ {
+ // focus level => all types from the linearization:
+ if (isInFocusLayer(this))
+ return this.allTSupersLinearized.toArray(new ConnectedType[size]);
+
+ // not focus, search in linearization for this type ...
+ int skip = 0;
+ boolean found = false;
+ while (skip < size)
+ if (this.allTSupersLinearized.get(skip++) == this) {
+ found = true;
+ break;
+ }
+ if (found) { // .. and take the tail after this type:
+ if (skip < size) { // if found at last pos, there's no tail
+ ConnectedType[] result = new ConnectedType[size-skip];
+ for (int i=0; skip<size;)
+ result[i++] = this.allTSupersLinearized.get(skip++);
+ return result;
+ }
+ } else {
+ System.out.println("HERE "+this);
+ // not focus type but seemingly bottom of the lattice, take all known tsupers
+ return this.allTSupersLinearized.toArray(new ConnectedType[size]);
+ }
+ }
+ return new ConnectedType[0];
+ }
+
+ /** Register a known tsub type of this type. */
+ protected void addTSubType(ConnectedType tsub) {
+ if (this.knownTSubTypes == null)
+ this.knownTSubTypes = new HashSet<ConnectedType>();
+ this.knownTSubTypes.add(tsub);
+ }
+
+ toString => toString; // for debugging
+
+ }
+ // binding source variant of IType
+ protected class ConnectedSourceType extends ConnectedType playedBy SourceType { /*just class binding, no details*/ }
+
+ // binding binary variant of IType
+ protected class ConnectedBinaryType extends ConnectedType playedBy BinaryType { /*just class binding, no details*/ }
+
+ // binding binary variant of IType
+ protected class ConnectedPhantomType extends ConnectedType playedBy PhantomType { /*just class binding, no details*/ }
+
+ // binding binary variant of IType
+ protected class ConnectedOTType extends ConnectedType playedBy OTType { /*just class binding, no details*/ }
+
+ // === start main part of nested team OTTypeHierarchy ===
+
+ /** Should the hierarchy show phantom roles? */
+ protected boolean phantomMode;
+
+ /**
+ * Connect the found tsuper classes into the connected type for the given type.
+ */
+ protected void connectTSupers(IType as ConnectedType connectedType,
+ boolean isPhantom,
+ IType as ConnectedType tsuperclassHandles[],
+ boolean[] arePhantoms,
+ FocusRelation focusRelation)
+ {
+ connectedType.init(isPhantom, tsuperclassHandles, focusRelation);
+
+ // connect tsuperclassHandles into the appropriate ConnectedType:
+ switch (focusRelation) {
+ case EQUAL:
+ connectedType.allTSupersLinearized = new LinkedList<ConnectedType>();
+ for (int i = 0; i < tsuperclassHandles.length; i++)
+ connectedType.allTSupersLinearized.add(tsuperclassHandles[i]);
+ break;
+ case ABOVE:
+ ConnectedType focusLayerType = connectedType.tsuperChainRoot;
+ focusLayerType.combineTSupers(focusLayerType, tsuperclassHandles);
+ connectedType.allTSupersLinearized = focusLayerType.allTSupersLinearized; // share the same list
+ break;
+ case BELOW:
+ // don't merge into focus' up-chain
+ break;
+ default: // UNRELATED
+// if (isInFocusLayer(connectedType)) {
+// connectedType.allTSupersLinearized = new LinkedList<ConnectedType>();
+// for (int i = 0; i < tsuperclassHandles.length; i++)
+// connectedType.allTSupersLinearized.add(tsuperclassHandles[i]);
+// }
+ // otherwise shouldn't be relevant?
+ }
+ // connect each in tsuperclassHandles back to the tsuperChainRoot:
+ for (int i = 0; i < tsuperclassHandles.length; i++) {
+ if (focusRelation == FocusRelation.EQUAL || focusRelation == FocusRelation.ABOVE)
+ tsuperclassHandles[i].tsuperChainRoot = connectedType.tsuperChainRoot;
+ tsuperclassHandles[i].isPhantom = arePhantoms[i];
+ // and remember the type-tsub link:
+ tsuperclassHandles[i].addTSubType(connectedType);
+ }
+ }
+
+ boolean isInFocusLayer(IType type) {
+ IType focusType = getFocusType();
+ if (type.equals(focusType))
+ return true;
+ return focusType.getParent().equals(type.getParent()); // FIXME(SH) elaborate more
+ }
+
+ boolean isStrictlyBelowFocusType(IType type) {
+ IType focusType = getFocusType();
+ if (focusType.equals(type))
+ return false;
+ return isBelowFocusType(focusType, type);
+ }
+
+ private boolean isBelowFocusType(IType focusType, IType type) {
+ if (focusType.equals(type))
+ return true;
+ return false;
+ }
+
+ /** Given that 'type' is element of a superclass linearization return the next super in the chain. */
+ @SuppressWarnings("basecall")
+ callin ConnectedType getSuperclassLinearized(ConnectedType type) {
+ // check for tsuper type in the computed list:
+ ConnectedType tsuperType = type.getTSuperType();
+ if (tsuperType != null)
+ return tsuperType;
+ // if type is the last in the list ...
+ if (type.isLastTSuper()) {
+ // ...we're done with tsupers, start over with super of the focus level type:
+ return base.getSuperclassLinearized(type.tsuperChainRoot);
+ }
+ return base.getSuperclassLinearized(type);
+ }
+
+ // ==== handling for phantom mode: ====
+
+ ConnectedType[] maybeSubstitutePhantoms(ConnectedType[] roles) throws JavaModelException {
+ if (this.phantomMode)
+ return roles;
+ ConnectedType[] substituted = new ConnectedType[roles.length];
+ for (int i = 0; i < roles.length; i++)
+ substituted[i] = roles[i].getRealTSuper();
+ return substituted;
+ }
+
+ protected ConnectedType[] filterPhantomRoles(ConnectedType[] roles) {
+ ConnectedType[] substituted = new ConnectedType[roles.length];
+ int n = 0;
+ for (int i = 0; i < roles.length; i++)
+ if (!roles[i].isPhantom)
+ substituted[n++] = roles[i];
+ if (n<roles.length)
+ System.arraycopy(substituted, 0, substituted=new ConnectedType[n], 0, n);
+ return substituted;
+ }
+
+ // wrappers for use in multiple callin bindings
+ callin ConnectedType[] phantomFilterWrapper() {
+ return filterPhantomRoles(base.phantomFilterWrapper());
+ }
+
+ callin ConnectedType[] filterDuplicatesAndPhantoms(IType type) {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ return filterDupsAndPhants(base.filterDuplicatesAndPhantoms(type));
+ }
+
+ protected ConnectedType[] filterDupsAndPhants(ConnectedType[] unfiltered) {
+ if (unfiltered == null)
+ return unfiltered;
+ Set<ConnectedType> filtered = new HashSet<ConnectedType>();
+ for(ConnectedType type : unfiltered)
+ if (this.phantomMode || !type.isPhantom)
+ filtered.add(type);
+ return filtered.toArray(new ConnectedType[filtered.size()]);
+ }
+
+ callin void ensureJavaType(IType type) {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ base.ensureJavaType(type);
+ }
+
+ // ==== adjusting some subtype queries for tsubs:
+
+ callin ConnectedType[] addTSubs(ConnectedType type) {
+ ConnectedType[] res1 = base.addTSubs(type);
+ Set<ConnectedType> tsubs = type.knownTSubTypes;
+
+ if (tsubs == null || tsubs.size() == 0)
+ return this.phantomMode ? res1 : filterDupsAndPhants(res1);
+
+ Set<ConnectedType> result = new HashSet<ConnectedType>();
+ result.addAll(tsubs);
+ for (ConnectedType t1 : res1)
+ result.add(t1);
+ return result.toArray(new ConnectedType[result.size()]);
+ }
+
+
+ // ==== queries for clients (wrapped by methods of enclosing team, see there for documentation): ====
+
+ protected IType[] getAllTSuperTypes(IType as ConnectedType type) {
+ ConnectedType[] result = type.getAllTSuperTypes();
+ return this.phantomMode ? result : filterPhantomRoles(result);
+ // FIXME(SH) return without intermediate local var -> CCE
+ // like: return type.getAllTSuperTypes();
+ }
+
+ protected IType[] getDirectTSupers(IType as ConnectedType type) throws JavaModelException {
+ if (type.directTSupers == null)
+ return NO_TYPE;
+ return maybeSubstitutePhantoms(type.directTSupers);
+ }
+
+ protected IType getPlainSuperclass(IType type) throws JavaModelException {
+ try {
+ OTTypeHierarchies.this.deactivate();
+ ConnectedType result = getSuperclass(type);
+ if (this.phantomMode || result == null)
+ return result;
+ return result.getRealTSuper();
+ } finally {
+ OTTypeHierarchies.this.activate();
+ }
+ }
+
+ // sole purpose of this wrapper: array-lowering
+ protected IType[] getAllSuperclasses(IType type) {
+ return getAllSuperclassesUnfiltered(type);
+ }
+ }
+
+ /**
+ * This role adapts the HierarchyBuilder in order to record information about implicit inheritance, too.
+ */
+ protected class OTHierarchyBuilder playedBy HierarchyBuilder {
+
+ @SuppressWarnings("decapsulation")
+ OTTypeHierarchy getHierarchy() -> get TypeHierarchy hierarchy;
+
+ connectTSupers <- before hookableConnect;
+
+ private void connectTSupers(ReferenceBinding focusType, ReferenceBinding typeBinding, IGenericType type, IType typeHandle, boolean isPhantom,
+ IType superclassHandle, IType[] tsuperclassHandles, boolean[] arePhantoms, IType[] superinterfaceHandles)
+ {
+ if (tsuperclassHandles!= null) {
+ FocusRelation focusRelation = FocusRelation.compute(focusType, typeBinding);
+ getHierarchy().connectTSupers(typeHandle, isPhantom, tsuperclassHandles, arePhantoms, focusRelation);
+ }
+ }
+ }
+
+ /**
+ * API: Query all direct and indirect implicit superclasses of the given type.
+ * If phantomMode is set to <code>false</code> any phantom roles will be filtered from the result.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return a non-null array of ordered implicit super classes
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType[] getAllTSuperTypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ return otHierarchy.getAllTSuperTypes(type);
+ }
+
+ /**
+ * API: Query all direct implicit superclasses of the given type.
+ * If phantomMode is set to <code>false</code> any phantom roles will be translated to its real origin.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return a non-null array of ordered implicit super classes
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType[] getTSuperTypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ return otHierarchy.getDirectTSupers(type);
+ }
+
+ /**
+ * API: Query all direct, implicit and explicit superclasses of the given type.
+ * If phantomMode is set to <code>false</code> any phantom roles will be substituted with their real origin.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return a non-null array of ordered super classes.
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType[] getSuperclasses(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ // have superclass (otherwise type == java.lang.Object?)
+ IType superclass = otHierarchy.getPlainSuperclass(type);
+ if (superclass == null)
+ return NO_TYPE;
+
+ // check direct tsupers:
+ IType[] directTSupers = getTSuperTypes(otHierarchy, type);
+ if (directTSupers == null)
+ return new IType[] { superclass };
+
+ // found both => merge
+ int count = directTSupers.length;
+ IType[] merged = new IType[count+1];
+ System.arraycopy(directTSupers, 0, merged, 0, count);
+ merged[count] = superclass;
+ return merged;
+ }
+
+ /**
+ * API: Query all direct and indirect, implicit and explicit superclasses of the given type.
+ * If phantomMode is set to <code>false</code> any phantom roles will be filtered from the result.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return a non-null array of ordered super classes.
+ * @throws JavaModelException if accessing type failed
+ */
+ public IType[] getAllSuperclasses(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type.isInterface())
+ return NO_TYPE;
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ return otHierarchy.getAllSuperclasses(type);
+ }
+
+ /**
+ * API: Query the explicit superclass of the given type.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super type is queried
+ * @return the superclass
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType getExplicitSuperclass(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ // have superclass (otherwise type == java.lang.Object?)
+ return otHierarchy.getPlainSuperclass(type);
+ }
+
+ /** Get ALL super types: classes and interfaces, explicit and implicit, direct and indirect. */
+ public IType[] getAllSupertypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ IType[] superclasses = otHierarchy.getAllSuperclasses(type);
+ IType[] superinterfaces = otHierarchy.getAllSuperInterfaces(type);
+ int l1 = superclasses.length, l2 = superinterfaces.length;
+ IType[] result = new IType[l1+l2];
+ System.arraycopy(superclasses, 0, result, 0, l1);
+ System.arraycopy(superinterfaces, 0, result, l1, l2);
+ return result;
+ }
+
+ /**
+ * API: Query the superinterfaces of the given type, plus if it's a role interface the tsuper interfaces.
+ * tsuper's direct superinterfaces are also counted as direct interfaces.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return the superinterfaces
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType[] getSuperInterfaces(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ IType[] superinterfaces = otHierarchy.getSuperInterfaces(type);
+ if (!OTModelManager.isRole(type))
+ return superinterfaces;
+ Set<IType> all = new HashSet<IType>();
+ for (IType iType : superinterfaces)
+ all.add(iType);
+ for (IType tsuperinterface : otHierarchy.getDirectTSupers(type)) {
+ if (type.isInterface()) // otherwise just traverse tsuper to find more super interfaces
+ all.add(tsuperinterface);
+ for (IType tsupersuper : otHierarchy.getSuperInterfaces(tsuperinterface))
+ all.add(tsupersuper);
+ }
+ return all.toArray(new IType[all.size()]);
+ }
+
+ /**
+ * API: Query the superinterfaces of the given type: explicit & implicit, direct & indirect.
+ *
+ * @param otHierarchy a hierarchy that has been focused on the given type
+ * @param type the focus type whose super types are queried
+ * @return the superinterfaces
+ * @throws JavaModelException If the tsuper linearization is corrupt
+ */
+ public IType[] getAllSuperInterfaces(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException {
+ if (!OTModelManager.isRole(type))
+ return otHierarchy.getAllSuperInterfaces(type);
+ if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement();
+ Set<IType> all = new HashSet<IType>();
+ getAllSuperInterfaces2(otHierarchy, type, all);
+ return all.toArray(new IType[all.size()]);
+ }
+ // recursive helper for above
+ private void getAllSuperInterfaces2(OTTypeHierarchy otHierarchy, IType seed, Set<IType> collected) throws JavaModelException {
+ for (IType tsuperinterface : otHierarchy.getAllTSuperTypes(seed)) {
+ if (seed.isInterface()) { // otherwise just traverse tsuper to find more super interfaces
+ collected.add(tsuperinterface);
+ }
+ getAllSuperInterfaces2(otHierarchy, tsuperinterface, collected);
+ }
+ for (IType superinterface : otHierarchy.getAllSuperInterfaces(seed)) {
+ collected.add(superinterface);
+ getAllSuperInterfaces2(otHierarchy, superinterface, collected);
+ }
+ }
+
+ /**
+ * Configure whether the given hierarchy should consider phantom roles or not.
+ * Depending on the query used, phantom roles will either be filtered out or replaced with their real origins.
+ * In order for the phantom modes to be respected, the hierarchy must not be directly consulted but only
+ * via the fassade methods of this team.
+ */
+ public void setPhantomMode(TypeHierarchy as OTTypeHierarchy otHierarchy, boolean mode) {
+ otHierarchy.phantomMode = mode;
+ }
+}