📄 check.java
字号:
/* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.comp;import java.util.*;import java.util.Set;import com.sun.tools.javac.code.*;import com.sun.tools.javac.jvm.*;import com.sun.tools.javac.tree.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;import com.sun.tools.javac.util.List;import com.sun.tools.javac.tree.JCTree.*;import com.sun.tools.javac.code.Lint;import com.sun.tools.javac.code.Lint.LintCategory;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.code.Symbol.*;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;/** Type checking helper class for the attribution phase. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class Check { protected static final Context.Key<Check> checkKey = new Context.Key<Check>(); private final Name.Table names; private final Log log; private final Symtab syms; private final Infer infer; private final Target target; private final Source source; private final Types types; private final boolean skipAnnotations; private final TreeInfo treeinfo; // The set of lint options currently in effect. It is initialized // from the context, and then is set/reset as needed by Attr as it // visits all the various parts of the trees during attribution. private Lint lint; public static Check instance(Context context) { Check instance = context.get(checkKey); if (instance == null) instance = new Check(context); return instance; } protected Check(Context context) { context.put(checkKey, this); names = Name.Table.instance(context); log = Log.instance(context); syms = Symtab.instance(context); infer = Infer.instance(context); this.types = Types.instance(context); Options options = Options.instance(context); target = Target.instance(context); source = Source.instance(context); lint = Lint.instance(context); treeinfo = TreeInfo.instance(context); Source source = Source.instance(context); allowGenerics = source.allowGenerics(); allowAnnotations = source.allowAnnotations(); complexInference = options.get("-complexinference") != null; skipAnnotations = options.get("skipAnnotations") != null; boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); deprecationHandler = new MandatoryWarningHandler(log,verboseDeprecated, "deprecated"); uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, "unchecked"); } /** Switch: generics enabled? */ boolean allowGenerics; /** Switch: annotations enabled? */ boolean allowAnnotations; /** Switch: -complexinference option set? */ boolean complexInference; /** A table mapping flat names of all compiled classes in this run to their * symbols; maintained from outside. */ public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>(); /** A handler for messages about deprecated usage. */ private MandatoryWarningHandler deprecationHandler; /** A handler for messages about unchecked or unsafe usage. */ private MandatoryWarningHandler uncheckedHandler;/* ************************************************************************* * Errors and Warnings **************************************************************************/ Lint setLint(Lint newLint) { Lint prev = lint; lint = newLint; return prev; } /** Warn about deprecated symbol. * @param pos Position to be used for error reporting. * @param sym The deprecated symbol. */ void warnDeprecated(DiagnosticPosition pos, Symbol sym) { if (!lint.isSuppressed(LintCategory.DEPRECATION)) deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); } /** Warn about unchecked operation. * @param pos Position to be used for error reporting. * @param msg A string describing the problem. */ public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) { if (!lint.isSuppressed(LintCategory.UNCHECKED)) uncheckedHandler.report(pos, msg, args); } /** * Report any deferred diagnostics. */ public void reportDeferredDiagnostics() { deprecationHandler.reportDeferredDiagnostic(); uncheckedHandler.reportDeferredDiagnostic(); } /** Report a failure to complete a class. * @param pos Position to be used for error reporting. * @param ex The failure to report. */ public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { log.error(pos, "cant.access", ex.sym, ex.errmsg); if (ex instanceof ClassReader.BadClassFile) throw new Abort(); else return syms.errType; } /** Report a type error. * @param pos Position to be used for error reporting. * @param problem A string describing the error. * @param found The type that was found. * @param req The type that was required. */ Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) { log.error(pos, "prob.found.req", problem, found, req); return syms.errType; } Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) { log.error(pos, "prob.found.req.1", problem, found, req, explanation); return syms.errType; } /** Report an error that wrong type tag was found. * @param pos Position to be used for error reporting. * @param required An internationalized string describing the type tag * required. * @param found The type that was found. */ Type typeTagError(DiagnosticPosition pos, Object required, Object found) { log.error(pos, "type.found.req", found, required); return syms.errType; } /** Report an error that symbol cannot be referenced before super * has been called. * @param pos Position to be used for error reporting. * @param sym The referenced symbol. */ void earlyRefError(DiagnosticPosition pos, Symbol sym) { log.error(pos, "cant.ref.before.ctor.called", sym); } /** Report duplicate declaration error. */ void duplicateError(DiagnosticPosition pos, Symbol sym) { if (!sym.type.isErroneous()) { log.error(pos, "already.defined", sym, sym.location()); } } /** Report array/varargs duplicate declaration */ void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { log.error(pos, "array.and.varargs", sym1, sym2, sym2.location()); } }/* ************************************************************************ * duplicate declaration checking *************************************************************************/ /** Check that variable does not hide variable with same name in * immediately enclosing local scope. * @param pos Position for error reporting. * @param v The symbol. * @param s The scope. */ void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { if (s.next != null) { for (Scope.Entry e = s.next.lookup(v.name); e.scope != null && e.sym.owner == v.owner; e = e.next()) { if (e.sym.kind == VAR && (e.sym.owner.kind & (VAR | MTH)) != 0 && v.name != names.error) { duplicateError(pos, e.sym); return; } } } } /** Check that a class or interface does not hide a class or * interface with same name in immediately enclosing local scope. * @param pos Position for error reporting. * @param c The symbol. * @param s The scope. */ void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { if (s.next != null) { for (Scope.Entry e = s.next.lookup(c.name); e.scope != null && e.sym.owner == c.owner; e = e.next()) { if (e.sym.kind == TYP && (e.sym.owner.kind & (VAR | MTH)) != 0 && c.name != names.error) { duplicateError(pos, e.sym); return; } } } } /** Check that class does not have the same name as one of * its enclosing classes, or as a class defined in its enclosing scope. * return true if class is unique in its enclosing scope. * @param pos Position for error reporting. * @param name The class name. * @param s The enclosing scope. */ boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) { if (e.sym.kind == TYP && e.sym.name != names.error) { duplicateError(pos, e.sym); return false; } } for (Symbol sym = s.owner; sym != null; sym = sym.owner) { if (sym.kind == TYP && sym.name == name && sym.name != names.error) { duplicateError(pos, sym); return true; } } return true; }/* ************************************************************************* * Class name generation **************************************************************************/ /** Return name of local class. * This is of the form <enclClass> $ n <classname> * where * enclClass is the flat name of the enclosing class, * classname is the simple name of the local class */ Name localClassName(ClassSymbol c) { for (int i=1; ; i++) { Name flatname = names. fromString("" + c.owner.enclClass().flatname + target.syntheticNameChar() + i + c.name); if (compiled.get(flatname) == null) return flatname; } }/* ************************************************************************* * Type Checking **************************************************************************/ /** Check that a given type is assignable to a given proto-type. * If it is, return the type, otherwise return errType. * @param pos Position to be used for error reporting. * @param found The type that was found. * @param req The type that was required. */ Type checkType(DiagnosticPosition pos, Type found, Type req) { if (req.tag == ERROR) return req; if (found.tag == FORALL) return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); if (req.tag == NONE) return found; if (types.isAssignable(found, req, convertWarner(pos, found, req))) return found; if (found.tag <= DOUBLE && req.tag <= DOUBLE) return typeError(pos, JCDiagnostic.fragment("possible.loss.of.precision"), found, req); if (found.isSuperBound()) { log.error(pos, "assignment.from.super-bound", found); return syms.errType; } if (req.isExtendsBound()) { log.error(pos, "assignment.to.extends-bound", req); return syms.errType; } return typeError(pos, JCDiagnostic.fragment("incompatible.types"), found, req); } /** Instantiate polymorphic type to some prototype, unless * prototype is `anyPoly' in which case polymorphic type * is returned unchanged. */ Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) { if (pt == Infer.anyPoly && complexInference) { return t; } else if (pt == Infer.anyPoly || pt.tag == NONE) { Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; return instantiatePoly(pos, t, newpt, warn); } else if (pt.tag == ERROR) { return pt; } else { try { return infer.instantiateExpr(t, pt, warn); } catch (Infer.NoInstanceException ex) { if (ex.isAmbiguous) { JCDiagnostic d = ex.getDiagnostic();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -