⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 check.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                            ((Type) unhandled.head).toJava());
                }
            }
            if ((other.flags() & DEPRECATED) != 0 && (m.flags() & DEPRECATED) == 0 &&
                    m.outermostClass() != other.outermostClass() &&
                    m.enclClass().type.supertype().tsym == other.enclClass())
                warnDeprecated(TreeInfo.positionFor(m, tree), other);
        }
    }

    /**
      * Check that a given method conforms with any method it overrides.
      *  @param tree         The tree from which positions are extracted
      *			    for errors.
      *  @param m            The overriding method.
      */
    void checkOverride(Tree tree, MethodSymbol m) {
        ClassSymbol origin = (ClassSymbol) m.owner;
        for (Type t = origin.type.supertype(); t.tag == CLASS; t = t.supertype()) {
            TypeSymbol c = t.tsym;
            Scope.Entry e = c.members().lookup(m.name);
            while (e.scope != null) {
                if (m.overrides(e.sym, origin))
                    checkOverride(tree, m, (MethodSymbol) e.sym, origin);
                e = e.next();
            }
        }
    }

    /**
      * Return the first method which is defined with same args
      *  but different return types in two given interfaces, or null if none
      *  exists.
      *  @param t1     The first interface.
      *  @param t2     The second interface.
      *  @param site   The most derived type.
      */
    public Symbol firstIncompatibility(Type t1, Type t2, Type site) {
        return firstIncompatibility(t1, t2, t2, site);
    }

    /**
      * Return the first method which is defined with same args
      *  but different return types in a type `t1' and a supertype
      *  `t2super' of a type `t2', or null if none exists.
      *  @param t1       The first type.
      *  @param t2       The second type.
      *  @param t2super  The second's supertype.
      *  @param site     The most derived type.
      */
    public Symbol firstIncompatibility(Type t1, Type t2, Type t2super, Type site) {
        if ((t2super.tsym.flags() & ABSTRACT) == 0)
            return null;
        for (Scope.Entry e = t2super.tsym.members().elems; e != null; e = e.sibling) {
            if (e.sym.kind == MTH && (e.sym.flags() & ABSTRACT) != 0 &&
                    (site == null || e.sym.isInheritedIn(site.tsym)) &&
                    !isCompatible(t1, t1, t2, e.sym))
                return e.sym;
        }
        for (List is = t2super.interfaces(); is.nonEmpty(); is = is.tail) {
            Symbol sym = firstIncompatibility(t1, t2, (Type) is.head, site);
            if (sym != null)
                return sym;
        }
        return (t2super.supertype().tag == CLASS) ?
                firstIncompatibility(t1, t2, t2super.supertype(), site) : null;
    }

    /**
      * Check that supertype `t1super' of type `t1' does not define
      *  an abstract method with with same name and argument types but
      *  a different return type than its definition in type `t2'.
      *  @param t1       The first type.
      *  @param t1super  The first type's supertype.
      *  @param t2       The second type.
      *  @param sym      The method symbol.
      */
    private boolean isCompatible(Type t1, Type t1super, Type t2, Symbol sym) {
        for (Scope.Entry e = t1super.tsym.members().lookup(sym.name);
                e.scope != null; e = e.next()) {
            if (e.sym.kind == MTH && (e.sym.flags() & ABSTRACT) != 0) {
                Type symt1 = t1.memberType(e.sym);
                Type symt2 = t2.memberType(sym);
                if (symt1.hasSameArgs(symt2)) {
                    List tvars1 = symt1.typarams();
                    List tvars2 = symt2.typarams();
                    Type rt1 = symt1.restype();
                    Type rt2 = symt2.restype().subst(tvars2, tvars1);
                    return rt1.isSameType(rt2);
                }
            }
        }
        for (List is = t1super.interfaces(); is.nonEmpty(); is = is.tail) {
            if (!isCompatible(t1, (Type) is.head, t2, sym))
                return false;
        }
        return (t1super.supertype().tag == CLASS &&
                (t1super.supertype().tsym.flags() & ABSTRACT) != 0) ?
                isCompatible(t1, t1super.supertype(), t2, sym) : true;
    }

    /**
      * Check that (arrays of) interfaces do not each define a method
      *  with same name and arguments but different return types.
      *  If either argument type is not an (array of) interface type, do
      *  nothing.
      *  @param pos          Position to be used for error reporting.
      *  @param t1           The first argument type.
      *  @param t2           The second argument type.
      */
    public boolean checkCompatible(int pos, Type t1, Type t2) {
        if (t1.tag == ARRAY && t2.tag == ARRAY) {
            checkCompatible(pos, t1.elemtype(), t2.elemtype());
        } else if (t1.tag == CLASS && (t1.tsym.flags() & INTERFACE) != 0 &&
                t2.tag == CLASS && (t2.tsym.flags() & INTERFACE) != 0) {
            return checkCompatibleAbstracts(pos, t1, t2, null);
        }
        return true;
    }

    /**
      * Check that classes (or interfaces) do not each define an abstract
      *  method with same name and arguments but different return types.
      *  @param pos          Position to be used for error reporting.
      *  @param t1           The first argument type.
      *  @param t2           The second argument type.
      */
    public boolean checkCompatibleAbstracts(int pos, Type t1, Type t2, Type site) {
        Symbol sym = firstIncompatibility(t1, t2, site);
        if (sym != null) {
            log.error(pos, "types.incompatible.diff.ret", t1.toJava(), t2.toJava(),
                    sym.name + "(" + t2.memberType(sym).argtypes() + ")");
            return false;
        }
        return true;
    }

    /**
      * Check that all abstract members of given class have definitions.
      *  @param pos          Position to be used for error reporting.
      *  @param c            The class.
      */
    void checkAllDefined(int pos, ClassSymbol c) {
        try {
            MethodSymbol undef = firstUndef(c, c);
            if (undef != null) {
                MethodSymbol undef1 = new MethodSymbol(undef.flags(), undef.name,
                        c.type.memberType(undef), undef.owner);
                log.error(pos, "does.not.override.abstract", c.toJava(),
                        undef1.toJava(), undef1.javaLocation());
            }
        } catch (CompletionFailure ex) {
            completionError(pos, ex);
        }
    }

    /**
      * Return first abstract member of class `c' that is not defined
      *  in `impl', null if there is none.
      */
    private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) {
        MethodSymbol undef = null;
        if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
            Scope s = c.members();
            for (Scope.Entry e = s.elems; undef == null && e != null; e = e.sibling) {
                if (e.sym.kind == MTH &&
                        (e.sym.flags() & (ABSTRACT | IPROXY)) == ABSTRACT) {
                    MethodSymbol absmeth = (MethodSymbol) e.sym;
                    MethodSymbol implmeth = absmeth.implementation(impl);
                    if (implmeth == null || implmeth == absmeth)
                        undef = absmeth;
                }
            }
            if (undef == null) {
                Type st = c.type.supertype();
                if (st.tag == CLASS)
                    undef = firstUndef(impl, (ClassSymbol) st.tsym);
            }
            for (List l = c.type.interfaces(); undef == null && l.nonEmpty();
                    l = l.tail) {
                undef = firstUndef(impl, (ClassSymbol)((Type) l.head).tsym);
            }
        }
        return undef;
    }

    /**
      * Check for cyclic references. Issue an error if the
      *  symbol of the type referred to has a LOCKED flag set.
      *
      *  @param pos      Position to be used for error reporting.
      *  @param t        The type referred to.
      */
    Type checkNonCyclic(int pos, Type t) {
        Symbol c = t.tsym;
        if ((c.flags_field & LOCKED) != 0) {
            log.error(pos, "cyclic.inheritance", c.toJava());
            t = new ErrorType((ClassSymbol) c);
        } else if ((c.flags_field & ACYCLIC) != 0) {
            return t;
        } else if (!c.type.isErroneous()) {
            try {
                c.flags_field |= LOCKED;
                for (List l = c.type.interfaces(); l.nonEmpty(); l = l.tail)
                    l.head = checkNonCyclic(pos, (Type) l.head);
                Type st = c.type.supertype();
                if (st != null && st.tag == CLASS)
                    ((ClassType) c.type).supertype_field = checkNonCyclic(pos, st);
            }
            finally { c.flags_field &= ~LOCKED;
                    } }
        c.flags_field |= ACYCLIC;
        return t;
    }

    /**
      * Check that all methods which implement some
      *  method conform to the method they implement.
      *  @param tree         The class definition whose members are checked.
      */
    void checkImplementations(ClassDef tree) {
        checkImplementations(tree, tree.sym);
    }

    /**
      * Check that all methods which implement some
      *  method in `ic' conform to the method they implement.
      */
    void checkImplementations(ClassDef tree, ClassSymbol ic) {
        ClassSymbol origin = tree.sym;
        if ((origin != ic) && (ic.flags() & ABSTRACT) != 0) {
            for (Scope.Entry e = ic.members().elems; e != null; e = e.sibling) {
                if (e.sym.kind == MTH &&
                        (e.sym.flags() & (STATIC | ABSTRACT)) == ABSTRACT) {
                    MethodSymbol absmeth = (MethodSymbol) e.sym;
                    MethodSymbol implmeth = absmeth.implementation(origin);
                    if (implmeth != null && implmeth != absmeth &&
                            (implmeth.owner.flags() & INTERFACE) ==
                            (origin.flags() & INTERFACE)) {
                        checkOverride(tree, implmeth, absmeth, origin);
                    }
                }
            }
        }
        Type st = ic.type.supertype();
        if (st.tag == CLASS)
            checkImplementations(tree, (ClassSymbol) st.tsym);
        for (List l = ic.type.interfaces(); l.nonEmpty(); l = l.tail)
            checkImplementations(tree, (ClassSymbol)((Type) l.head).tsym);
    }

    /**
      * Check that all abstract methods implemented by a class are
      *  mutually compatible.
      *  @param pos          Position to be used for error reporting.
      *  @param c            The class whose interfaces are checked.
      */
    void checkCompatibleSupertypes(int pos, Type c) {
        List supertypes = c.interfaces();
        Type supertype = c.supertype();
        if (supertype.tag == CLASS && (supertype.tsym.flags() & ABSTRACT) != 0)
            supertypes = supertypes.prepend(supertype);
        for (List l = supertypes; l.nonEmpty(); l = l.tail) {
            for (List m = supertypes; m != l; m = m.tail)
                if (!checkCompatibleAbstracts(pos, (Type) l.head, (Type) m.head, c))
                    return;
        }
    }

    /**
      * Enter interface into into set.
      *  If it existed already, issue a "repeated interface" error.
      */
    void checkNotRepeated(int pos, Type it, Set its) {
        if (its.contains(it))
            log.error(pos, "repeated.interface");
        else {
            its.put(it);
        }
    }

    /**
      * Check for cycles in the graph of constructors calling other
      *  constructors.
      */
    void checkCyclicConstructors(ClassDef tree) {
        Hashtable callMap = new Hashtable();
        for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
            Apply app = TreeInfo.firstConstructorCall((Tree) l.head);
            if (app == null)
                continue;
            MethodDef meth = (MethodDef) l.head;
            if (TreeInfo.name(app.meth) == names._this) {
                callMap.put(meth.sym, TreeInfo.symbol(app.meth));
            } else {
                meth.sym.flags_field |= ACYCLIC;
            }
        }
        for (List callers = callMap.keys(); callers.nonEmpty();
                callers = callers.tail) {
            checkCyclicConstructor(tree, (Symbol) callers.head, callMap);
        }
    }

    /**
      * Look in the map to see if the given constructor is part of a
      *  call cycle.
      */
    private void checkCyclicConstructor(ClassDef tree, Symbol ctor,
            Hashtable callMap) {
        if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
            if ((ctor.flags_field & LOCKED) != 0) {
                log.error(TreeInfo.positionFor(ctor, tree), "recursive.ctor.invocation");
            } else {
                ctor.flags_field |= LOCKED;
                checkCyclicConstructor(tree, (Symbol) callMap.remove(ctor), callMap);
                ctor.flags_field &= ~LOCKED;
            }
            ctor.flags_field |= ACYCLIC;
        }
    }

    /**
      * Check that a qualified name is in canonical form (for import decls).
      */
    public void checkCanonical(Tree tree) {
        if (!isCanonical(tree))
            log.error(tree.pos, "import.requires.canonical",
                    TreeInfo.symbol(tree).toJava());
    }

    private boolean isCanonical(Tree tree) {
        while (tree.tag == Tree.SELECT) {
            Select s = (Select) tree;
            if (s.sym.owner != TreeInfo.symbol(s.selected))
                return false;
            tree = s.selected;
        }
        return true;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -