|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.tools.java; |
|
|
|
import java.util.Stack; |
|
import java.io.IOException; |
|
import sun.tools.tree.Context; |
|
|
|
import java.io.File; |
|
//end JCOV |
|
|
|
/** |
|
* This class defines the environment for a compilation. |
|
* It is used to load classes, resolve class names and |
|
* report errors. It is an abstract class, a subclass |
|
* must define implementations for some of the functions.<p> |
|
* |
|
* An environment has a source object associated with it. |
|
* This is the thing against which errors are reported, it |
|
* is usually a file name, a field or a class.<p> |
|
* |
|
* Environments can be nested to change the source object.<p> |
|
* |
|
* WARNING: The contents of this source file are not part of any |
|
* supported API. Code that depends on them does so at its own risk: |
|
* they are subject to change or removal without notice. |
|
* |
|
* @author Arthur van Hoff |
|
*/ |
|
|
|
public class Environment implements Constants { |
|
|
|
|
|
*/ |
|
Environment env; |
|
|
|
|
|
|
|
*/ |
|
String encoding; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Object source; |
|
|
|
public Environment(Environment env, Object source) { |
|
if (env != null && env.env != null && env.getClass() == this.getClass()) |
|
env = env.env; |
|
this.env = env; |
|
this.source = source; |
|
} |
|
public Environment() { |
|
this(null, null); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isExemptPackage(Identifier id) { |
|
return env.isExemptPackage(id); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ClassDeclaration getClassDeclaration(Identifier nm) { |
|
return env.getClassDeclaration(nm); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound { |
|
if (nm.isInner()) { |
|
ClassDefinition c = getClassDefinition(nm.getTopName()); |
|
Identifier tail = nm.getFlatName(); |
|
walkTail: |
|
while (tail.isQualified()) { |
|
tail = tail.getTail(); |
|
Identifier head = tail.getHead(); |
|
|
|
String hname = head.toString(); |
|
// If the name is of the form 'ClassName.N$localName', where N is |
|
// a number, the field 'N$localName' may not necessarily be a member |
|
// of the class named by 'ClassName', but might be a member of some |
|
// inaccessible class contained within it. We use 'getLocalClass' |
|
// to do the lookup in this case. This is part of a fix for bugid |
|
// 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'. |
|
// This should also work for anonymous class names of the form |
|
// 'ClassName.N'. Note that the '.' qualifications get converted to |
|
// '$' characters when determining the external name of the class and |
|
|
|
if (hname.length() > 0 |
|
&& Character.isDigit(hname.charAt(0))) { |
|
ClassDefinition localClass = c.getLocalClass(hname); |
|
if (localClass != null) { |
|
c = localClass; |
|
continue walkTail; |
|
} |
|
} else { |
|
for (MemberDefinition f = c.getFirstMatch(head); |
|
f != null; f = f.getNextMatch()) { |
|
if (f.isInnerClass()) { |
|
c = f.getInnerClass(); |
|
continue walkTail; |
|
} |
|
} |
|
} |
|
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head)); |
|
} |
|
|
|
return c; |
|
} |
|
return getClassDeclaration(nm).getClassDefinition(this); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassDeclaration getClassDeclaration(Type t) { |
|
return getClassDeclaration(t.getClassName()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound { |
|
return getClassDefinition(t.getClassName()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean classExists(Identifier nm) { |
|
return env.classExists(nm); |
|
} |
|
|
|
public final boolean classExists(Type t) { |
|
return !t.isType(TC_CLASS) || classExists(t.getClassName()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Package getPackage(Identifier pkg) throws IOException { |
|
return env.getPackage(pkg); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void loadDefinition(ClassDeclaration c) { |
|
env.loadDefinition(c); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final Object getSource() { |
|
return source; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean resolve(long where, ClassDefinition c, Type t) { |
|
switch (t.getTypeCode()) { |
|
case TC_CLASS: { |
|
ClassDefinition def; |
|
try { |
|
Identifier nm = t.getClassName(); |
|
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) { |
|
resolve(nm); |
|
} |
|
def = getQualifiedClassDefinition(where, nm, c, false); |
|
if (!c.canAccess(this, def.getClassDeclaration())) { |
|
// Reported error location may be imprecise |
|
|
|
error(where, "cant.access.class", def); |
|
return true; |
|
} |
|
def.noteUsedBy(c, where, env); |
|
} catch (AmbiguousClass ee) { |
|
error(where, "ambig.class", ee.name1, ee.name2); |
|
return false; |
|
} catch (ClassNotFound e) { |
|
// For now, report "class.and.package" only when the code |
|
|
|
try { |
|
if (e.name.isInner() && |
|
getPackage(e.name.getTopName()).exists()) { |
|
env.error(where, "class.and.package", |
|
e.name.getTopName()); |
|
} |
|
} catch (IOException ee) { |
|
env.error(where, "io.exception", "package check"); |
|
} |
|
// This error message is also emitted for 'new' expressions. |
|
|
|
error(where, "class.not.found.no.context", e.name); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
case TC_ARRAY: |
|
return resolve(where, c, t.getElementType()); |
|
|
|
case TC_METHOD: |
|
boolean ok = resolve(where, c, t.getReturnType()); |
|
Type args[] = t.getArgumentTypes(); |
|
for (int i = args.length ; i-- > 0 ; ) { |
|
ok &= resolve(where, c, args[i]); |
|
} |
|
return ok; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean resolveByName(long where, ClassDefinition c, Identifier nm) { |
|
return resolveByName(where, c, nm, false); |
|
} |
|
|
|
public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) { |
|
return resolveByName(where, c, nm, true); |
|
} |
|
|
|
private boolean resolveByName(long where, ClassDefinition c, |
|
Identifier nm, boolean isExtends) { |
|
ClassDefinition def; |
|
try { |
|
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) { |
|
resolve(nm); |
|
} |
|
def = getQualifiedClassDefinition(where, nm, c, isExtends); |
|
ClassDeclaration decl = def.getClassDeclaration(); |
|
if (!((!isExtends && c.canAccess(this, decl)) |
|
|| |
|
(isExtends && c.extendsCanAccess(this, decl)))) { |
|
error(where, "cant.access.class", def); |
|
return true; |
|
} |
|
} catch (AmbiguousClass ee) { |
|
error(where, "ambig.class", ee.name1, ee.name2); |
|
return false; |
|
} catch (ClassNotFound e) { |
|
// For now, report "class.and.package" only when the code |
|
|
|
try { |
|
if (e.name.isInner() && |
|
getPackage(e.name.getTopName()).exists()) { |
|
env.error(where, "class.and.package", |
|
e.name.getTopName()); |
|
} |
|
} catch (IOException ee) { |
|
env.error(where, "io.exception", "package check"); |
|
} |
|
error(where, "class.not.found", e.name, "type name"); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final ClassDefinition |
|
getQualifiedClassDefinition(long where, |
|
Identifier nm, |
|
ClassDefinition ctxClass, |
|
boolean isExtends) throws ClassNotFound { |
|
if (nm.isInner()) { |
|
ClassDefinition c = getClassDefinition(nm.getTopName()); |
|
Identifier tail = nm.getFlatName(); |
|
walkTail: |
|
while (tail.isQualified()) { |
|
tail = tail.getTail(); |
|
Identifier head = tail.getHead(); |
|
|
|
String hname = head.toString(); |
|
// Handle synthesized names of local and anonymous classes. |
|
|
|
if (hname.length() > 0 |
|
&& Character.isDigit(hname.charAt(0))) { |
|
ClassDefinition localClass = c.getLocalClass(hname); |
|
if (localClass != null) { |
|
c = localClass; |
|
continue walkTail; |
|
} |
|
} else { |
|
for (MemberDefinition f = c.getFirstMatch(head); |
|
f != null; f = f.getNextMatch()) { |
|
if (f.isInnerClass()) { |
|
ClassDeclaration rdecl = c.getClassDeclaration(); |
|
c = f.getInnerClass(); |
|
ClassDeclaration fdecl = c.getClassDeclaration(); |
|
// This check is presumably applicable even if the |
|
// original source-code name (expanded by 'resolveNames') |
|
// was a simple, unqualified name. Hopefully, JLS 2e |
|
|
|
if ((!isExtends |
|
&& !ctxClass.canAccess(env, fdecl)) |
|
|| |
|
(isExtends |
|
&& !ctxClass.extendsCanAccess(env, fdecl))) { |
|
|
|
env.error(where, "no.type.access", head, rdecl, ctxClass); |
|
} |
|
// The JLS 6.6.2 restrictions on access to protected members |
|
// depend in an essential way upon the syntactic form of the name. |
|
// Since the compiler has previously expanded the class names |
|
// here into fully-qualified form ('resolveNames'), this check |
|
// cannot be performed here. Unfortunately, the original names |
|
// are clobbered during 'basicCheck', which is also the phase that |
|
// resolves the inheritance structure, required to implement the |
|
// access restrictions. Pending a large-scale revision of the |
|
// name-resolution machinery, we forgo this check, with the result |
|
// that the JLS 6.6.2 restrictions are not enforced for some cases |
|
// of qualified access to inner classes. Some qualified names are |
|
// resolved elsewhere via a different mechanism, and will be |
|
// treated correctly -- see 'FieldExpression.checkCommon'. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*---------------------------------------*/ |
|
continue walkTail; |
|
} |
|
} |
|
} |
|
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head)); |
|
} |
|
|
|
return c; |
|
} |
|
return getClassDeclaration(nm).getClassDefinition(this); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Type resolveNames(ClassDefinition c, Type t, boolean synth) { |
|
if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t); |
|
switch (t.getTypeCode()) { |
|
case TC_CLASS: { |
|
Identifier name = t.getClassName(); |
|
Identifier rname; |
|
if (synth) { |
|
rname = resolvePackageQualifiedName(name); |
|
} else { |
|
rname = c.resolveName(this, name); |
|
} |
|
if (name != rname) { |
|
t = Type.tClass(rname); |
|
} |
|
break; |
|
} |
|
|
|
case TC_ARRAY: |
|
t = Type.tArray(resolveNames(c, t.getElementType(), synth)); |
|
break; |
|
|
|
case TC_METHOD: { |
|
Type ret = t.getReturnType(); |
|
Type rret = resolveNames(c, ret, synth); |
|
Type args[] = t.getArgumentTypes(); |
|
Type rargs[] = new Type[args.length]; |
|
boolean changed = (ret != rret); |
|
for (int i = args.length ; i-- > 0 ; ) { |
|
Type arg = args[i]; |
|
Type rarg = resolveNames(c, arg, synth); |
|
rargs[i] = rarg; |
|
if (arg != rarg) { |
|
changed = true; |
|
} |
|
} |
|
if (changed) { |
|
t = Type.tMethod(rret, rargs); |
|
} |
|
break; |
|
} |
|
} |
|
return t; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Identifier resolveName(Identifier name) { |
|
// This logic is pretty exactly parallel to that of |
|
|
|
if (name.isQualified()) { |
|
// Try to resolve the first identifier component, |
|
// because inner class names take precedence over |
|
|
|
Identifier rhead = resolveName(name.getHead()); |
|
|
|
if (rhead.hasAmbigPrefix()) { |
|
// The first identifier component refers to an |
|
// ambiguous class. Limp on. We throw away the |
|
// rest of the classname as it is irrelevant. |
|
|
|
return rhead; |
|
} |
|
|
|
if (!this.classExists(rhead)) { |
|
return this.resolvePackageQualifiedName(name); |
|
} |
|
try { |
|
return this.getClassDefinition(rhead). |
|
resolveInnerClass(this, name.getTail()); |
|
} catch (ClassNotFound ee) { |
|
|
|
return Identifier.lookupInner(rhead, name.getTail()); |
|
} |
|
} |
|
try { |
|
return resolve(name); |
|
} catch (AmbiguousClass ee) { |
|
// Don't force a resolution of the name if it is ambiguous. |
|
// Forcing the resolution would tack the current package |
|
// name onto the front of the class, which would be wrong. |
|
// Instead, mark the name as ambiguous and let a later stage |
|
// find the error by calling env.resolve(name). |
|
// (part of solution for 4059855). |
|
|
|
if (name.hasAmbigPrefix()) { |
|
return name; |
|
} else { |
|
return name.addAmbigPrefix(); |
|
} |
|
} catch (ClassNotFound ee) { |
|
|
|
Imports imports = getImports(); |
|
if (imports != null) |
|
return imports.forceResolve(this, name); |
|
} |
|
return name; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final Identifier resolvePackageQualifiedName(Identifier name) { |
|
Identifier tail = null; |
|
for (;;) { |
|
if (classExists(name)) { |
|
break; |
|
} |
|
if (!name.isQualified()) { |
|
name = (tail == null) ? name : Identifier.lookup(name, tail); |
|
tail = null; |
|
break; |
|
} |
|
Identifier nm = name.getName(); |
|
tail = (tail == null)? nm: Identifier.lookup(nm, tail); |
|
name = name.getQualifier(); |
|
} |
|
if (tail != null) |
|
name = Identifier.lookupInner(name, tail); |
|
return name; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Identifier resolve(Identifier nm) throws ClassNotFound { |
|
if (env == null) return nm; |
|
return env.resolve(nm); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Imports getImports() { |
|
if (env == null) return null; |
|
return env.getImports(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ClassDefinition makeClassDefinition(Environment origEnv, long where, |
|
IdentifierToken name, |
|
String doc, int modifiers, |
|
IdentifierToken superClass, |
|
IdentifierToken interfaces[], |
|
ClassDefinition outerClass) { |
|
if (env == null) return null; |
|
return env.makeClassDefinition(origEnv, where, name, |
|
doc, modifiers, |
|
superClass, interfaces, outerClass); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public MemberDefinition makeMemberDefinition(Environment origEnv, long where, |
|
ClassDefinition clazz, |
|
String doc, int modifiers, |
|
Type type, Identifier name, |
|
IdentifierToken argNames[], |
|
IdentifierToken expIds[], |
|
Object value) { |
|
if (env == null) return null; |
|
return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers, |
|
type, name, argNames, expIds, value); |
|
} |
|
|
|
/** |
|
* Returns true if the given method is applicable to the given arguments |
|
*/ |
|
|
|
public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound { |
|
Type mType = m.getType(); |
|
if (!mType.isType(TC_METHOD)) |
|
return false; |
|
Type mArgs[] = mType.getArgumentTypes(); |
|
if (args.length != mArgs.length) |
|
return false; |
|
for (int i = args.length ; --i >= 0 ;) |
|
if (!isMoreSpecific(args[i], mArgs[i])) |
|
return false; |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other) |
|
throws ClassNotFound { |
|
Type bestType = best.getClassDeclaration().getType(); |
|
Type otherType = other.getClassDeclaration().getType(); |
|
boolean result = isMoreSpecific(bestType, otherType) |
|
&& isApplicable(other, best.getType().getArgumentTypes()); |
|
// System.out.println("isMoreSpecific: " + best + "/" + other |
|
|
|
return result; |
|
} |
|
|
|
/** |
|
* Returns true if "from" is a more specific type than "to" |
|
*/ |
|
|
|
public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound { |
|
return implicitCast(from, to); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean implicitCast(Type from, Type to) throws ClassNotFound { |
|
if (from == to) |
|
return true; |
|
|
|
int toTypeCode = to.getTypeCode(); |
|
|
|
switch(from.getTypeCode()) { |
|
case TC_BYTE: |
|
if (toTypeCode == TC_SHORT) |
|
return true; |
|
case TC_SHORT: |
|
case TC_CHAR: |
|
if (toTypeCode == TC_INT) return true; |
|
case TC_INT: |
|
if (toTypeCode == TC_LONG) return true; |
|
case TC_LONG: |
|
if (toTypeCode == TC_FLOAT) return true; |
|
case TC_FLOAT: |
|
if (toTypeCode == TC_DOUBLE) return true; |
|
case TC_DOUBLE: |
|
default: |
|
return false; |
|
|
|
case TC_NULL: |
|
return to.inMask(TM_REFERENCE); |
|
|
|
case TC_ARRAY: |
|
if (!to.isType(TC_ARRAY)) { |
|
return (to == Type.tObject || to == Type.tCloneable |
|
|| to == Type.tSerializable); |
|
} else { |
|
|
|
do { |
|
from = from.getElementType(); |
|
to = to.getElementType(); |
|
} while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY)); |
|
if ( from.inMask(TM_ARRAY|TM_CLASS) |
|
&& to.inMask(TM_ARRAY|TM_CLASS)) { |
|
return isMoreSpecific(from, to); |
|
} else { |
|
return (from.getTypeCode() == to.getTypeCode()); |
|
} |
|
} |
|
|
|
case TC_CLASS: |
|
if (toTypeCode == TC_CLASS) { |
|
ClassDefinition fromDef = getClassDefinition(from); |
|
ClassDefinition toDef = getClassDefinition(to); |
|
return toDef.implementedBy(this, |
|
fromDef.getClassDeclaration()); |
|
} else { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean explicitCast(Type from, Type to) throws ClassNotFound { |
|
if (implicitCast(from, to)) { |
|
return true; |
|
} |
|
if (from.inMask(TM_NUMBER)) { |
|
return to.inMask(TM_NUMBER); |
|
} |
|
if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) { |
|
ClassDefinition fromClass = getClassDefinition(from); |
|
ClassDefinition toClass = getClassDefinition(to); |
|
if (toClass.isFinal()) { |
|
return fromClass.implementedBy(this, |
|
toClass.getClassDeclaration()); |
|
} |
|
if (fromClass.isFinal()) { |
|
return toClass.implementedBy(this, |
|
fromClass.getClassDeclaration()); |
|
} |
|
|
|
// The code here used to omit this case. If both types |
|
// involved in a cast are interfaces, then JLS 5.5 requires |
|
// that we do a simple test -- make sure none of the methods |
|
// in toClass and fromClass have the same signature but |
|
|
|
if (toClass.isInterface() && fromClass.isInterface()) { |
|
return toClass.couldImplement(fromClass); |
|
} |
|
|
|
return toClass.isInterface() || |
|
fromClass.isInterface() || |
|
fromClass.superClassOf(this, toClass.getClassDeclaration()); |
|
} |
|
if (to.isType(TC_ARRAY)) { |
|
if (from.isType(TC_ARRAY)) { |
|
Type t1 = from.getElementType(); |
|
Type t2 = to.getElementType(); |
|
while ((t1.getTypeCode() == TC_ARRAY) |
|
&& (t2.getTypeCode() == TC_ARRAY)) { |
|
t1 = t1.getElementType(); |
|
t2 = t2.getElementType(); |
|
} |
|
if (t1.inMask(TM_ARRAY|TM_CLASS) && |
|
t2.inMask(TM_ARRAY|TM_CLASS)) { |
|
return explicitCast(t1, t2); |
|
} |
|
} else if (from == Type.tObject || from == Type.tCloneable |
|
|| from == Type.tSerializable) |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public int getFlags() { |
|
return env.getFlags(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final boolean debug_lines() { |
|
return (getFlags() & F_DEBUG_LINES) != 0; |
|
} |
|
public final boolean debug_vars() { |
|
return (getFlags() & F_DEBUG_VARS) != 0; |
|
} |
|
public final boolean debug_source() { |
|
return (getFlags() & F_DEBUG_SOURCE) != 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final boolean opt() { |
|
return (getFlags() & F_OPT) != 0; |
|
} |
|
public final boolean opt_interclass() { |
|
return (getFlags() & F_OPT_INTERCLASS) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean verbose() { |
|
return (getFlags() & F_VERBOSE) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean dump() { |
|
return (getFlags() & F_DUMP) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean warnings() { |
|
return (getFlags() & F_WARNINGS) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean dependencies() { |
|
return (getFlags() & F_DEPENDENCIES) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean print_dependencies() { |
|
return (getFlags() & F_PRINT_DEPENDENCIES) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean deprecation() { |
|
return (getFlags() & F_DEPRECATION) != 0; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final boolean version12() { |
|
return (getFlags() & F_VERSION12) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean strictdefault() { |
|
return (getFlags() & F_STRICTDEFAULT) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void shutdown() { |
|
if (env != null) { |
|
env.shutdown(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) { |
|
env.error(source, where, err, arg1, arg2, arg3); |
|
} |
|
public final void error(long where, String err, Object arg1, Object arg2, Object arg3) { |
|
error(source, where, err, arg1, arg2, arg3); |
|
} |
|
public final void error(long where, String err, Object arg1, Object arg2) { |
|
error(source, where, err, arg1, arg2, null); |
|
} |
|
public final void error(long where, String err, Object arg1) { |
|
error(source, where, err, arg1, null, null); |
|
} |
|
public final void error(long where, String err) { |
|
error(source, where, err, null, null, null); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void output(String msg) { |
|
env.output(msg); |
|
} |
|
|
|
private static boolean debugging = (System.getProperty("javac.debug") != null); |
|
|
|
public static void debugOutput(Object msg) { |
|
if (Environment.debugging) |
|
System.out.println(msg.toString()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setCharacterEncoding(String encoding) { |
|
this.encoding = encoding; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String getCharacterEncoding() { |
|
return encoding; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public short getMajorVersion() { |
|
if (env==null) return JAVA_DEFAULT_VERSION; |
|
return env.getMajorVersion(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public short getMinorVersion() { |
|
if (env==null) return JAVA_DEFAULT_MINOR_VERSION; |
|
return env.getMinorVersion(); |
|
} |
|
|
|
// JCOV |
|
|
|
|
|
*/ |
|
public final boolean coverage() { |
|
return (getFlags() & F_COVERAGE) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public final boolean covdata() { |
|
return (getFlags() & F_COVDATA) != 0; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public File getcovFile() { |
|
return env.getcovFile(); |
|
} |
|
|
|
// end JCOV |
|
|
|
/** |
|
* Debug tracing. |
|
* Currently, this code is used only for tracing the loading and |
|
* checking of classes, particularly the demand-driven aspects. |
|
* This code should probably be integrated with 'debugOutput' above, |
|
* but we need to give more thought to the issue of classifying debugging |
|
* messages and allowing those only those of interest to be enabled. |
|
* |
|
* Calls to these methods are generally conditioned on the final variable |
|
* 'Constants.tracing', which allows the calls to be completely omitted |
|
* in a production release to avoid space and time overhead. |
|
*/ |
|
|
|
private static boolean dependtrace = |
|
(System.getProperty("javac.trace.depend") != null); |
|
|
|
public void dtEnter(String s) { |
|
if (dependtrace) System.out.println(">>> " + s); |
|
} |
|
|
|
public void dtExit(String s) { |
|
if (dependtrace) System.out.println("<<< " + s); |
|
} |
|
|
|
public void dtEvent(String s) { |
|
if (dependtrace) System.out.println(s); |
|
} |
|
|
|
/** |
|
* Enable diagnostic dump of class modifier bits, including those |
|
* in InnerClasses attributes, as they are written to the classfile. |
|
* In the future, may also enable dumping field and method modifiers. |
|
*/ |
|
|
|
private static boolean dumpmodifiers = |
|
(System.getProperty("javac.dump.modifiers") != null); |
|
|
|
public boolean dumpModifiers() { return dumpmodifiers; } |
|
|
|
} |