Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcbateman2007-05-16 22:30:39 +0000
committercbateman2007-05-16 22:30:39 +0000
commit81457d55b860afb38403a45a7b153858ec3b6108 (patch)
tree0fc8a9da1f7d004c51a361b4326ff969292b99a6
parent752b7467e02f22e72e4b75a59d143d5e43c4b9ec (diff)
downloadwebtools.jsf-81457d55b860afb38403a45a7b153858ec3b6108.tar.gz
webtools.jsf-81457d55b860afb38403a45a7b153858ec3b6108.tar.xz
webtools.jsf-81457d55b860afb38403a45a7b153858ec3b6108.zip
Patch https://bugs.eclipse.org/bugs/attachment.cgi?id=64528 from https://bugs.eclipse.org/bugs/show_bug.cgi?id=163890.
Major performance improvement on EL bean resolution (Matthias Fuessel) plus regression JUnits (Cameron Bateman/Oracle).
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfo.java100
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfoCache.java543
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/util/TypeUtil.java18
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java78
4 files changed, 703 insertions, 36 deletions
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfo.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfo.java
new file mode 100644
index 000000000..0015b6f49
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfo.java
@@ -0,0 +1,100 @@
+package org.eclipse.jst.jsf.common.internal.types;
+
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jst.jsf.context.symbol.IBeanMethodSymbol;
+import org.eclipse.jst.jsf.context.symbol.IBeanPropertySymbol;
+
+/**This class contains all info that is cached for a given IType.
+ * @see org.eclipse.jst.jsf.common.internal.types.TypeInfoCache
+ *
+ * @author Matthias
+ */
+class TypeInfo {
+
+ /**Empty String array. Used for the (usual) case when a type has no missing supertypes.
+ */
+ public static String[] NO_NAMES = new String[0];
+
+ private IBeanMethodSymbol[] methods = null;
+ private IBeanPropertySymbol[] properties = null;
+ private IType[] supertypes = null;
+ private IType[] interfaceTypes = null;
+ private String[] missingSupertypeNames = null;
+
+ /**Creates an empty TypeInfo object
+ */
+ public TypeInfo() {
+ super();
+ }
+
+ /**Returns the method symbols. Returns <code>null</code> if none have been cached.
+ * @return the method symbols. May be null.
+ */
+ public IBeanMethodSymbol[] getMethodSymbols() {
+ return methods;
+ }
+
+ /**Returns the property symbols. Returns <code>null</code> if none have been cached.
+ * @return the property symbols. May be null.
+ */
+ public IBeanPropertySymbol[] getPropertySymbols() {
+ return properties;
+ }
+
+ /**Sets the methods symbols to be cached.
+ * @param methods - the method symbols
+ */
+ public void setMethodSymbols(IBeanMethodSymbol[] methods) {
+ this.methods = methods;
+ }
+
+ /**Sets the property symbols to be cached.
+ * @param properties - the property symbols
+ */
+ public void setPropertySymbols(IBeanPropertySymbol[] properties) {
+ this.properties = properties;
+ }
+
+ /**Returns the supertypes. Returns <code>null</code> if none have been cached.
+ * @return the supertypes. May be null.
+ */
+ public IType[] getSupertypes() {
+ return supertypes;
+ }
+
+ /**Sets the supertypes to be cached.
+ * @param superTypes - the property symbols
+ */
+ public void setSupertypes(IType[] superTypes) {
+ this.supertypes = superTypes;
+ }
+
+ /**Returns the interface types. Returns <code>null</code> if none have been cached.
+ * @return the interface types. May be null.
+ */
+ public IType[] getInterfaceTypes() {
+ return interfaceTypes;
+ }
+
+ /**Sets the interface types to be cached.
+ * @param interfaceTypes - the property symbols
+ */
+ public void setInterfaceTypes(IType[] interfaceTypes) {
+ this.interfaceTypes = interfaceTypes;
+ }
+
+ /**Returns the names of the missing supertypes. Returns <code>null</code> if none have been cached.
+ * @return the names of the missing supertypes. May be null.
+ */
+ public String[] getMissingSupertypeNames() {
+ return missingSupertypeNames;
+ }
+
+ /**Sets the supertypes to be cached.
+ * @param missingSupertypeNames - the names of the missing supertypes
+ */
+ public void setMissingSupertypeNames(String[] missingSupertypeNames) {
+ this.missingSupertypeNames = missingSupertypeNames;
+ }
+
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfoCache.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfoCache.java
new file mode 100644
index 000000000..dcd0c29eb
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/types/TypeInfoCache.java
@@ -0,0 +1,543 @@
+package org.eclipse.jst.jsf.common.internal.types;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.jst.jsf.common.JSFCommonPlugin;
+import org.eclipse.jst.jsf.context.symbol.IBeanMethodSymbol;
+import org.eclipse.jst.jsf.context.symbol.IBeanPropertySymbol;
+
+/**Provides a cache for java IType properties. It can cache bean property symbols, method symbols,
+ * supertypes and implemented interfaces per IType. The cache listens to changes in the java model
+ * and invalidates affected properties, but does not update them.
+ *
+ * @author Matthias
+ */
+public class TypeInfoCache implements IElementChangedListener {
+
+ private static TypeInfoCache instance = null;
+
+ /**Returns the TypeInfoCache instance.
+ *
+ * @return the TypeInfoCache instance
+ */
+ public static synchronized TypeInfoCache getInstance() {
+ if (instance == null) {
+ instance = new TypeInfoCache();
+ JavaCore.addElementChangedListener(instance, ElementChangedEvent.POST_CHANGE);
+ }
+ return instance;
+ }
+
+ private final Map /*<IType, TypeInfo>*/ cachedInfo;
+ private final Map /*<ITypeRoot, Set<IType>>*/ cachedTypesByAffectingTypeRoot;
+ private final Map /*<String, Set<IType>>*/ cachedTypesByMissingSupertypename;
+
+ private TypeInfoCache() {
+ cachedInfo = new HashMap();
+ cachedTypesByAffectingTypeRoot = new HashMap();
+ cachedTypesByMissingSupertypename = new HashMap(10);
+ }
+
+ public void elementChanged(ElementChangedEvent event) {
+ updateChangedJavaElement(event.getDelta());
+ }
+
+ /**Returns the cached info({@link TypeInfo}) for a given type. Will
+ * return <code>null</code> if no info has been cached or the the type/something it depends on
+ * has changed since then.
+ *
+ * @param type - the type in question
+ * @return a TypeInfo instance that contains all cached info for the given type. May be null.
+ */
+ protected TypeInfo getTypeInfo(IType type) {
+ TypeInfo info = null;
+ if (type != null)
+ {
+ info = (TypeInfo) cachedInfo.get(type);
+ }
+ return info;
+ }
+
+ /**Returns the cached bean property symbols for a given type. Will return null if no
+ * bean property symbols have been cached or the type/something it depends on has changed since
+ * then.
+ * @param beanType - the bean type in question
+ * @return the bean property symbols for the given type. May be null.
+ * @see TypeInfoCache#cachePropertySymbols(IType, IBeanPropertySymbol[])
+ */
+ public synchronized IBeanPropertySymbol[] getCachedPropertySymbols(IType beanType) {
+ IBeanPropertySymbol[] props = null;
+
+ if (beanType != null)
+ {
+ TypeInfo typeInfo = getTypeInfo(beanType);
+ if (typeInfo != null)
+ {
+ props = typeInfo.getPropertySymbols();
+ }
+ }
+ return props;
+ }
+
+ /**Returns the cached method symbols for a given type. Will return null if no
+ * method symbols have been cached or the type/something it depends on has changed since
+ * then.
+ * @param beanType - the bean type in question
+ * @return the method symbols for the given type. May be null.
+ * @see TypeInfoCache#cacheMethodSymbols(IType, IBeanMethodSymbol[])
+ */
+ public synchronized IBeanMethodSymbol[] getCachedMethodSymbols(IType beanType) {
+ IBeanMethodSymbol[] methods = null;
+
+ if (beanType != null)
+ {
+ TypeInfo typeInfo = getTypeInfo(beanType);
+ if (typeInfo != null)
+ {
+ methods = typeInfo.getMethodSymbols();
+ }
+ }
+
+ return methods;
+ }
+
+ /**Returns the cached supertypes for a given type. Will return null if no supertypes
+ * have been cached for this type or if the type/something it depends on has changed since
+ * then.
+ * @param type - the bean type in question
+ * @return the supertypes for the given type. May be null.
+ * @see TypeInfoCache#cacheSupertypesFor(IType)
+ */
+ public synchronized IType[] getCachedSupertypes(IType type) {
+ IType[] types = null;
+
+ if (type != null)
+ {
+ TypeInfo typeInfo = getTypeInfo(type);
+ if (typeInfo != null)
+ {
+ types = typeInfo.getSupertypes();
+ }
+ }
+
+ return types;
+ }
+
+ /**Returns the cached implemented interfaces for a given type. Will return null if no interfaces
+ * have been cached for this type or if the type/something it depends on has changed since
+ * then.
+ * @param type - the bean type in question
+ * @return the interface types implemented by the given type. May be null.
+ * @see TypeInfoCache#cacheInterfaceTypesFor(IType)
+ */
+ public synchronized IType[] getCachedInterfaceTypes(IType type)
+ {
+ IType[] types = null;
+
+ if (type != null)
+ {
+ TypeInfo typeInfo = getTypeInfo(type);
+ if (typeInfo != null)
+ {
+ types = typeInfo.getInterfaceTypes();
+ }
+ }
+
+ return types;
+ }
+
+ /**Caches the given method symbols for the given type.
+ * @param beanType - the type
+ * @param methods - the method symbols to cache
+ */
+ public synchronized void cacheMethodSymbols(IType beanType, IBeanMethodSymbol[] methods) {
+ if (beanType != null)
+ {
+ TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
+ if (typeInfo != null) {
+ typeInfo.setMethodSymbols(methods);
+ }
+ }
+ }
+
+ /**Caches the given property symbols for the given type.
+ * @param beanType - the type
+ * @param properties - the property symbols to cache
+ */
+ public synchronized void cachePropertySymbols(IType beanType, IBeanPropertySymbol[] properties) {
+ if (beanType != null)
+ {
+ TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
+ if (typeInfo != null) {
+ typeInfo.setPropertySymbols(properties);
+ }
+ }
+ }
+
+ /**Caches the supertypes for the given type. The supertypes will be calculated (and also returned)
+ * by this method.
+ * @param type - the type to cache supertypes for
+ * @return the supertypes of the given type.
+ */
+ public synchronized IType[] cacheSupertypesFor(IType type)
+ {
+ IType[] types = null;
+
+ if (type != null)
+ {
+ TypeInfo typeInfo = getOrCreateTypeInfo(type);
+
+ if (typeInfo != null)
+ {
+ types = typeInfo.getSupertypes();
+ }
+ }
+ return types;
+ }
+
+ /**Caches the interface types for the given type. The interface types will be calculated (and also
+ * returned) by this method.
+ * @param type - the type to cache interface types for
+ * @return the interface types implemented by the given type.
+ */
+ public synchronized IType[] cacheInterfaceTypesFor(IType type)
+ {
+ IType[] types = null;
+
+ if (type != null)
+ {
+ TypeInfo typeInfo = getOrCreateTypeInfo(type);
+ if (typeInfo != null)
+ {
+ types = typeInfo.getInterfaceTypes();
+ }
+ }
+ return types;
+ }
+
+ /**Returns the TypeInfo for the given type. If no TypeInfo exists for this type, an empty TypeInfo
+ * will be created and cached.
+ * @param type - the type in question
+ * @return the (modifyable) TypeInfo for the given type
+ */
+ protected TypeInfo getOrCreateTypeInfo(IType type) {
+ TypeInfo typeInfo = getTypeInfo(type);
+ if (typeInfo == null) {
+ try {
+ final ITypeHierarchy hierarchy =
+ type.newSupertypeHierarchy(new NullProgressMonitor());
+ final IType[] supertypes = hierarchy.getAllSuperclasses(type);
+ final IType[] interfaceTypes = hierarchy.getAllInterfaces();
+ final IType[] rootClasses = hierarchy.getRootClasses();
+ List missingSupertypesList = null;
+ for (int i = 0; i < rootClasses.length; i++) {
+ String superclassName = rootClasses[i].getSuperclassName();
+ if (superclassName != null) {
+ if (missingSupertypesList == null) {
+ missingSupertypesList = new ArrayList(1);
+ }
+ superclassName = shortTypename(superclassName);
+ missingSupertypesList.add(superclassName);
+ }
+ }
+ String[] missingSupertypes = null;
+ if (missingSupertypesList != null) {
+ missingSupertypes = (String[]) missingSupertypesList.toArray(new String[missingSupertypesList.size()]);
+ } else {
+ missingSupertypes = TypeInfo.NO_NAMES;
+ }
+ typeInfo = new TypeInfo();
+ typeInfo.setSupertypes(supertypes);
+ typeInfo.setInterfaceTypes(interfaceTypes);
+ typeInfo.setMissingSupertypeNames(missingSupertypes);
+ cachedInfo.put(type, typeInfo);
+ registerCachedType(type, typeInfo);
+ } catch (JavaModelException e) {
+ JSFCommonPlugin.log(e);
+ }
+ }
+ return typeInfo;
+ }
+
+ /**Returns the typename fragment after the last "." (which in most cases is identical to the
+ * unqualified typename).
+ * Used only to make sure that if n1 and n2 are names of the same type
+ * shortname(n1) equals shortname(2) even if one name is qualified and one not.
+ * @param typename
+ * @return the typename fragment after the last "."
+ */
+ private String shortTypename(String typename) {
+ int pos = typename.lastIndexOf('.');
+ if (pos >= 0) {
+ typename = typename.substring(pos + 1);
+ }
+ return typename;
+ }
+
+ /**
+ * Registers the given type for all ITypeRoot's it depends on, so that it can be uncached if
+ * one of this ITypeRoot's has changed. The type must be unregistered when it should not be watched
+ * anymore.
+ * @param type - the type
+ * @param typeInfo - TypeInfo of the given type
+ * @see TypeInfoCache#unregisterCachedType(IType, TypeInfo)
+ */
+ protected void registerCachedType(IType type, TypeInfo typeInfo) {
+ registerTypeForTypeRoot(type, type.getTypeRoot());
+ IType[] supertypes = typeInfo.getSupertypes();
+ for (int i = 0; i < supertypes.length; i++) {
+ registerTypeForTypeRoot(type, supertypes[i].getTypeRoot());
+ }
+ String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
+ if (missingSupertypeNames != null) {
+ for (int i = 0; i < missingSupertypeNames.length; i++) {
+ registerTypeForMissingSupertype(type, missingSupertypeNames[i]);
+ }
+ }
+ }
+
+ private void registerTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
+ Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (dependentTypes == null) {
+ dependentTypes = new HashSet(5);
+ cachedTypesByAffectingTypeRoot.put(typeRoot, dependentTypes);
+ }
+ dependentTypes.add(type);
+ }
+
+ private void registerTypeForMissingSupertype(IType type, String supertype) {
+ Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
+ if (dependentTypes == null) {
+ dependentTypes = new HashSet(5);
+ cachedTypesByMissingSupertypename.put(supertype, dependentTypes);
+ }
+ dependentTypes.add(type);
+ }
+
+ /**Unregisters the given type for all ITypeRoot's it depended on.
+ * @param type - the type
+ * @param typeInfo - TypeInfo of the given type
+ */
+ protected void unregisterCachedType(IType type, TypeInfo typeInfo) {
+ unregisterTypeForTypeRoot(type, type.getTypeRoot());
+ IType[] supertypes = typeInfo.getSupertypes();
+ for (int i = 0; i < supertypes.length; i++) {
+ unregisterTypeForTypeRoot(type, supertypes[i].getTypeRoot());
+ }
+ String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
+ if (missingSupertypeNames != null) {
+ for (int i = 0; i < missingSupertypeNames.length; i++) {
+ unregisterTypeForMissingSupertype(type, missingSupertypeNames[i]);
+ }
+ }
+ }
+
+ private void unregisterTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
+ Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (dependentTypes != null) {
+ dependentTypes.remove(type);
+ if (dependentTypes.isEmpty()) {
+ cachedTypesByAffectingTypeRoot.remove(typeRoot);
+ }
+ }
+ }
+
+ private void unregisterTypeForMissingSupertype(IType type, String supertype) {
+ Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
+ if (dependentTypes != null) {
+ dependentTypes.remove(type);
+ if (dependentTypes.isEmpty()) {
+ cachedTypesByMissingSupertypename.remove(supertype);
+ }
+ }
+ }
+
+ /**This will remove all cached info for all types.
+ */
+ protected synchronized void uncacheAllTypes() {
+ cachedInfo.clear();
+ cachedTypesByAffectingTypeRoot.clear();
+ cachedTypesByMissingSupertypename.clear();
+ }
+
+ /**Removes all cached info for all types that are subtypes of a type of the given ITypeRoot.
+ * @param typeRoot
+ */
+ protected synchronized void uncacheAffectedTypes(ITypeRoot typeRoot) {
+ Collection affectedTypes = (Collection) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (affectedTypes != null && !affectedTypes.isEmpty()) {
+ List affectedTypesCopy = new ArrayList(affectedTypes);
+ for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
+ IType cachedType = (IType) it.next();
+ TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
+ unregisterCachedType(cachedType, typeInfo);
+ }
+ }
+ }
+
+ /**Removes all cached info for all types (or subtypes of types) that specify a supertype
+ * that has a name similar to the given name.
+ * @param supertypename - the missing supertype name. May be qualified or not
+ */
+ protected synchronized void uncacheTypesWithMissingSupertype(String supertypename) {
+ Collection affectedTypes = (Collection) cachedTypesByMissingSupertypename.get(shortTypename(supertypename));
+ if (affectedTypes != null && !affectedTypes.isEmpty()) {
+ List affectedTypesCopy = new ArrayList(affectedTypes);
+ for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
+ IType cachedType = (IType) it.next();
+ TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
+ unregisterCachedType(cachedType, typeInfo);
+ }
+ }
+ }
+
+ /**Removes all cached info that may be affected by the given change.
+ * @param delta - the change in the java model
+ */
+ protected void updateChangedJavaElement(IJavaElementDelta delta) {
+ IJavaElement element= delta.getElement();
+ switch (element.getElementType()) {
+ case IJavaElement.JAVA_MODEL:
+ updateChangedJavaModel(delta, element);
+ break;
+ case IJavaElement.JAVA_PROJECT:
+ updateChangedJavaProject(delta, element);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ updateChangedPackageFragmentRoot(delta, element);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT:
+ updateChangedPackageFragment(delta, (PackageFragment) element);
+ break;
+ case IJavaElement.CLASS_FILE:
+ case IJavaElement.COMPILATION_UNIT:
+ updateChangedOpenable(delta, element);
+ break;
+ }
+ }
+
+ private void updateChangedChildren(IJavaElementDelta delta) {
+ if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) > 0) {
+ IJavaElementDelta[] children= delta.getAffectedChildren();
+ for (int i= 0; i < children.length; i++) {
+ updateChangedJavaElement(children[i]);
+ }
+ }
+ }
+
+ private void updateChangedJavaModel(IJavaElementDelta delta, IJavaElement element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ updateChangedChildren(delta);
+ break;
+ }
+ }
+
+ private void updateChangedJavaProject(IJavaElementDelta delta, IJavaElement element) {
+ int kind = delta.getKind();
+ int flags = delta.getFlags();
+ if ((flags & IJavaElementDelta.F_OPENED) != 0) {
+ kind = IJavaElementDelta.ADDED; // affected in the same way
+ }
+ if ((flags & IJavaElementDelta.F_CLOSED) != 0) {
+ kind = IJavaElementDelta.REMOVED; // affected in the same way
+ }
+ switch (kind) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ updateChangedChildren(delta);
+ break;
+ }
+ }
+
+ private void updateChangedPackageFragment(IJavaElementDelta delta, PackageFragment element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ // if the package fragment is in the projects being considered, this could
+ // introduce new types, changing the hierarchy
+ case IJavaElementDelta.REMOVED :
+ // is a change if the package fragment contains supertypes?
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ // look at the files in the package fragment
+ updateChangedChildren(delta);
+ }
+ }
+
+ private void updateChangedPackageFragmentRoot(IJavaElementDelta delta, IJavaElement element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ int flags = delta.getFlags();
+ if (((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0)||(flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+ uncacheAllTypes();
+ } else {
+ updateChangedChildren(delta);
+ }
+ break;
+ }
+ }
+
+ /**Removes all cached info that may be affected by the change in this IOpenable
+ * @param delta - the change in the java model
+ * @param element - the (changed) IOpenable considered
+ */
+ protected void updateChangedOpenable(IJavaElementDelta delta, IJavaElement element) {
+ if (element instanceof ITypeRoot) {
+ ITypeRoot typeRoot = (ITypeRoot) element;
+ uncacheAffectedTypes(typeRoot);
+ // Creates missing superclass for any cached type?
+ if (delta.getKind() == IJavaElementDelta.ADDED) {
+ if (typeRoot instanceof ICompilationUnit) {
+ ICompilationUnit cu = (ICompilationUnit) typeRoot;
+ try {
+ IType[] types = cu.getAllTypes();
+ for (int i = 0; i < types.length; i++) {
+ uncacheTypesWithMissingSupertype(types[i].getElementName());
+ }
+ } catch (JavaModelException e) {
+ JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for compilation unit " + cu, e); //$NON-NLS-1$
+ uncacheAllTypes();
+ }
+ } else if (typeRoot instanceof IClassFile) {
+ IClassFile cf = (IClassFile) typeRoot;
+ IType type = cf.getType();
+ uncacheTypesWithMissingSupertype(type.getElementName());
+ }
+ }
+ }
+ }
+
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/util/TypeUtil.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/util/TypeUtil.java
index 0389b4cfb..d26fac48b 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/util/TypeUtil.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/util/TypeUtil.java
@@ -80,7 +80,7 @@ public final class TypeUtil
/**
* Resolve typeSignature in the context of owningType. This method will return
* a type erased signture if eraseTypeParameters == true and will attempt to
- * resolve and include parameters if eraseTypeParamters
+ * resolve and include parameters if eraseTypeParamters == false
*
* NOTE: special rules apply to the way unresolved type parameters and wildcards
* are resolved:
@@ -102,7 +102,7 @@ public final class TypeUtil
* i.e. List<?> -> Ljava.util.List<Ljava.lang.Object;>;
*
*
- * The reason for this substitions is to return the most accurate reasonable approximation
+ * The reason for this substition is to return the most accurate reasonable approximation
* of the type within what is known by owningType
*
* @param owningType
@@ -413,12 +413,12 @@ public final class TypeUtil
{
if (type == null || !isEnumType(type))
{
- throw new IllegalArgumentException("type must be non-null and isEnum()==true");
+ throw new IllegalArgumentException("type must be non-null and isEnum()==true"); //$NON-NLS-1$
}
if (fieldName == null)
{
- throw new IllegalArgumentException("fieldName must be non-null");
+ throw new IllegalArgumentException("fieldName must be non-null"); //$NON-NLS-1$
}
// if type is the java.lang.Enum, always true
@@ -452,13 +452,13 @@ public final class TypeUtil
{
if (typeSig1 == null || typeSig2 == null)
{
- throw new IllegalArgumentException("args must not be null");
+ throw new IllegalArgumentException("args must not be null"); //$NON-NLS-1$
}
if (Signature.getTypeSignatureKind(typeSig1) != Signature.CLASS_TYPE_SIGNATURE
|| Signature.getTypeSignatureKind(typeSig2) != Signature.CLASS_TYPE_SIGNATURE)
{
- throw new IllegalArgumentException("args must be resolved class types");
+ throw new IllegalArgumentException("args must be resolved class types"); //$NON-NLS-1$
}
// if one or the other is the raw enum type, then they *may* be comparable; we don't know
@@ -484,13 +484,13 @@ public final class TypeUtil
{
if (typeSig1 == null || typeSig2 == null)
{
- throw new IllegalArgumentException("args must not be null");
+ throw new IllegalArgumentException("args must not be null"); //$NON-NLS-1$
}
if (Signature.getTypeSignatureKind(typeSig1) != Signature.CLASS_TYPE_SIGNATURE
|| Signature.getTypeSignatureKind(typeSig2) != Signature.CLASS_TYPE_SIGNATURE)
{
- throw new IllegalArgumentException("args must be resolved class types");
+ throw new IllegalArgumentException("args must be resolved class types"); //$NON-NLS-1$
}
// if either one is the base enum type, then we can't be sure
@@ -533,7 +533,7 @@ public final class TypeUtil
catch (JavaModelException jme)
{
// log and fallthrough to return false
- JSFCommonPlugin.log(jme, "Problem resolving isEnum");
+ JSFCommonPlugin.log(jme, "Problem resolving isEnum"); //$NON-NLS-1$
}
// if unresolved assume false
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java
index a1b1626db..60fcf9d8c 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java
@@ -18,7 +18,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
@@ -29,10 +28,10 @@ import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
+import org.eclipse.jst.jsf.common.internal.types.TypeInfoCache;
import org.eclipse.jst.jsf.common.util.JDTBeanIntrospector;
import org.eclipse.jst.jsf.common.util.JDTBeanProperty;
import org.eclipse.jst.jsf.common.util.TypeUtil;
@@ -177,6 +176,10 @@ public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJa
eNotify(new ENotificationImpl(this, Notification.SET, SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE, oldType, type));
}
+ /**
+ * @see org.eclipse.jst.jsf.context.symbol.internal.impl.ITypeDescriptorImpl#getInterfaceTypeSignatures()
+ * @generated NOT
+ */
public EList getInterfaceTypeSignatures()
{
EList interfaces = new BasicEList();
@@ -185,22 +188,21 @@ public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJa
if (type_ != null)
{
- // TODO: type hierarchy is potentially expensive, should
- // cache once and listen for changes
- try {
- final ITypeHierarchy hierarchy =
- type_.newSupertypeHierarchy(new NullProgressMonitor());
- final IType[] interfaceTypes = hierarchy.getAllInterfaces();
- copySignatures(interfaces, interfaceTypes);
- } catch (JavaModelException e) {
- JSFCommonPlugin.log(e);
+ final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IType[] interfaceTypes = typeInfoCache.getCachedInterfaceTypes(type_);
+ if (interfaceTypes == null) {
+ interfaceTypes = typeInfoCache.cacheInterfaceTypesFor(type_);
}
-
+ copySignatures(interfaces, interfaceTypes);
}
return interfaces;
}
+ /**
+ * @see org.eclipse.jst.jsf.context.symbol.internal.impl.ITypeDescriptorImpl#getSuperTypeSignatures()
+ * @generated NOT
+ */
public EList getSuperTypeSignatures()
{
EList interfaces = new BasicEList();
@@ -209,16 +211,14 @@ public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJa
if (type_ != null)
{
- // TODO: type hierarchy is potentially expensive, should
- // cache once and listen for changes
- try {
- final ITypeHierarchy hierarchy =
- type_.newSupertypeHierarchy(new NullProgressMonitor());
- final IType[] interfaceTypes = hierarchy.getAllSuperclasses(type_);
- copySignatures(interfaces, interfaceTypes);
- } catch (JavaModelException e) {
- JSFCommonPlugin.log(e);
+ final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IType[] interfaceTypes = typeInfoCache.getCachedSupertypes(type_);
+
+ if (interfaceTypes == null)
+ {
+ interfaceTypes = typeInfoCache.cacheSupertypesFor(type_);
}
+ copySignatures(interfaces, interfaceTypes);
}
return interfaces;
@@ -256,10 +256,23 @@ public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJa
* <!-- end-user-doc -->
* @generated NOT
*/
- public EList getBeanProperties() {
- BasicEList list = new BasicEList();
- list.addAll(getPropertiesInternal());
- return list;
+ public EList getBeanProperties()
+ {
+ TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IBeanPropertySymbol[] properties = typeInfoCache.getCachedPropertySymbols(type);
+ Collection propertyColl;
+ if (properties == null) {
+ propertyColl = getPropertiesInternal();
+ properties = (IBeanPropertySymbol[]) propertyColl.toArray(new IBeanPropertySymbol[propertyColl.size()]);
+ typeInfoCache.cachePropertySymbols(type, properties);
+ }
+ else
+ {
+ propertyColl = new ArrayList(properties.length);
+ Collections.addAll(propertyColl, properties);
+ }
+ BasicEList list = new BasicEList(propertyColl);
+ return list;
}
/**
@@ -269,8 +282,19 @@ public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJa
* @generated NOT
*/
public EList getBeanMethods() {
- BasicEList list = new BasicEList();
- list.addAll(getMethodsInternal());
+ TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IBeanMethodSymbol[] methods = typeInfoCache.getCachedMethodSymbols(type);
+ Collection methodColl;
+ if (methods == null)
+ {
+ methodColl = getMethodsInternal();
+ methods = (IBeanMethodSymbol[]) methodColl.toArray(new IBeanMethodSymbol[methodColl.size()]);
+ typeInfoCache.cacheMethodSymbols(type, methods);
+ } else {
+ methodColl = new ArrayList(methods.length);
+ Collections.addAll(methodColl, methods);
+ }
+ BasicEList list = new BasicEList(methodColl);
return list;
}

Back to the top