Merge
This commit is contained in:
commit
c76e1a308a
@ -95,6 +95,7 @@ public class Kinds {
|
||||
ANNOTATION("kindname.interface"),
|
||||
CONSTRUCTOR("kindname.constructor"),
|
||||
INTERFACE("kindname.interface"),
|
||||
ENUM("kindname.enum"),
|
||||
STATIC("kindname.static"),
|
||||
TYPEVAR("kindname.type.variable"),
|
||||
BOUND("kindname.type.variable.bound"),
|
||||
@ -145,11 +146,15 @@ public class Kinds {
|
||||
return KindName.PACKAGE;
|
||||
|
||||
case ENUM:
|
||||
return KindName.ENUM;
|
||||
|
||||
case ANNOTATION_TYPE:
|
||||
case INTERFACE:
|
||||
case CLASS:
|
||||
return KindName.CLASS;
|
||||
|
||||
case INTERFACE:
|
||||
return KindName.INTERFACE;
|
||||
|
||||
case TYPE_PARAMETER:
|
||||
return KindName.TYPEVAR;
|
||||
|
||||
@ -160,8 +165,10 @@ public class Kinds {
|
||||
case EXCEPTION_PARAMETER:
|
||||
return KindName.VAR;
|
||||
|
||||
case METHOD:
|
||||
case CONSTRUCTOR:
|
||||
return KindName.CONSTRUCTOR;
|
||||
|
||||
case METHOD:
|
||||
case STATIC_INIT:
|
||||
case INSTANCE_INIT:
|
||||
return KindName.METHOD;
|
||||
|
@ -303,7 +303,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
public Env<AttrContext> attribExprToTree(JCTree expr, Env<AttrContext> env, JCTree tree) {
|
||||
breakTree = tree;
|
||||
JavaFileObject prev = log.useSource(null);
|
||||
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
||||
try {
|
||||
attribExpr(expr, env);
|
||||
} catch (BreakAttr b) {
|
||||
@ -317,7 +317,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
public Env<AttrContext> attribStatToTree(JCTree stmt, Env<AttrContext> env, JCTree tree) {
|
||||
breakTree = tree;
|
||||
JavaFileObject prev = log.useSource(null);
|
||||
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
||||
try {
|
||||
attribStat(stmt, env);
|
||||
} catch (BreakAttr b) {
|
||||
|
@ -82,15 +82,15 @@ public class Resolve {
|
||||
syms = Symtab.instance(context);
|
||||
|
||||
varNotFound = new
|
||||
ResolveError(ABSENT_VAR, syms.errSymbol, "variable not found");
|
||||
SymbolNotFoundError(ABSENT_VAR);
|
||||
wrongMethod = new
|
||||
ResolveError(WRONG_MTH, syms.errSymbol, "method not found");
|
||||
InapplicableSymbolError(syms.errSymbol);
|
||||
wrongMethods = new
|
||||
ResolveError(WRONG_MTHS, syms.errSymbol, "wrong methods");
|
||||
InapplicableSymbolsError(syms.errSymbol);
|
||||
methodNotFound = new
|
||||
ResolveError(ABSENT_MTH, syms.errSymbol, "method not found");
|
||||
SymbolNotFoundError(ABSENT_MTH);
|
||||
typeNotFound = new
|
||||
ResolveError(ABSENT_TYP, syms.errSymbol, "type not found");
|
||||
SymbolNotFoundError(ABSENT_TYP);
|
||||
|
||||
names = Names.instance(context);
|
||||
log = Log.instance(context);
|
||||
@ -110,11 +110,11 @@ public class Resolve {
|
||||
|
||||
/** error symbols, which are returned when resolution fails
|
||||
*/
|
||||
final ResolveError varNotFound;
|
||||
final ResolveError wrongMethod;
|
||||
final ResolveError wrongMethods;
|
||||
final ResolveError methodNotFound;
|
||||
final ResolveError typeNotFound;
|
||||
final SymbolNotFoundError varNotFound;
|
||||
final InapplicableSymbolError wrongMethod;
|
||||
final InapplicableSymbolsError wrongMethods;
|
||||
final SymbolNotFoundError methodNotFound;
|
||||
final SymbolNotFoundError typeNotFound;
|
||||
|
||||
/* ************************************************************************
|
||||
* Identifier resolution
|
||||
@ -710,13 +710,13 @@ public class Resolve {
|
||||
return new AmbiguityError(m1, m2);
|
||||
case AMBIGUOUS:
|
||||
AmbiguityError e = (AmbiguityError)m2;
|
||||
Symbol err1 = mostSpecific(m1, e.sym1, env, site, allowBoxing, useVarargs);
|
||||
Symbol err1 = mostSpecific(m1, e.sym, env, site, allowBoxing, useVarargs);
|
||||
Symbol err2 = mostSpecific(m1, e.sym2, env, site, allowBoxing, useVarargs);
|
||||
if (err1 == err2) return err1;
|
||||
if (err1 == e.sym1 && err2 == e.sym2) return m2;
|
||||
if (err1 == e.sym && err2 == e.sym2) return m2;
|
||||
if (err1 instanceof AmbiguityError &&
|
||||
err2 instanceof AmbiguityError &&
|
||||
((AmbiguityError)err1).sym1 == ((AmbiguityError)err2).sym1)
|
||||
((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
|
||||
return new AmbiguityError(m1, m2);
|
||||
else
|
||||
return new AmbiguityError(err1, err2);
|
||||
@ -1192,18 +1192,12 @@ public class Resolve {
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
if (sym.kind >= AMBIGUOUS) {
|
||||
// printscopes(site.tsym.members());//DEBUG
|
||||
ResolveError errSym = (ResolveError)sym;
|
||||
if (!site.isErroneous() &&
|
||||
!Type.isErroneous(argtypes) &&
|
||||
(typeargtypes==null || !Type.isErroneous(typeargtypes)))
|
||||
((ResolveError)sym).report(log, pos, site, name, argtypes, typeargtypes);
|
||||
do {
|
||||
sym = ((ResolveError)sym).sym;
|
||||
} while (sym.kind >= AMBIGUOUS);
|
||||
if (sym == syms.errSymbol // preserve the symbol name through errors
|
||||
|| ((sym.kind & ERRONEOUS) == 0 // make sure an error symbol is returned
|
||||
&& (sym.kind & TYP) != 0))
|
||||
sym = types.createErrorType(name, qualified ? site.tsym : syms.noSymbol, sym.type).tsym;
|
||||
logResolveError(errSym, pos, site, name, argtypes, typeargtypes);
|
||||
sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
@ -1583,7 +1577,19 @@ public class Resolve {
|
||||
|
||||
public void logAccessError(Env<AttrContext> env, JCTree tree, Type type) {
|
||||
AccessError error = new AccessError(env, type.getEnclosingType(), type.tsym);
|
||||
error.report(log, tree.pos(), type.getEnclosingType(), null, null, null);
|
||||
logResolveError(error, tree.pos(), type.getEnclosingType(), null, null, null);
|
||||
}
|
||||
//where
|
||||
private void logResolveError(ResolveError error,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
|
||||
pos, site, name, argtypes, typeargtypes);
|
||||
if (d != null)
|
||||
log.report(d);
|
||||
}
|
||||
|
||||
private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
|
||||
@ -1592,152 +1598,71 @@ public class Resolve {
|
||||
return argtypes.isEmpty() ? noArgs : argtypes;
|
||||
}
|
||||
|
||||
/** Root class for resolve errors.
|
||||
* Instances of this class indicate "Symbol not found".
|
||||
* Instances of subclass indicate other errors.
|
||||
/**
|
||||
* Root class for resolution errors. Subclass of ResolveError
|
||||
* represent a different kinds of resolution error - as such they must
|
||||
* specify how they map into concrete compiler diagnostics.
|
||||
*/
|
||||
private class ResolveError extends Symbol {
|
||||
private abstract class ResolveError extends Symbol {
|
||||
|
||||
ResolveError(int kind, Symbol sym, String debugName) {
|
||||
super(kind, 0, null, null, null);
|
||||
this.debugName = debugName;
|
||||
this.sym = sym;
|
||||
}
|
||||
|
||||
/** The name of the kind of error, for debugging only.
|
||||
*/
|
||||
/** The name of the kind of error, for debugging only. */
|
||||
final String debugName;
|
||||
|
||||
/** The symbol that was determined by resolution, or errSymbol if none
|
||||
* was found.
|
||||
*/
|
||||
final Symbol sym;
|
||||
|
||||
/** The symbol that was a close mismatch, or null if none was found.
|
||||
* wrongSym is currently set if a simgle method with the correct name, but
|
||||
* the wrong parameters was found.
|
||||
*/
|
||||
Symbol wrongSym;
|
||||
|
||||
/** An auxiliary explanation set in case of instantiation errors.
|
||||
*/
|
||||
JCDiagnostic explanation;
|
||||
|
||||
ResolveError(int kind, String debugName) {
|
||||
super(kind, 0, null, null, null);
|
||||
this.debugName = debugName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/** Print the (debug only) name of the kind of error.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return debugName + " wrongSym=" + wrongSym + " explanation=" + explanation;
|
||||
}
|
||||
|
||||
/** Update wrongSym and explanation and return this.
|
||||
*/
|
||||
ResolveError setWrongSym(Symbol sym, JCDiagnostic explanation) {
|
||||
this.wrongSym = sym;
|
||||
this.explanation = explanation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Update wrongSym and return this.
|
||||
*/
|
||||
ResolveError setWrongSym(Symbol sym) {
|
||||
this.wrongSym = sym;
|
||||
this.explanation = null;
|
||||
return this;
|
||||
return debugName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
switch (kind) {
|
||||
case HIDDEN:
|
||||
case ABSENT_VAR:
|
||||
case ABSENT_MTH:
|
||||
case ABSENT_TYP:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Report error.
|
||||
* @param log The error log to be used for error reporting.
|
||||
* @param pos The position to be used for error reporting.
|
||||
* @param site The original type from where the selection took place.
|
||||
* @param name The name of the symbol to be resolved.
|
||||
* @param argtypes The invocation's value arguments,
|
||||
* if we looked for a method.
|
||||
* @param typeargtypes The invocation's type arguments,
|
||||
* if we looked for a method.
|
||||
/**
|
||||
* Create an external representation for this erroneous symbol to be
|
||||
* used during attribution - by default this returns the symbol of a
|
||||
* brand new error type which stores the original type found
|
||||
* during resolution.
|
||||
*
|
||||
* @param name the name used during resolution
|
||||
* @param location the location from which the symbol is accessed
|
||||
*/
|
||||
void report(Log log, DiagnosticPosition pos, Type site, Name name,
|
||||
List<Type> argtypes, List<Type> typeargtypes) {
|
||||
if (argtypes == null)
|
||||
argtypes = List.nil();
|
||||
if (typeargtypes == null)
|
||||
typeargtypes = List.nil();
|
||||
if (name != names.error) {
|
||||
KindName kindname = absentKind(kind);
|
||||
Name idname = name;
|
||||
if (kind >= WRONG_MTHS && kind <= ABSENT_MTH) {
|
||||
if (isOperator(name)) {
|
||||
log.error(pos, "operator.cant.be.applied",
|
||||
name, argtypes);
|
||||
return;
|
||||
}
|
||||
if (name == names.init) {
|
||||
kindname = KindName.CONSTRUCTOR;
|
||||
idname = site.tsym.name;
|
||||
}
|
||||
}
|
||||
if (kind == WRONG_MTH) {
|
||||
Symbol ws = wrongSym.asMemberOf(site, types);
|
||||
log.error(pos,
|
||||
"cant.apply.symbol" + (explanation != null ? ".1" : ""),
|
||||
kindname,
|
||||
ws.name == names.init ? ws.owner.name : ws.name,
|
||||
methodArguments(ws.type.getParameterTypes()),
|
||||
methodArguments(argtypes),
|
||||
kindName(ws.owner),
|
||||
ws.owner.type,
|
||||
explanation);
|
||||
} else if (!site.tsym.name.isEmpty()) {
|
||||
if (site.tsym.kind == PCK && !site.tsym.exists())
|
||||
log.error(pos, "doesnt.exist", site.tsym);
|
||||
else {
|
||||
String errKey = getErrorKey("cant.resolve.location",
|
||||
argtypes, typeargtypes,
|
||||
kindname);
|
||||
log.error(pos, errKey, kindname, idname, //symbol kindname, name
|
||||
typeargtypes, argtypes, //type parameters and arguments (if any)
|
||||
typeKindName(site), site); //location kindname, type
|
||||
}
|
||||
} else {
|
||||
String errKey = getErrorKey("cant.resolve",
|
||||
argtypes, typeargtypes,
|
||||
kindname);
|
||||
log.error(pos, errKey, kindname, idname, //symbol kindname, name
|
||||
typeargtypes, argtypes); //type parameters and arguments (if any)
|
||||
}
|
||||
}
|
||||
}
|
||||
//where
|
||||
String getErrorKey(String key, List<Type> argtypes, List<Type> typeargtypes, KindName kindname) {
|
||||
String suffix = "";
|
||||
switch (kindname) {
|
||||
case METHOD:
|
||||
case CONSTRUCTOR: {
|
||||
suffix += ".args";
|
||||
suffix += typeargtypes.nonEmpty() ? ".params" : "";
|
||||
}
|
||||
}
|
||||
return key + suffix;
|
||||
protected Symbol access(Name name, TypeSymbol location) {
|
||||
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
|
||||
}
|
||||
|
||||
/** A name designates an operator if it consists
|
||||
* of a non-empty sequence of operator symbols +-~!/*%&|^<>=
|
||||
/**
|
||||
* Create a diagnostic representing this resolution error.
|
||||
*
|
||||
* @param dkind The kind of the diagnostic to be created (e.g error).
|
||||
* @param pos The position to be used for error reporting.
|
||||
* @param site The original type from where the selection took place.
|
||||
* @param name The name of the symbol to be resolved.
|
||||
* @param argtypes The invocation's value arguments,
|
||||
* if we looked for a method.
|
||||
* @param typeargtypes The invocation's type arguments,
|
||||
* if we looked for a method.
|
||||
*/
|
||||
abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes);
|
||||
|
||||
/**
|
||||
* A name designates an operator if it consists
|
||||
* of a non-empty sequence of operator symbols +-~!/*%&|^<>=
|
||||
*/
|
||||
boolean isOperator(Name name) {
|
||||
int i = 0;
|
||||
@ -1747,9 +1672,206 @@ public class Resolve {
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve error class indicating that a symbol is not accessible.
|
||||
/**
|
||||
* This class is the root class of all resolution errors caused by
|
||||
* an invalid symbol being found during resolution.
|
||||
*/
|
||||
class AccessError extends ResolveError {
|
||||
abstract class InvalidSymbolError extends ResolveError {
|
||||
|
||||
/** The invalid symbol found during resolution */
|
||||
Symbol sym;
|
||||
|
||||
InvalidSymbolError(int kind, Symbol sym, String debugName) {
|
||||
super(kind, debugName);
|
||||
this.sym = sym;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " wrongSym=" + sym;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol access(Name name, TypeSymbol location) {
|
||||
if (sym.kind >= AMBIGUOUS)
|
||||
return ((ResolveError)sym).access(name, location);
|
||||
else if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
|
||||
return types.createErrorType(name, location, sym.type).tsym;
|
||||
else
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* InvalidSymbolError error class indicating that a symbol matching a
|
||||
* given name does not exists in a given site.
|
||||
*/
|
||||
class SymbolNotFoundError extends ResolveError {
|
||||
|
||||
SymbolNotFoundError(int kind) {
|
||||
super(kind, "symbol not found error");
|
||||
}
|
||||
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
argtypes = argtypes == null ? List.<Type>nil() : argtypes;
|
||||
typeargtypes = typeargtypes == null ? List.<Type>nil() : typeargtypes;
|
||||
if (name == names.error)
|
||||
return null;
|
||||
|
||||
if (isOperator(name)) {
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
"operator.cant.be.applied", name, argtypes);
|
||||
}
|
||||
boolean hasLocation = false;
|
||||
if (!site.tsym.name.isEmpty()) {
|
||||
if (site.tsym.kind == PCK && !site.tsym.exists()) {
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
"doesnt.exist", site.tsym);
|
||||
}
|
||||
hasLocation = true;
|
||||
}
|
||||
boolean isConstructor = kind == ABSENT_MTH &&
|
||||
name == names.table.names.init;
|
||||
KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
|
||||
Name idname = isConstructor ? site.tsym.name : name;
|
||||
String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
|
||||
if (hasLocation) {
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
errKey, kindname, idname, //symbol kindname, name
|
||||
typeargtypes, argtypes, //type parameters and arguments (if any)
|
||||
typeKindName(site), site); //location kindname, type
|
||||
}
|
||||
else {
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
errKey, kindname, idname, //symbol kindname, name
|
||||
typeargtypes, argtypes); //type parameters and arguments (if any)
|
||||
}
|
||||
}
|
||||
//where
|
||||
private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) {
|
||||
String key = "cant.resolve";
|
||||
String suffix = hasLocation ? ".location" : "";
|
||||
switch (kindname) {
|
||||
case METHOD:
|
||||
case CONSTRUCTOR: {
|
||||
suffix += ".args";
|
||||
suffix += hasTypeArgs ? ".params" : "";
|
||||
}
|
||||
}
|
||||
return key + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* InvalidSymbolError error class indicating that a given symbol
|
||||
* (either a method, a constructor or an operand) is not applicable
|
||||
* given an actual arguments/type argument list.
|
||||
*/
|
||||
class InapplicableSymbolError extends InvalidSymbolError {
|
||||
|
||||
/** An auxiliary explanation set in case of instantiation errors. */
|
||||
JCDiagnostic explanation;
|
||||
|
||||
InapplicableSymbolError(Symbol sym) {
|
||||
super(WRONG_MTH, sym, "inapplicable symbol error");
|
||||
}
|
||||
|
||||
/** Update sym and explanation and return this.
|
||||
*/
|
||||
InapplicableSymbolError setWrongSym(Symbol sym, JCDiagnostic explanation) {
|
||||
this.sym = sym;
|
||||
this.explanation = explanation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Update sym and return this.
|
||||
*/
|
||||
InapplicableSymbolError setWrongSym(Symbol sym) {
|
||||
this.sym = sym;
|
||||
this.explanation = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " explanation=" + explanation;
|
||||
}
|
||||
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
if (name == names.error)
|
||||
return null;
|
||||
|
||||
if (isOperator(name)) {
|
||||
return diags.create(dkind, false, log.currentSource(),
|
||||
pos, "operator.cant.be.applied", name, argtypes);
|
||||
}
|
||||
else {
|
||||
Symbol ws = sym.asMemberOf(site, types);
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
"cant.apply.symbol" + (explanation != null ? ".1" : ""),
|
||||
kindName(ws),
|
||||
ws.name == names.init ? ws.owner.name : ws.name,
|
||||
methodArguments(ws.type.getParameterTypes()),
|
||||
methodArguments(argtypes),
|
||||
kindName(ws.owner),
|
||||
ws.owner.type,
|
||||
explanation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol access(Name name, TypeSymbol location) {
|
||||
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ResolveError error class indicating that a set of symbols
|
||||
* (either methods, constructors or operands) is not applicable
|
||||
* given an actual arguments/type argument list.
|
||||
*/
|
||||
class InapplicableSymbolsError extends ResolveError {
|
||||
InapplicableSymbolsError(Symbol sym) {
|
||||
super(WRONG_MTHS, "inapplicable symbols");
|
||||
}
|
||||
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
|
||||
site, name, argtypes, typeargtypes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An InvalidSymbolError error class indicating that a symbol is not
|
||||
* accessible from a given site
|
||||
*/
|
||||
class AccessError extends InvalidSymbolError {
|
||||
|
||||
private Env<AttrContext> env;
|
||||
private Type site;
|
||||
|
||||
AccessError(Symbol sym) {
|
||||
this(null, null, sym);
|
||||
@ -1763,111 +1885,107 @@ public class Resolve {
|
||||
log.error("proc.messager", sym + " @ " + site + " is inaccessible.");
|
||||
}
|
||||
|
||||
private Env<AttrContext> env;
|
||||
private Type site;
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Report error.
|
||||
* @param log The error log to be used for error reporting.
|
||||
* @param pos The position to be used for error reporting.
|
||||
* @param site The original type from where the selection took place.
|
||||
* @param name The name of the symbol to be resolved.
|
||||
* @param argtypes The invocation's value arguments,
|
||||
* if we looked for a method.
|
||||
* @param typeargtypes The invocation's type arguments,
|
||||
* if we looked for a method.
|
||||
*/
|
||||
void report(Log log, DiagnosticPosition pos, Type site, Name name,
|
||||
List<Type> argtypes, List<Type> typeargtypes) {
|
||||
if (sym.owner.type.tag != ERROR) {
|
||||
if (sym.name == names.init && sym.owner != site.tsym)
|
||||
new ResolveError(ABSENT_MTH, sym.owner, "absent method " + sym).report(
|
||||
log, pos, site, name, argtypes, typeargtypes);
|
||||
if ((sym.flags() & PUBLIC) != 0
|
||||
|| (env != null && this.site != null
|
||||
&& !isAccessible(env, this.site)))
|
||||
log.error(pos, "not.def.access.class.intf.cant.access",
|
||||
sym, sym.location());
|
||||
else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0)
|
||||
log.error(pos, "report.access", sym,
|
||||
asFlagSet(sym.flags() & (PRIVATE | PROTECTED)),
|
||||
sym.location());
|
||||
else
|
||||
log.error(pos, "not.def.public.cant.access",
|
||||
sym, sym.location());
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
if (sym.owner.type.tag == ERROR)
|
||||
return null;
|
||||
|
||||
if (sym.name == names.init && sym.owner != site.tsym) {
|
||||
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind,
|
||||
pos, site, name, argtypes, typeargtypes);
|
||||
}
|
||||
else if ((sym.flags() & PUBLIC) != 0
|
||||
|| (env != null && this.site != null
|
||||
&& !isAccessible(env, this.site))) {
|
||||
return diags.create(dkind, false, log.currentSource(),
|
||||
pos, "not.def.access.class.intf.cant.access",
|
||||
sym, sym.location());
|
||||
}
|
||||
else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) {
|
||||
return diags.create(dkind, false, log.currentSource(),
|
||||
pos, "report.access", sym,
|
||||
asFlagSet(sym.flags() & (PRIVATE | PROTECTED)),
|
||||
sym.location());
|
||||
}
|
||||
else {
|
||||
return diags.create(dkind, false, log.currentSource(),
|
||||
pos, "not.def.public.cant.access", sym, sym.location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve error class indicating that an instance member was accessed
|
||||
* from a static context.
|
||||
/**
|
||||
* InvalidSymbolError error class indicating that an instance member
|
||||
* has erroneously been accessed from a static context.
|
||||
*/
|
||||
class StaticError extends ResolveError {
|
||||
class StaticError extends InvalidSymbolError {
|
||||
|
||||
StaticError(Symbol sym) {
|
||||
super(STATICERR, sym, "static error");
|
||||
}
|
||||
|
||||
/** Report error.
|
||||
* @param log The error log to be used for error reporting.
|
||||
* @param pos The position to be used for error reporting.
|
||||
* @param site The original type from where the selection took place.
|
||||
* @param name The name of the symbol to be resolved.
|
||||
* @param argtypes The invocation's value arguments,
|
||||
* if we looked for a method.
|
||||
* @param typeargtypes The invocation's type arguments,
|
||||
* if we looked for a method.
|
||||
*/
|
||||
void report(Log log,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
Symbol errSym = ((sym.kind == TYP && sym.type.tag == CLASS)
|
||||
? types.erasure(sym.type).tsym
|
||||
: sym);
|
||||
log.error(pos, "non-static.cant.be.ref",
|
||||
kindName(sym), errSym);
|
||||
return diags.create(dkind, false, log.currentSource(), pos,
|
||||
"non-static.cant.be.ref", kindName(sym), errSym);
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve error class indicating an ambiguous reference.
|
||||
/**
|
||||
* InvalidSymbolError error class indicating that a pair of symbols
|
||||
* (either methods, constructors or operands) are ambiguous
|
||||
* given an actual arguments/type argument list.
|
||||
*/
|
||||
class AmbiguityError extends ResolveError {
|
||||
Symbol sym1;
|
||||
class AmbiguityError extends InvalidSymbolError {
|
||||
|
||||
/** The other maximally specific symbol */
|
||||
Symbol sym2;
|
||||
|
||||
AmbiguityError(Symbol sym1, Symbol sym2) {
|
||||
super(AMBIGUOUS, sym1, "ambiguity error");
|
||||
this.sym1 = sym1;
|
||||
this.sym2 = sym2;
|
||||
}
|
||||
|
||||
/** Report error.
|
||||
* @param log The error log to be used for error reporting.
|
||||
* @param pos The position to be used for error reporting.
|
||||
* @param site The original type from where the selection took place.
|
||||
* @param name The name of the symbol to be resolved.
|
||||
* @param argtypes The invocation's value arguments,
|
||||
* if we looked for a method.
|
||||
* @param typeargtypes The invocation's type arguments,
|
||||
* if we looked for a method.
|
||||
*/
|
||||
void report(Log log, DiagnosticPosition pos, Type site, Name name,
|
||||
List<Type> argtypes, List<Type> typeargtypes) {
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
|
||||
DiagnosticPosition pos,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
AmbiguityError pair = this;
|
||||
while (true) {
|
||||
if (pair.sym1.kind == AMBIGUOUS)
|
||||
pair = (AmbiguityError)pair.sym1;
|
||||
if (pair.sym.kind == AMBIGUOUS)
|
||||
pair = (AmbiguityError)pair.sym;
|
||||
else if (pair.sym2.kind == AMBIGUOUS)
|
||||
pair = (AmbiguityError)pair.sym2;
|
||||
else break;
|
||||
}
|
||||
Name sname = pair.sym1.name;
|
||||
if (sname == names.init) sname = pair.sym1.owner.name;
|
||||
log.error(pos, "ref.ambiguous", sname,
|
||||
kindName(pair.sym1),
|
||||
pair.sym1,
|
||||
pair.sym1.location(site, types),
|
||||
Name sname = pair.sym.name;
|
||||
if (sname == names.init) sname = pair.sym.owner.name;
|
||||
return diags.create(dkind, false, log.currentSource(),
|
||||
pos, "ref.ambiguous", sname,
|
||||
kindName(pair.sym),
|
||||
pair.sym,
|
||||
pair.sym.location(site, types),
|
||||
kindName(pair.sym2),
|
||||
pair.sym2,
|
||||
pair.sym2.location(site, types));
|
||||
|
@ -109,7 +109,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
return formatDiagnostic(d, locale);
|
||||
}
|
||||
|
||||
abstract String formatDiagnostic(JCDiagnostic d, Locale locale);
|
||||
protected abstract String formatDiagnostic(JCDiagnostic d, Locale locale);
|
||||
|
||||
public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) {
|
||||
assert (d.getPosition() != Position.NOPOS);
|
||||
|
@ -58,7 +58,7 @@ public abstract class AbstractLog {
|
||||
|
||||
protected DiagnosticSource getSource(JavaFileObject file) {
|
||||
if (file == null)
|
||||
return null;
|
||||
return DiagnosticSource.NO_SOURCE;
|
||||
DiagnosticSource s = sourceMap.get(file);
|
||||
if (s == null) {
|
||||
s = new DiagnosticSource(file, this);
|
||||
|
@ -46,11 +46,22 @@ import static com.sun.tools.javac.util.LayoutCharacters.*;
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class DiagnosticSource {
|
||||
|
||||
/* constant DiagnosticSource to be used when sourcefile is missing */
|
||||
public static final DiagnosticSource NO_SOURCE = new DiagnosticSource() {
|
||||
@Override
|
||||
protected boolean findLine(int pos) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public DiagnosticSource(JavaFileObject fo, AbstractLog log) {
|
||||
this.fileObject = fo;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
private DiagnosticSource() {}
|
||||
|
||||
/** Return the underlying file object handled by this
|
||||
* DiagnosticSource object.
|
||||
*/
|
||||
@ -134,7 +145,7 @@ public class DiagnosticSource {
|
||||
/** Find the line in the buffer that contains the current position
|
||||
* @param pos Character offset into the buffer
|
||||
*/
|
||||
private boolean findLine(int pos) {
|
||||
protected boolean findLine(int pos) {
|
||||
if (pos == Position.NOPOS)
|
||||
return false;
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic error(
|
||||
DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, ERROR, true, source, pos, qualify(ERROR, key), args);
|
||||
return create(ERROR, true, source, pos, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +96,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic mandatoryWarning(
|
||||
DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, WARNING, true, source, pos, qualify(WARNING, key), args);
|
||||
return create(WARNING, true, source, pos, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +108,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic warning(
|
||||
DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, WARNING, false, source, pos, qualify(WARNING, key), args);
|
||||
return create(WARNING, false, source, pos, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +118,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* @see MandatoryWarningHandler
|
||||
*/
|
||||
public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, NOTE, true, source, null, qualify(NOTE, key), args);
|
||||
return create(NOTE, true, source, null, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,7 +127,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* @param args Fields of the error message.
|
||||
*/
|
||||
public JCDiagnostic note(String key, Object... args) {
|
||||
return note(null, null, key, args);
|
||||
return create(NOTE, false, null, null, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,7 +139,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic note(
|
||||
DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, NOTE, false, source, pos, qualify(NOTE, key), args);
|
||||
return create(NOTE, false, source, pos, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +148,21 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* @param args Fields of the error message.
|
||||
*/
|
||||
public JCDiagnostic fragment(String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, FRAGMENT, false, null, null, qualify(FRAGMENT, key), args);
|
||||
return create(FRAGMENT, false, null, null, key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new diagnostic of the given kind.
|
||||
* @param kind The diagnostic kind
|
||||
* @param isMandatory is diagnostic mandatory?
|
||||
* @param source The source of the compilation unit, if any, in which to report the note.
|
||||
* @param pos The source position at which to report the note.
|
||||
* @param key The key for the localized error message.
|
||||
* @param args Fields of the error message.
|
||||
*/
|
||||
public JCDiagnostic create(
|
||||
DiagnosticType kind, boolean isMandatory, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return new JCDiagnostic(formatter, kind, isMandatory, source, pos, qualify(kind, key), args);
|
||||
}
|
||||
|
||||
protected String qualify(DiagnosticType t, String key) {
|
||||
|
@ -68,7 +68,10 @@ public class RichDiagnosticFormatter extends
|
||||
final JavacMessages messages;
|
||||
|
||||
/* name simplifier used by this formatter */
|
||||
ClassNameSimplifier nameSimplifier;
|
||||
protected ClassNameSimplifier nameSimplifier;
|
||||
|
||||
/* type/symbol printer used by this formatter */
|
||||
private RichPrinter printer;
|
||||
|
||||
/* map for keeping track of a where clause associated to a given type */
|
||||
Map<WhereClauseKind, Map<Type, JCDiagnostic>> whereClauses;
|
||||
@ -83,7 +86,7 @@ public class RichDiagnosticFormatter extends
|
||||
|
||||
protected RichDiagnosticFormatter(Context context) {
|
||||
super((AbstractDiagnosticFormatter)Log.instance(context).getDiagnosticFormatter());
|
||||
this.formatter.setPrinter(printer);
|
||||
setRichPrinter(new RichPrinter());
|
||||
this.syms = Symtab.instance(context);
|
||||
this.diags = JCDiagnostic.Factory.instance(context);
|
||||
this.types = Types.instance(context);
|
||||
@ -116,6 +119,23 @@ public class RichDiagnosticFormatter extends
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type/symbol printer used by this formatter.
|
||||
* @param printer the rich printer to be set
|
||||
*/
|
||||
protected void setRichPrinter(RichPrinter printer) {
|
||||
this.printer = printer;
|
||||
formatter.setPrinter(printer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type/symbol printer used by this formatter.
|
||||
* @return type/symbol rich printer
|
||||
*/
|
||||
protected RichPrinter getRichPrinter() {
|
||||
return printer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess a given diagnostic by looking both into its arguments and into
|
||||
* its subdiagnostics (if any). This preprocessing is responsible for
|
||||
@ -217,7 +237,7 @@ public class RichDiagnosticFormatter extends
|
||||
* name belong to different packages - in this case the formatter reverts
|
||||
* to fullnames as compact names might lead to a confusing diagnostic.
|
||||
*/
|
||||
class ClassNameSimplifier {
|
||||
protected class ClassNameSimplifier {
|
||||
|
||||
/* table for keeping track of all short name usages */
|
||||
Map<Name, List<Symbol>> nameClashes = new HashMap<Name, List<Symbol>>();
|
||||
@ -272,7 +292,7 @@ public class RichDiagnosticFormatter extends
|
||||
* discovered during type/symbol preprocessing. This printer is set on the delegate
|
||||
* formatter so that rich type/symbol info can be properly rendered.
|
||||
*/
|
||||
protected Printer printer = new Printer() {
|
||||
protected class RichPrinter extends Printer {
|
||||
|
||||
@Override
|
||||
public String localize(Locale locale, String key, Object... args) {
|
||||
|
66
langtools/test/tools/javac/api/6852595/T6852595.java
Normal file
66
langtools/test/tools/javac/api/6852595/T6852595.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2009 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6852595
|
||||
* @summary Accessing scope using JSR199 API on erroneous tree causes Illegal Argument Exception
|
||||
* @author mcimadamore
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.tree.*;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.Trees;
|
||||
import com.sun.tools.javac.api.JavacTrees;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
import static javax.tools.JavaFileObject.Kind;
|
||||
|
||||
public class T6852595 {
|
||||
public static void main(String[] args) throws IOException {
|
||||
JavaFileObject sfo = new SimpleJavaFileObject(URI.create("myfo:/Test.java"),Kind.SOURCE) {
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return "class BadName { Object o = j; }";
|
||||
}
|
||||
};
|
||||
List<? extends JavaFileObject> files = Arrays.asList(sfo);
|
||||
JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||
JavacTask ct = (JavacTask)tool.getTask(null, null, null, null, null, files);
|
||||
Iterable<? extends CompilationUnitTree> compUnits = ct.parse();
|
||||
CompilationUnitTree cu = compUnits.iterator().next();
|
||||
ClassTree cdef = (ClassTree)cu.getTypeDecls().get(0);
|
||||
JCVariableDecl vdef = (JCVariableDecl)cdef.getMembers().get(0);
|
||||
TreePath path = TreePath.getPath(cu, vdef.init);
|
||||
Trees.instance(ct).getScope(path);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user