Search in sources :

Example 1 with ClassHierarchyTraverser

use of com.jopdesign.common.graphutils.ClassHierarchyTraverser in project jop by jop-devel.

the class AppInfo method removeClasses.

/**
 * Remove a collection of classes and all their nested classes from AppInfo, and update the class hierarchy.
 *
 * @param classes the classes to remove. Duplicates in this collection will be removed first.
 */
public void removeClasses(Collection<ClassInfo> classes) {
    // first, collect all nested classes and remove duplicates.
    final Map<String, ClassInfo> map = new LinkedHashMap<String, ClassInfo>(classes.size());
    for (ClassInfo classInfo : classes) {
        ClassVisitor v = new ClassVisitor() {

            @Override
            public boolean visitClass(ClassInfo classInfo) {
                // we put the visited (nested) class in the map, and descend if it is not already there
                return map.put(classInfo.getClassName(), classInfo) == null;
            }

            @Override
            public void finishClass(ClassInfo classInfo) {
            }
        };
        ClassHierarchyTraverser cht = new ClassHierarchyTraverser(v);
        cht.setVisitSubclasses(false, false);
        cht.setVisitInnerClasses(true);
        cht.traverseDown(classInfo);
    }
    // now we go through all classes and remove them from the class-list and from the class hierarchy
    for (ClassInfo classInfo : classes) {
        for (AppEventHandler mgr : eventHandlers) {
            mgr.onRemoveClass(classInfo);
        }
        this.classes.remove(classInfo.getClassName());
        classInfo.removeFromClassHierarchy();
    }
    // finally go through all classes once more to update the FullyKnown-flags
    for (ClassInfo classInfo : classes) {
        // since we already removed the classes from the class hierarchy, this won't descend down
        // classes we are removing
        classInfo.finishRemoveFromHierarchy();
        classInfo.resetHierarchyInfos();
    }
}
Also used : ClassHierarchyTraverser(com.jopdesign.common.graphutils.ClassHierarchyTraverser) CallString(com.jopdesign.common.code.CallString) ClassVisitor(com.jopdesign.common.graphutils.ClassVisitor) LinkedHashMap(java.util.LinkedHashMap)

Example 2 with ClassHierarchyTraverser

use of com.jopdesign.common.graphutils.ClassHierarchyTraverser in project jop by jop-devel.

the class AppInfo method findImplementations.

/**
 * Find all methods which might get invoked for a given methodRef.
 * This does not use the callgraph to eliminate methods. If you want a more precise result,
 * use {@link #findImplementations(InvokeSite, CallString)} and use callgraph thinning first.
 * <p>
 * Note that this method is slightly different from {@link MethodInfo#getImplementations(boolean)}, since
 * it returns only methods for subclasses of the invokee class, not of the implementing class.
 * </p>
 * <p>To handle invocations of super-methods correctly, use {@link #findImplementations(InvokeSite)}
 * instead.</p>
 *
 * @see #findImplementations(InvokeSite)
 * @see MethodInfo#overrides(MethodRef, boolean)
 * @param invokee the method to resolve.
 * @return all possible implementations, including native methods.
 */
public Set<MethodInfo> findImplementations(final MethodRef invokee) {
    final Set<MethodInfo> methods = new LinkedHashSet<MethodInfo>();
    // 'method' may refer to an inherited MethodInfo or to an interface method if there is no implementation
    final MethodInfo method = invokee.getMethodInfo();
    if (method != null && (method.isStatic() || method.isPrivate())) {
        methods.add(method);
        return methods;
    }
    final String methodSig = invokee.getMethodSignature();
    final ClassInfo invokeeClass = invokee.getClassRef().getClassInfo();
    if (invokeeClass == null) {
        // ok, now, if the target class is unknown, there is not much we can do, so return an empty set
        logger.debug("Trying to find implementations of a method in an unknown class " + invokee.toString());
        return methods;
    }
    // Constructors are only called by invokespecial
    if ("<init>".equals(invokee.getName())) {
        MethodInfo init = invokee.getMethodInfo();
        if (init == null) {
            throw new JavaClassFormatError("Constructor not found: " + invokee);
        }
        if (init.isAbstract()) {
            throw new JavaClassFormatError("Found abstract constructor, this isn't right..: " + invokee);
        }
        methods.add(init);
        return methods;
    }
    boolean undefinedBaseMethod = false;
    // check if method is defined in the referenced class or in a superclass
    if (invokeeClass.getMethodInfo(methodSig) == null) {
        // method is inherited, add to implementations
        if (method != null && !method.isAbstract()) {
            methods.add(method);
        } else if (method == null) {
            // hm, invoke to an unknown method (maybe excluded or native), what should we do?
            if (invokeeClass.isFullyKnown(true)) {
                // .. or maybe the method has not been loaded somehow when the MethodRef was created (check!)
                throw new JavaClassFormatError("Method implementation not found in superclass: " + invokee.toString());
            } else {
                // maybe defined in excluded superclass, but we do not know for sure..
                // We *must* return an empty set, but lets try to continue for now and
                // handle it like an excluded class, and abort only if we find overriding methods
                logger.debug("Method implementation not found in incomplete superclass: " + invokee.toString());
                undefinedBaseMethod = true;
            }
        }
    }
    // now, we have a virtual call on our hands ..
    ClassVisitor visitor = new ClassVisitor() {

        public boolean visitClass(ClassInfo classInfo) {
            // Note: we also handle interface classes here, because they can contain <clinit> methods
            MethodInfo m;
            if (invokeeClass.isInterface() && !classInfo.isInterface()) {
                // If we invoke an interface method, we also need to find inherited methods in implementing
                // classes
                m = classInfo.getMethodInfoInherited(methodSig, true);
            } else {
                // If we do not invoke an interface method, 'method' is already the only possible inherited
                // method; If the visited class is an interface, it does not inherit implementations.
                m = classInfo.getMethodInfo(methodSig);
            }
            if (m != null) {
                if (m.isPrivate() && !classInfo.equals(invokeeClass)) {
                    // found an overriding method which is private .. this is interesting..
                    logger.error("Found private method " + m.getMethodSignature() + " in " + classInfo.getClassName() + " overriding non-private method in " + invokee.getClassName());
                }
                if (!m.isAbstract() && (method == null || m.overrides(method, false))) {
                    methods.add(m);
                }
            }
            return true;
        }

        public void finishClass(ClassInfo classInfo) {
        }
    };
    ClassHierarchyTraverser traverser = new ClassHierarchyTraverser(visitor);
    traverser.setVisitSubclasses(true, true);
    traverser.traverseDown(invokeeClass);
    if (undefinedBaseMethod && methods.size() > 0) {
        // overriding methods, this we cannot handle for now
        throw new JavaClassFormatError("Found overriding methods for " + invokee + " but superclasses are undefined!");
    }
    return methods;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) JavaClassFormatError(com.jopdesign.common.misc.JavaClassFormatError) ClassHierarchyTraverser(com.jopdesign.common.graphutils.ClassHierarchyTraverser) CallString(com.jopdesign.common.code.CallString) ClassVisitor(com.jopdesign.common.graphutils.ClassVisitor)

Example 3 with ClassHierarchyTraverser

use of com.jopdesign.common.graphutils.ClassHierarchyTraverser in project jop by jop-devel.

the class InlineHelper method makePublic.

private void makePublic(ClassMemberInfo member) {
    boolean wasPrivate = member.isPrivate();
    // If we need to make it public, check if we need to make the class and all enclosing classes public too
    ClassInfo cls = member.getClassInfo();
    while (cls != null) {
        if (!cls.isPublic()) {
            cls.setAccessType(AccessType.ACC_PUBLIC);
        }
        cls = cls.getEnclosingClassInfo();
    }
    if (wasPrivate && member instanceof MethodInfo) {
        // we are done here. if the method was private, there are no conflicting
        // methods or we needed to rename it anyway.
        member.setAccessType(AccessType.ACC_PUBLIC);
        return;
    }
    // if we make a non-private method or any field public, need to go down to find all overriding
    // members and make them public too
    final MemberID memberID = member.getMemberID();
    ClassVisitor visitor = new EmptyClassVisitor() {

        @Override
        public boolean visitClass(ClassInfo classInfo) {
            ClassMemberInfo m = classInfo.getMemberInfo(memberID);
            if (m == null) {
                return true;
            }
            if (m.isPublic()) {
                // we do not need to go further down if we find a public member
                return false;
            }
            m.setAccessType(AccessType.ACC_PUBLIC);
            return true;
        }
    };
    new ClassHierarchyTraverser(visitor).traverseDown(member.getClassInfo());
}
Also used : MemberID(com.jopdesign.common.type.MemberID) ClassMemberInfo(com.jopdesign.common.ClassMemberInfo) MethodInfo(com.jopdesign.common.MethodInfo) ClassHierarchyTraverser(com.jopdesign.common.graphutils.ClassHierarchyTraverser) EmptyClassVisitor(com.jopdesign.common.graphutils.EmptyClassVisitor) ClassVisitor(com.jopdesign.common.graphutils.ClassVisitor) EmptyClassVisitor(com.jopdesign.common.graphutils.EmptyClassVisitor) ClassInfo(com.jopdesign.common.ClassInfo)

Example 4 with ClassHierarchyTraverser

use of com.jopdesign.common.graphutils.ClassHierarchyTraverser in project jop by jop-devel.

the class MethodInfo method getImplementations.

/**
 * Get all non-abstract methods (including this method if it is not abstract) overriding this method.
 * @see AppInfo#findImplementations(CallString)
 * @see AppInfo#findImplementations(MethodRef)
 * @param checkAccess if false, find all non-abstract methods with same signature even if they do not
 *        override this method.
 * @return a collection of all implementations of this method.
 */
public List<MethodInfo> getImplementations(final boolean checkAccess) {
    final List<MethodInfo> implementations = new LinkedList<MethodInfo>();
    if (checkAccess && (isPrivate() || isStatic())) {
        if (isAbstract()) {
            throw new JavaClassFormatError("Method is private or static but abstract!: " + toString());
        }
        implementations.add(this);
        return implementations;
    }
    if ("<init>".equals(getShortName())) {
        if (isAbstract()) {
            throw new JavaClassFormatError("Found abstract constructor, this isn't right..: " + toString());
        }
        implementations.add(this);
        return implementations;
    }
    ClassVisitor visitor = new ClassVisitor() {

        public boolean visitClass(ClassInfo classInfo) {
            MethodInfo m = classInfo.getMethodInfo(getMethodSignature());
            if (m != null) {
                if (m.isPrivate() && !isPrivate()) {
                    // found an overriding method which is private .. this is interesting..
                    logger.error("Found private method " + m.getMethodSignature() + " in " + classInfo.getClassName() + " overriding non-private method in " + getClassInfo().getClassName());
                }
                if (!m.isAbstract() && (!checkAccess || m.overrides(MethodInfo.this, false))) {
                    implementations.add(m);
                }
            }
            return true;
        }

        public void finishClass(ClassInfo classInfo) {
        }
    };
    new ClassHierarchyTraverser(visitor).traverseDown(getClassInfo());
    return implementations;
}
Also used : JavaClassFormatError(com.jopdesign.common.misc.JavaClassFormatError) ClassHierarchyTraverser(com.jopdesign.common.graphutils.ClassHierarchyTraverser) ClassVisitor(com.jopdesign.common.graphutils.ClassVisitor) LinkedList(java.util.LinkedList)

Example 5 with ClassHierarchyTraverser

use of com.jopdesign.common.graphutils.ClassHierarchyTraverser in project jop by jop-devel.

the class ClassInfo method finishRemoveFromHierarchy.

protected void finishRemoveFromHierarchy() {
    // all extensions and inner classes of this class will now be incomplete
    if (fullyKnown == Ternary.TRUE) {
        ClassVisitor visitor = new ClassVisitor() {

            @SuppressWarnings({ "AccessingNonPublicFieldOfAnotherObject" })
            public boolean visitClass(ClassInfo classInfo) {
                classInfo.fullyKnown = Ternary.FALSE;
                return true;
            }

            public void finishClass(ClassInfo classInfo) {
            }
        };
        ClassHierarchyTraverser traverser = new ClassHierarchyTraverser(visitor);
        traverser.setVisitSubclasses(true, false);
        // we do not support nested classes without enclosing class, so no need to visit them
        // as they are removed too
        traverser.setVisitInnerClasses(false);
        traverser.traverseDown(this);
    }
}
Also used : ClassHierarchyTraverser(com.jopdesign.common.graphutils.ClassHierarchyTraverser) ClassVisitor(com.jopdesign.common.graphutils.ClassVisitor)

Aggregations

ClassHierarchyTraverser (com.jopdesign.common.graphutils.ClassHierarchyTraverser)7 ClassVisitor (com.jopdesign.common.graphutils.ClassVisitor)7 LinkedList (java.util.LinkedList)3 CallString (com.jopdesign.common.code.CallString)2 JavaClassFormatError (com.jopdesign.common.misc.JavaClassFormatError)2 ClassInfo (com.jopdesign.common.ClassInfo)1 ClassMemberInfo (com.jopdesign.common.ClassMemberInfo)1 MethodInfo (com.jopdesign.common.MethodInfo)1 EmptyClassVisitor (com.jopdesign.common.graphutils.EmptyClassVisitor)1 MemberID (com.jopdesign.common.type.MemberID)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1