aspect Overriding { syn lazy boolean MethodDecl.canOverrideOrHide(MethodDecl md) { // this code is copy-n-pasted from TypeHierarchyCheck.jrag sans error messages if(!isStatic() && !md.isPrivate() && md.accessibleFrom(hostType()) && hostType().instanceOf(md.hostType())) { if(md.isStatic()) return false; if(!mayOverrideReturn(md)) return false; for(int i = 0; i < getNumException(); i++) { Access e = getException(i); boolean found = false; for(int j = 0; !found && j < md.getNumException(); j++) { if(e.type().instanceOf(md.getException(j).type())) found = true; } if(!found && e.type().isUncheckedException()) return false; } if(md.isPublic() && !isPublic() || md.isProtected() && !(isPublic() || isProtected()) || !md.isPrivate() && !md.isProtected() && !md.isPublic() && isPrivate()) return false; if(md.isFinal()) return false; } else if(isStatic() && !md.isPrivate() && md.accessibleFrom(hostType()) && hostType().instanceOf(md.hostType())) { if(!md.isStatic()) return false; if(type() != md.type()) return false; for(int i = 0; i < getNumException(); i++) { Access e = getException(i); boolean found = false; for(int j = 0; !found && j < md.getNumException(); j++) { if(e.type().instanceOf(md.getException(j).type())) found = true; } if(!found) return false; } if(md.isPublic() && !isPublic() || md.isProtected() && !(isPublic() || isProtected()) || !md.isPrivate() && !md.isProtected() && !md.isPublic() && isPrivate()) return false; if(md.isFinal()) return false; } return true; } // collect all method declarations overriding a given method declaration coll HashSet MethodDecl.coll_overridingMethods() [new HashSet()] with add root Program; MethodDecl contributes this to MethodDecl.coll_overridingMethods() for each overriddenMethods(); /* Problem with generics for overriding/overriddenMethods: * * overriddenMethods returns MethodDeclSubstituted, so overridingMethods from generic superclass * don't work as expected */ public Collection MethodDecl.overridingMethods() { if(this.isFinal() || this.isPrivate() || this.isStatic()) return Collections.EMPTY_SET; return coll_overridingMethods(); } // get all method declarations overridden by a given method declaration syn lazy HashSet MethodDecl.overriddenMethods() { HashSet ret = new HashSet(); if(this.isPrivate() || this.isStatic()) return ret; for(Iterator iter=possiblyOverriddenAncestors().iterator(); iter.hasNext();) { MethodDecl md = iter.next(); if(overrides(md)) ret.add(md); } return ret; } // get all method declaration hidden by a given method declaration syn lazy HashSet MethodDecl.hiddenMethods() { HashSet ret = new HashSet(); if(!this.isStatic()) return ret; for(Iterator iter=possiblyOverriddenAncestors().iterator(); iter.hasNext();) { MethodDecl md = iter.next(); if(hides(md)) ret.add(md); } return ret; } public HashSet MethodDecl.possiblyOverriddenAncestors() { return hostType().possiblyOverriddenAncestors(signature()); } syn HashSet TypeDecl.possiblyOverriddenAncestors(String signature) { HashSet s = new HashSet(); possiblyOverriddenAncestors(s, signature); return s; } protected void TypeDecl.possiblyOverriddenAncestors(HashSet s, String signature) { for(TypeDecl supertp : supertypes()) possiblyOverriddenAncestorsFrom(supertp, s, signature); } protected void TypeDecl.possiblyOverriddenAncestorsFrom(TypeDecl supertp, HashSet s, String signature) { SimpleSet r = supertp.localMethodsSignature(signature); if(r.isEmpty()) { supertp.possiblyOverriddenAncestors(s, signature); } else { for(Iterator iter=r.iterator(); iter.hasNext();) s.add(iter.next()); } } protected void InterfaceDecl.possiblyOverriddenAncestors(HashSet s, String signature) { super.possiblyOverriddenAncestors(s, signature); if(getNumSuperInterfaceId() == 0) possiblyOverriddenAncestorsFrom(typeObject(), s, signature); } syn lazy Collection MethodDecl.rootDefs() { if(isPrivate() || isStatic()) return Collections.singleton(this); Collection res = new LinkedHashSet(); LinkedList worklist = new LinkedList(); worklist.addFirst(this); while(!worklist.isEmpty()) { MethodDecl md = worklist.removeFirst(); if(res.contains(md)) continue; if(md.overriddenMethods().isEmpty()) res.add(md); worklist.addAll(md.overriddenMethods()); } return res; } syn lazy Collection TypeDecl.supertypestransitive() { java.util.Set supertypestransitive = new HashSet(); for (TypeDecl supertype : supertypes()) { supertypestransitive.addAll(supertype.supertypestransitive()); supertypestransitive.add(supertype); } if(supertypes().size() == 0 && isInterfaceDecl()) supertypestransitive.add(programRoot().findType("java.lang.Object")); return supertypestransitive; } syn lazy Collection TypeDecl.childtypestransitive() { java.util.Set childtypestransitive = new HashSet(); for (TypeDecl childtype : childTypes()) { childtypestransitive.addAll(childtype.childtypestransitive()); childtypestransitive.add(childtype); } return childtypestransitive; } syn lazy Collection TypeDecl.supertypes() = Collections.emptySet(); eq ClassDecl.supertypes() { Collection res = new LinkedList(); if(superclass() != null) res.add(superclass()); for(Iterator iter = interfacesIterator(); iter.hasNext();) res.add(iter.next()); return res; } eq InterfaceDecl.supertypes() { Collection res = new LinkedList(); for(Iterator iter = superinterfacesIterator(); iter.hasNext();) res.add(iter.next()); return res; } syn lazy Collection TypeDecl.superinterfaces() = Collections.emptySet(); eq ClassDecl.superinterfaces() { Collection res = new LinkedList(); for(Iterator iter = interfacesIterator(); iter.hasNext();) res.add(iter.next()); return res; } eq InterfaceDecl.superinterfaces() { Collection res = new LinkedList(); for(Iterator iter = superinterfacesIterator(); iter.hasNext();) res.add(iter.next()); return res; } syn lazy Collection FieldDeclaration.hiddenFields() { Collection res = new LinkedHashSet(); for(TypeDecl std : hostType().supertypes()) { for(Iterator iter=std.memberFields(name()).iterator();iter.hasNext();) { FieldDeclaration that = iter.next(); if(that.accessibleFrom(hostType())) res.add(that); } } return res; } /* Indirect overriding: We say that a method m in a class A indirectly overrides a method m' in an interface * I if there is some class C inheriting both m from A and m' from I under the same * signature, yet A itself does not inherit m' under the signature of m. */ syn lazy Collection MethodDecl.indirectlyOverriddenMethods() { Collection inheritors = inheritingTypes(); Collection res = new HashSet(); for(TypeDecl inheritor : inheritors) { if(inheritor == hostType()) continue; for(InterfaceDecl sup : inheritor.superinterfaces()) for(Iterator iter = sup.methodsSignature(signature()).iterator();iter.hasNext();) res.add(iter.next()); } return res; } syn lazy Collection MethodDecl.possiblyHiddenMethods() { HashSet ret = new HashSet(); if(!this.isStatic()) return ret; return possiblyOverriddenAncestors(); } }