### Eclipse Workspace Patch 1.0 #P org.eclipse.jst.jsf.common Index: src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java =================================================================== RCS file: /cvsroot/webtools/org.eclipse.jsf/components/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java,v retrieving revision 1.3 diff -u -r1.3 JDTBeanProperty.java --- src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java 7 Apr 2007 00:27:43 -0000 1.3 +++ src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java 10 Apr 2007 15:07:21 -0000 @@ -30,6 +30,11 @@ protected final IType _type; /** + * cached type signature, created on first request + */ + private String _typeSignature = null; + + /** * @param type */ protected JDTBeanProperty(IType type) @@ -114,17 +119,19 @@ */ public String getTypeSignature() { - try - { - String unResolvedSig = getUnresolvedType(); - final String signature = TypeUtil.resolveTypeSignature(_type, unResolvedSig); - return signature; - } - catch (JavaModelException jme) - { - JSFCommonPlugin.log(jme, "Error resolving bean property type signature"); //$NON-NLS-1$ - return null; + if (_typeSignature == null) { + try + { + String unresolvedSig = getUnresolvedType(); + _typeSignature = TypeUtil.resolveTypeSignature(_type, unresolvedSig); + } + catch (JavaModelException jme) + { + JSFCommonPlugin.log(jme, "Error resolving bean property type signature"); + return null; + } } + return _typeSignature; } private String getUnresolvedType() throws JavaModelException Index: src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java =================================================================== RCS file: /cvsroot/webtools/org.eclipse.jsf/components/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java,v retrieving revision 1.4 diff -u -r1.4 IJavaTypeDescriptor2Impl.java --- src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java 7 Apr 2007 00:27:43 -0000 1.4 +++ src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java 10 Apr 2007 15:07:21 -0000 @@ -18,7 +18,6 @@ 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; @@ -27,7 +26,6 @@ import org.eclipse.jdt.core.Flags; 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; @@ -41,6 +39,7 @@ import org.eclipse.jst.jsf.context.symbol.internal.provisional.IJavaTypeDescriptor2; import org.eclipse.jst.jsf.context.symbol.internal.provisional.IObjectSymbol; import org.eclipse.jst.jsf.context.symbol.internal.provisional.IPropertySymbol; +import org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.TypeInfoCache; /** @@ -163,17 +162,12 @@ 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; @@ -187,16 +181,12 @@ 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[] supertypes = typeInfoCache.getCachedSupertypes(type_); + if (supertypes == null) { + supertypes = typeInfoCache.cacheSupertypesFor(type_); } + copySignatures(interfaces, supertypes); } return interfaces; @@ -235,9 +225,19 @@ * @generated NOT */ public EList getBeanProperties() { - BasicEList list = new BasicEList(); - list.addAll(getPropertiesInternal()); - return list; + 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; } /** @@ -247,8 +247,18 @@ * @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; } Index: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java =================================================================== RCS file: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java diff -N src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,100 @@ +package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache; + +import org.eclipse.jdt.core.IType; +import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanMethodSymbol; +import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanPropertySymbol; + +/**This class contains all info that is cached for a given IType. + * @see org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.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 null if none have been cached. + * @return the method symbols. May be null. + */ + public IBeanMethodSymbol[] getMethodSymbols() { + return methods; + } + + /**Returns the property symbols. Returns null 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 null 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 null 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 null 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; + } + +} Index: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java =================================================================== RCS file: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java diff -N src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,476 @@ +package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache; + +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.internal.provisional.IBeanMethodSymbol; +import org.eclipse.jst.jsf.context.symbol.internal.provisional.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 Map /**/ cachedInfo; + private Map /*>*/ cachedTypesByAffectingTypeRoot; + private Map /*>*/ 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 null 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 = (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) { + TypeInfo typeInfo = getTypeInfo(beanType); + return typeInfo == null? null : typeInfo.getPropertySymbols(); + } + + /**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) { + TypeInfo typeInfo = getTypeInfo(beanType); + return typeInfo == null? null : typeInfo.getMethodSymbols(); + } + + /**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) { + TypeInfo typeInfo = getTypeInfo(type); + return typeInfo == null? null : typeInfo.getSupertypes(); + } + + /**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) { + TypeInfo typeInfo = getTypeInfo(type); + return typeInfo == null? null : typeInfo.getInterfaceTypes(); + } + + /**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) { + 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) { + 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) { + TypeInfo typeInfo = getOrCreateTypeInfo(type); + return typeInfo == null? null : typeInfo.getSupertypes(); + } + + /**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) { + TypeInfo typeInfo = getOrCreateTypeInfo(type); + return typeInfo == null? null : typeInfo.getInterfaceTypes(); + } + + /**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); + uncacheAllTypes(); + } + } else if (typeRoot instanceof IClassFile) { + IClassFile cf = (IClassFile) typeRoot; + try { + IType type = cf.getType(); + uncacheTypesWithMissingSupertype(type.getElementName()); + } catch (JavaModelException e) { + JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for classfile " + cf, e); + uncacheAllTypes(); + } + } + } + } + } + +}