Java程序  |  211行  |  7.2 KB

package annotations.el;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import annotations.util.coll.VivifyingMap;

/**
 * Manages all annotations within expressions, that is, annotations on typecasts,
 * instanceofs, and object creations.
 * We can use this class for methods, field initializers, and static initializers.
 */
public class AExpression extends AElement {
    /** The method's annotated typecasts; map key is the offset of the checkcast bytecode */
    public final VivifyingMap<RelativeLocation, ATypeElement> typecasts =
            ATypeElement.<RelativeLocation>newVivifyingLHMap_ATE();

    /** The method's annotated "instanceof" tests; map key is the offset of the instanceof bytecode */
    public final VivifyingMap<RelativeLocation, ATypeElement> instanceofs =
            ATypeElement.<RelativeLocation>newVivifyingLHMap_ATE();

    /** The method's annotated "new" invocations; map key is the offset of the new bytecode */
    public final VivifyingMap<RelativeLocation, ATypeElement> news =
            ATypeElement.<RelativeLocation>newVivifyingLHMap_ATE();

    /** A method invocation's annotated type arguments; map key is the offset of the invokestatic bytecode */
    public final VivifyingMap<RelativeLocation, ATypeElement> calls =
            ATypeElement.<RelativeLocation>newVivifyingLHMap_ATE();

    /** A member reference's annotated type parameters; map key is the offset of the invokestatic bytecode */
    public final VivifyingMap<RelativeLocation, ATypeElement> refs =
            ATypeElement.<RelativeLocation>newVivifyingLHMap_ATE();

    /** The method's annotated lambda expressions; map key is the offset of the invokedynamic bytecode */
    public final VivifyingMap<RelativeLocation, AMethod> funs =
            new VivifyingMap<RelativeLocation, AMethod>(
                    new LinkedHashMap<RelativeLocation, AMethod>()) {
        @Override
        public AMethod createValueFor(RelativeLocation k) {
            return new AMethod("" + k);  // FIXME: find generated method name
        }

        @Override
        public boolean subPrune(AMethod v) {
            return v.prune();
        }
    };

    protected Object id;

    AExpression(Object id) {
        super(id);

        this.id = id;
    }

    AExpression(AExpression expr) {
        super(expr);
        copyMapContents(expr.typecasts, typecasts);
        copyMapContents(expr.instanceofs, instanceofs);
        copyMapContents(expr.news, news);
        copyMapContents(expr.calls, calls);
        copyMapContents(expr.refs, refs);
        copyMapContents(expr.funs, funs);
        id = expr.id;
    }

    @Override
    public AExpression clone() {
        return new AExpression(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(AElement o) {
        return o instanceof AExpression &&
            ((AExpression) o).equalsExpression(this);
    }

    protected boolean equalsExpression(AExpression o) {
        return super.equals(o)
                && typecasts.equals(o.typecasts)
                && instanceofs.equals(o.instanceofs)
                && news.equals(o.news)
                && refs.equals(o.refs)
                && calls.equals(o.calls)
                && funs.equals(o.funs);
        }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return super.hashCode() + typecasts.hashCode()
            + instanceofs.hashCode() + news.hashCode()
            + refs.hashCode() + calls.hashCode() + funs.hashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean prune() {
        return super.prune() & typecasts.prune() & instanceofs.prune()
                & news.prune() & refs.prune() & calls.prune() & funs.prune();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        SortedMap<RelativeLocation, ATypeElement> map =
            new TreeMap<RelativeLocation, ATypeElement>();
        RelativeLocation prev = null;
        // sb.append("AExpression ");
        // sb.append(id);
        for (Map.Entry<RelativeLocation, ATypeElement> em : typecasts.entrySet()) {
            sb.append("typecast: ");
            RelativeLocation loc = em.getKey();
            sb.append(loc);
            sb.append(": ");
            AElement ae = em.getValue();
            sb.append(ae.toString());
            sb.append(' ');
        }
        for (Map.Entry<RelativeLocation, ATypeElement> em : instanceofs.entrySet()) {
            sb.append("instanceof: ");
            RelativeLocation loc = em.getKey();
            sb.append(loc);
            sb.append(": ");
            AElement ae = em.getValue();
            sb.append(ae.toString());
            sb.append(' ');
        }
        for (Map.Entry<RelativeLocation, ATypeElement> em : news.entrySet()) {
            sb.append("new ");
            RelativeLocation loc = em.getKey();
            sb.append(loc);
            sb.append(": ");
            AElement ae = em.getValue();
            sb.append(ae.toString());
            sb.append(' ');
        }
        map.putAll(refs);
        for (Entry<RelativeLocation, ATypeElement> em : map.entrySet()) {
            RelativeLocation loc = em.getKey();
            AElement ae = em.getValue();
            boolean isOffset = loc.index < 0;
            if (prev == null
                    || (isOffset ? loc.offset == prev.offset
                        : loc.index == prev.index)) {
                sb.append("reference ");
                sb.append(isOffset ? "*" + loc.offset : "#" + loc.index);
                sb.append(": ");
                sb.append(ae.toString());
            }
            if (loc.type_index >= 0) {
                sb.append("typearg " + loc);
                sb.append(": ");
                sb.append(ae.toString());
                sb.append(' ');
            }
            prev = loc;
        }
        prev = null;
        map.clear();
        map.putAll(calls);
        for (Entry<RelativeLocation, ATypeElement> em : map.entrySet()) {
            RelativeLocation loc = em.getKey();
            AElement ae = em.getValue();
            boolean isOffset = loc.index < 0;
            if (prev == null
                    || (isOffset ? loc.offset == prev.offset
                        : loc.index == prev.index)) {
                sb.append("call ");
                sb.append(isOffset ? "*" + loc.offset : "#" + loc.index);
                sb.append(": ");
            }
            if (loc.type_index >= 0) {
                sb.append("typearg " + loc);
                sb.append(": ");
                sb.append(ae.toString());
                sb.append(' ');
            }
            prev = loc;
        }
        prev = null;
        map.clear();
        for (Map.Entry<RelativeLocation, AMethod> em : funs.entrySet()) {
            sb.append("lambda ");
            RelativeLocation loc = em.getKey();
            sb.append(loc);
            sb.append(": ");
            AElement ae = em.getValue();
            sb.append(ae.toString());
            sb.append(' ');
        }
        return sb.toString();
    }

    @Override
    public <R, T> R accept(ElementVisitor<R, T> v, T t) {
        return v.visitExpression(this, t);
    }
}