8054448: (ann) Cannot reference field of inner class in an anonymous class
Reviewed-by: jlahoda, mcimadamore
This commit is contained in:
parent
535317c6f8
commit
0149333fb8
@ -989,8 +989,12 @@ public class Attr extends JCTree.Visitor {
|
|||||||
// parameters have already been entered
|
// parameters have already been entered
|
||||||
env.info.scope.enter(tree.sym);
|
env.info.scope.enter(tree.sym);
|
||||||
} else {
|
} else {
|
||||||
memberEnter.memberEnter(tree, env);
|
try {
|
||||||
annotate.flush();
|
annotate.enterStart();
|
||||||
|
memberEnter.memberEnter(tree, env);
|
||||||
|
} finally {
|
||||||
|
annotate.enterDone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tree.init != null) {
|
if (tree.init != null) {
|
||||||
|
@ -518,52 +518,46 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Env<AttrContext> localEnv = methodEnv(tree, env);
|
Env<AttrContext> localEnv = methodEnv(tree, env);
|
||||||
|
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||||
annotate.enterStart();
|
|
||||||
try {
|
try {
|
||||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
// Compute the method type
|
||||||
try {
|
m.type = signature(m, tree.typarams, tree.params,
|
||||||
// Compute the method type
|
tree.restype, tree.recvparam,
|
||||||
m.type = signature(m, tree.typarams, tree.params,
|
tree.thrown,
|
||||||
tree.restype, tree.recvparam,
|
localEnv);
|
||||||
tree.thrown,
|
|
||||||
localEnv);
|
|
||||||
} finally {
|
|
||||||
deferredLintHandler.setPos(prevLintPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (types.isSignaturePolymorphic(m)) {
|
|
||||||
m.flags_field |= SIGNATURE_POLYMORPHIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set m.params
|
|
||||||
ListBuffer<VarSymbol> params = new ListBuffer<>();
|
|
||||||
JCVariableDecl lastParam = null;
|
|
||||||
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
|
|
||||||
JCVariableDecl param = lastParam = l.head;
|
|
||||||
params.append(Assert.checkNonNull(param.sym));
|
|
||||||
}
|
|
||||||
m.params = params.toList();
|
|
||||||
|
|
||||||
// mark the method varargs, if necessary
|
|
||||||
if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0)
|
|
||||||
m.flags_field |= Flags.VARARGS;
|
|
||||||
|
|
||||||
localEnv.info.scope.leave();
|
|
||||||
if (chk.checkUnique(tree.pos(), m, enclScope)) {
|
|
||||||
enclScope.enter(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos());
|
|
||||||
// Visit the signature of the method. Note that
|
|
||||||
// TypeAnnotate doesn't descend into the body.
|
|
||||||
annotate.annotateTypeLater(tree, localEnv, m, tree.pos());
|
|
||||||
|
|
||||||
if (tree.defaultValue != null)
|
|
||||||
annotateDefaultValueLater(tree.defaultValue, localEnv, m);
|
|
||||||
} finally {
|
} finally {
|
||||||
annotate.enterDone();
|
deferredLintHandler.setPos(prevLintPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (types.isSignaturePolymorphic(m)) {
|
||||||
|
m.flags_field |= SIGNATURE_POLYMORPHIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set m.params
|
||||||
|
ListBuffer<VarSymbol> params = new ListBuffer<>();
|
||||||
|
JCVariableDecl lastParam = null;
|
||||||
|
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
|
||||||
|
JCVariableDecl param = lastParam = l.head;
|
||||||
|
params.append(Assert.checkNonNull(param.sym));
|
||||||
|
}
|
||||||
|
m.params = params.toList();
|
||||||
|
|
||||||
|
// mark the method varargs, if necessary
|
||||||
|
if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0)
|
||||||
|
m.flags_field |= Flags.VARARGS;
|
||||||
|
|
||||||
|
localEnv.info.scope.leave();
|
||||||
|
if (chk.checkUnique(tree.pos(), m, enclScope)) {
|
||||||
|
enclScope.enter(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos());
|
||||||
|
// Visit the signature of the method. Note that
|
||||||
|
// TypeAnnotate doesn't descend into the body.
|
||||||
|
annotate.annotateTypeLater(tree, localEnv, m, tree.pos());
|
||||||
|
|
||||||
|
if (tree.defaultValue != null)
|
||||||
|
annotateDefaultValueLater(tree.defaultValue, localEnv, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a fresh environment for method bodies.
|
/** Create a fresh environment for method bodies.
|
||||||
@ -591,56 +585,51 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
|||||||
localEnv.info.staticLevel++;
|
localEnv.info.staticLevel++;
|
||||||
}
|
}
|
||||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||||
annotate.enterStart();
|
|
||||||
try {
|
try {
|
||||||
try {
|
if (TreeInfo.isEnumInit(tree)) {
|
||||||
if (TreeInfo.isEnumInit(tree)) {
|
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
||||||
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
} else {
|
||||||
} else {
|
attr.attribType(tree.vartype, localEnv);
|
||||||
attr.attribType(tree.vartype, localEnv);
|
if (TreeInfo.isReceiverParam(tree))
|
||||||
if (TreeInfo.isReceiverParam(tree))
|
checkReceiver(tree, localEnv);
|
||||||
checkReceiver(tree, localEnv);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
deferredLintHandler.setPos(prevLintPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tree.mods.flags & VARARGS) != 0) {
|
|
||||||
//if we are entering a varargs parameter, we need to
|
|
||||||
//replace its type (a plain array type) with the more
|
|
||||||
//precise VarargsType --- we need to do it this way
|
|
||||||
//because varargs is represented in the tree as a
|
|
||||||
//modifier on the parameter declaration, and not as a
|
|
||||||
//distinct type of array node.
|
|
||||||
ArrayType atype = (ArrayType)tree.vartype.type;
|
|
||||||
tree.vartype.type = atype.makeVarargs();
|
|
||||||
}
|
|
||||||
WriteableScope enclScope = enter.enterScope(env);
|
|
||||||
VarSymbol v =
|
|
||||||
new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner);
|
|
||||||
v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree);
|
|
||||||
tree.sym = v;
|
|
||||||
if (tree.init != null) {
|
|
||||||
v.flags_field |= HASINIT;
|
|
||||||
if ((v.flags_field & FINAL) != 0 &&
|
|
||||||
needsLazyConstValue(tree.init)) {
|
|
||||||
Env<AttrContext> initEnv = getInitEnv(tree, env);
|
|
||||||
initEnv.info.enclVar = v;
|
|
||||||
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chk.checkUnique(tree.pos(), v, enclScope)) {
|
|
||||||
chk.checkTransparentVar(tree.pos(), v, enclScope);
|
|
||||||
enclScope.enter(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
|
|
||||||
annotate.annotateTypeLater(tree.vartype, localEnv, v, tree.pos());
|
|
||||||
|
|
||||||
v.pos = tree.pos;
|
|
||||||
} finally {
|
} finally {
|
||||||
annotate.enterDone();
|
deferredLintHandler.setPos(prevLintPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((tree.mods.flags & VARARGS) != 0) {
|
||||||
|
//if we are entering a varargs parameter, we need to
|
||||||
|
//replace its type (a plain array type) with the more
|
||||||
|
//precise VarargsType --- we need to do it this way
|
||||||
|
//because varargs is represented in the tree as a
|
||||||
|
//modifier on the parameter declaration, and not as a
|
||||||
|
//distinct type of array node.
|
||||||
|
ArrayType atype = (ArrayType)tree.vartype.type;
|
||||||
|
tree.vartype.type = atype.makeVarargs();
|
||||||
|
}
|
||||||
|
WriteableScope enclScope = enter.enterScope(env);
|
||||||
|
VarSymbol v =
|
||||||
|
new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner);
|
||||||
|
v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree);
|
||||||
|
tree.sym = v;
|
||||||
|
if (tree.init != null) {
|
||||||
|
v.flags_field |= HASINIT;
|
||||||
|
if ((v.flags_field & FINAL) != 0 &&
|
||||||
|
needsLazyConstValue(tree.init)) {
|
||||||
|
Env<AttrContext> initEnv = getInitEnv(tree, env);
|
||||||
|
initEnv.info.enclVar = v;
|
||||||
|
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chk.checkUnique(tree.pos(), v, enclScope)) {
|
||||||
|
chk.checkTransparentVar(tree.pos(), v, enclScope);
|
||||||
|
enclScope.enter(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
|
||||||
|
annotate.annotateTypeLater(tree.vartype, localEnv, v, tree.pos());
|
||||||
|
|
||||||
|
v.pos = tree.pos;
|
||||||
}
|
}
|
||||||
// where
|
// where
|
||||||
void checkType(JCTree tree, Type type, String diag) {
|
void checkType(JCTree tree, Type type, String diag) {
|
||||||
@ -866,219 +855,225 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassSymbol c = (ClassSymbol)sym;
|
|
||||||
ClassType ct = (ClassType)c.type;
|
|
||||||
Env<AttrContext> env = typeEnvs.get(c);
|
|
||||||
JCClassDecl tree = (JCClassDecl)env.tree;
|
|
||||||
boolean wasFirst = isFirst;
|
|
||||||
isFirst = false;
|
|
||||||
|
|
||||||
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
|
||||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
|
||||||
try {
|
try {
|
||||||
dependencies.push(c);
|
annotate.enterStart();
|
||||||
|
|
||||||
// Save class environment for later member enter (2) processing.
|
ClassSymbol c = (ClassSymbol)sym;
|
||||||
halfcompleted.append(env);
|
ClassType ct = (ClassType)c.type;
|
||||||
|
Env<AttrContext> env = typeEnvs.get(c);
|
||||||
|
JCClassDecl tree = (JCClassDecl)env.tree;
|
||||||
|
boolean wasFirst = isFirst;
|
||||||
|
isFirst = false;
|
||||||
|
|
||||||
// Mark class as not yet attributed.
|
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
||||||
c.flags_field |= UNATTRIBUTED;
|
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||||
|
|
||||||
// If this is a toplevel-class, make sure any preceding import
|
|
||||||
// clauses have been seen.
|
|
||||||
if (c.owner.kind == PCK) {
|
|
||||||
memberEnter(env.toplevel, env.enclosing(TOPLEVEL));
|
|
||||||
todo.append(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.owner.kind == TYP)
|
|
||||||
c.owner.complete();
|
|
||||||
|
|
||||||
// create an environment for evaluating the base clauses
|
|
||||||
Env<AttrContext> baseEnv = baseEnv(tree, env);
|
|
||||||
|
|
||||||
if (tree.extending != null)
|
|
||||||
annotate.annotateTypeLater(tree.extending, baseEnv, sym, tree.pos());
|
|
||||||
for (JCExpression impl : tree.implementing)
|
|
||||||
annotate.annotateTypeLater(impl, baseEnv, sym, tree.pos());
|
|
||||||
annotate.flush();
|
|
||||||
|
|
||||||
// Determine supertype.
|
|
||||||
Type supertype;
|
|
||||||
if (tree.extending != null) {
|
|
||||||
dependencies.push(AttributionKind.EXTENDS, tree.extending);
|
|
||||||
try {
|
|
||||||
supertype = attr.attribBase(tree.extending, baseEnv,
|
|
||||||
true, false, true);
|
|
||||||
} finally {
|
|
||||||
dependencies.pop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
supertype = ((tree.mods.flags & Flags.ENUM) != 0)
|
|
||||||
? attr.attribBase(enumBase(tree.pos, c), baseEnv,
|
|
||||||
true, false, false)
|
|
||||||
: (c.fullname == names.java_lang_Object)
|
|
||||||
? Type.noType
|
|
||||||
: syms.objectType;
|
|
||||||
}
|
|
||||||
ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
|
|
||||||
|
|
||||||
// Determine interfaces.
|
|
||||||
ListBuffer<Type> interfaces = new ListBuffer<>();
|
|
||||||
ListBuffer<Type> all_interfaces = null; // lazy init
|
|
||||||
Set<Type> interfaceSet = new HashSet<>();
|
|
||||||
List<JCExpression> interfaceTrees = tree.implementing;
|
|
||||||
for (JCExpression iface : interfaceTrees) {
|
|
||||||
dependencies.push(AttributionKind.IMPLEMENTS, iface);
|
|
||||||
try {
|
|
||||||
Type it = attr.attribBase(iface, baseEnv, false, true, true);
|
|
||||||
if (it.hasTag(CLASS)) {
|
|
||||||
interfaces.append(it);
|
|
||||||
if (all_interfaces != null) all_interfaces.append(it);
|
|
||||||
chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
|
|
||||||
} else {
|
|
||||||
if (all_interfaces == null)
|
|
||||||
all_interfaces = new ListBuffer<Type>().appendList(interfaces);
|
|
||||||
all_interfaces.append(modelMissingTypes(it, iface, true));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
dependencies.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((c.flags_field & ANNOTATION) != 0) {
|
|
||||||
ct.interfaces_field = List.of(syms.annotationType);
|
|
||||||
ct.all_interfaces_field = ct.interfaces_field;
|
|
||||||
} else {
|
|
||||||
ct.interfaces_field = interfaces.toList();
|
|
||||||
ct.all_interfaces_field = (all_interfaces == null)
|
|
||||||
? ct.interfaces_field : all_interfaces.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.fullname == names.java_lang_Object) {
|
|
||||||
if (tree.extending != null) {
|
|
||||||
chk.checkNonCyclic(tree.extending.pos(),
|
|
||||||
supertype);
|
|
||||||
ct.supertype_field = Type.noType;
|
|
||||||
}
|
|
||||||
else if (tree.implementing.nonEmpty()) {
|
|
||||||
chk.checkNonCyclic(tree.implementing.head.pos(),
|
|
||||||
ct.interfaces_field.head);
|
|
||||||
ct.interfaces_field = List.nil();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Annotations.
|
|
||||||
// In general, we cannot fully process annotations yet, but we
|
|
||||||
// can attribute the annotation types and then check to see if the
|
|
||||||
// @Deprecated annotation is present.
|
|
||||||
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
|
|
||||||
if (hasDeprecatedAnnotation(tree.mods.annotations))
|
|
||||||
c.flags_field |= DEPRECATED;
|
|
||||||
annotate.annotateLater(tree.mods.annotations, baseEnv,
|
|
||||||
c, tree.pos());
|
|
||||||
|
|
||||||
chk.checkNonCyclicDecl(tree);
|
|
||||||
|
|
||||||
// class type parameters use baseEnv but everything uses env
|
|
||||||
attr.attribTypeVariables(tree.typarams, baseEnv);
|
|
||||||
for (JCTypeParameter tp : tree.typarams)
|
|
||||||
annotate.annotateTypeLater(tp, baseEnv, sym, tree.pos());
|
|
||||||
|
|
||||||
// Add default constructor if needed.
|
|
||||||
if ((c.flags() & INTERFACE) == 0 &&
|
|
||||||
!TreeInfo.hasConstructors(tree.defs)) {
|
|
||||||
List<Type> argtypes = List.nil();
|
|
||||||
List<Type> typarams = List.nil();
|
|
||||||
List<Type> thrown = List.nil();
|
|
||||||
long ctorFlags = 0;
|
|
||||||
boolean based = false;
|
|
||||||
boolean addConstructor = true;
|
|
||||||
JCNewClass nc = null;
|
|
||||||
if (c.name.isEmpty()) {
|
|
||||||
nc = (JCNewClass)env.next.tree;
|
|
||||||
if (nc.constructor != null) {
|
|
||||||
addConstructor = nc.constructor.kind != ERR;
|
|
||||||
Type superConstrType = types.memberType(c.type,
|
|
||||||
nc.constructor);
|
|
||||||
argtypes = superConstrType.getParameterTypes();
|
|
||||||
typarams = superConstrType.getTypeArguments();
|
|
||||||
ctorFlags = nc.constructor.flags() & VARARGS;
|
|
||||||
if (nc.encl != null) {
|
|
||||||
argtypes = argtypes.prepend(nc.encl.type);
|
|
||||||
based = true;
|
|
||||||
}
|
|
||||||
thrown = superConstrType.getThrownTypes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (addConstructor) {
|
|
||||||
MethodSymbol basedConstructor = nc != null ?
|
|
||||||
(MethodSymbol)nc.constructor : null;
|
|
||||||
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
|
|
||||||
basedConstructor,
|
|
||||||
typarams, argtypes, thrown,
|
|
||||||
ctorFlags, based);
|
|
||||||
tree.defs = tree.defs.prepend(constrDef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// enter symbols for 'this' into current scope.
|
|
||||||
VarSymbol thisSym =
|
|
||||||
new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
|
|
||||||
thisSym.pos = Position.FIRSTPOS;
|
|
||||||
env.info.scope.enter(thisSym);
|
|
||||||
// if this is a class, enter symbol for 'super' into current scope.
|
|
||||||
if ((c.flags_field & INTERFACE) == 0 &&
|
|
||||||
ct.supertype_field.hasTag(CLASS)) {
|
|
||||||
VarSymbol superSym =
|
|
||||||
new VarSymbol(FINAL | HASINIT, names._super,
|
|
||||||
ct.supertype_field, c);
|
|
||||||
superSym.pos = Position.FIRSTPOS;
|
|
||||||
env.info.scope.enter(superSym);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that no package exists with same fully qualified name,
|
|
||||||
// but admit classes in the unnamed package which have the same
|
|
||||||
// name as a top-level package.
|
|
||||||
if (checkClash &&
|
|
||||||
c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
|
|
||||||
syms.packageExists(c.fullname)) {
|
|
||||||
log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
|
|
||||||
}
|
|
||||||
if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 &&
|
|
||||||
!env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) {
|
|
||||||
c.flags_field |= AUXILIARY;
|
|
||||||
}
|
|
||||||
} catch (CompletionFailure ex) {
|
|
||||||
chk.completionError(tree.pos(), ex);
|
|
||||||
} finally {
|
|
||||||
deferredLintHandler.setPos(prevLintPos);
|
|
||||||
log.useSource(prev);
|
|
||||||
dependencies.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enter all member fields and methods of a set of half completed
|
|
||||||
// classes in a second phase.
|
|
||||||
if (wasFirst) {
|
|
||||||
Set<JCCompilationUnit> topLevels = new HashSet<>();
|
|
||||||
try {
|
try {
|
||||||
while (halfcompleted.nonEmpty()) {
|
dependencies.push(c);
|
||||||
Env<AttrContext> toFinish = halfcompleted.next();
|
|
||||||
topLevels.add(toFinish.toplevel);
|
// Save class environment for later member enter (2) processing.
|
||||||
finish(toFinish);
|
halfcompleted.append(env);
|
||||||
if (allowTypeAnnos) {
|
|
||||||
typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
|
// Mark class as not yet attributed.
|
||||||
typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
|
c.flags_field |= UNATTRIBUTED;
|
||||||
|
|
||||||
|
// If this is a toplevel-class, make sure any preceding import
|
||||||
|
// clauses have been seen.
|
||||||
|
if (c.owner.kind == PCK) {
|
||||||
|
memberEnter(env.toplevel, env.enclosing(TOPLEVEL));
|
||||||
|
todo.append(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.owner.kind == TYP)
|
||||||
|
c.owner.complete();
|
||||||
|
|
||||||
|
// create an environment for evaluating the base clauses
|
||||||
|
Env<AttrContext> baseEnv = baseEnv(tree, env);
|
||||||
|
|
||||||
|
if (tree.extending != null)
|
||||||
|
annotate.annotateTypeLater(tree.extending, baseEnv, sym, tree.pos());
|
||||||
|
for (JCExpression impl : tree.implementing)
|
||||||
|
annotate.annotateTypeLater(impl, baseEnv, sym, tree.pos());
|
||||||
|
annotate.flush();
|
||||||
|
|
||||||
|
// Determine supertype.
|
||||||
|
Type supertype;
|
||||||
|
if (tree.extending != null) {
|
||||||
|
dependencies.push(AttributionKind.EXTENDS, tree.extending);
|
||||||
|
try {
|
||||||
|
supertype = attr.attribBase(tree.extending, baseEnv,
|
||||||
|
true, false, true);
|
||||||
|
} finally {
|
||||||
|
dependencies.pop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
supertype = ((tree.mods.flags & Flags.ENUM) != 0)
|
||||||
|
? attr.attribBase(enumBase(tree.pos, c), baseEnv,
|
||||||
|
true, false, false)
|
||||||
|
: (c.fullname == names.java_lang_Object)
|
||||||
|
? Type.noType
|
||||||
|
: syms.objectType;
|
||||||
|
}
|
||||||
|
ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
|
||||||
|
|
||||||
|
// Determine interfaces.
|
||||||
|
ListBuffer<Type> interfaces = new ListBuffer<>();
|
||||||
|
ListBuffer<Type> all_interfaces = null; // lazy init
|
||||||
|
Set<Type> interfaceSet = new HashSet<>();
|
||||||
|
List<JCExpression> interfaceTrees = tree.implementing;
|
||||||
|
for (JCExpression iface : interfaceTrees) {
|
||||||
|
dependencies.push(AttributionKind.IMPLEMENTS, iface);
|
||||||
|
try {
|
||||||
|
Type it = attr.attribBase(iface, baseEnv, false, true, true);
|
||||||
|
if (it.hasTag(CLASS)) {
|
||||||
|
interfaces.append(it);
|
||||||
|
if (all_interfaces != null) all_interfaces.append(it);
|
||||||
|
chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
|
||||||
|
} else {
|
||||||
|
if (all_interfaces == null)
|
||||||
|
all_interfaces = new ListBuffer<Type>().appendList(interfaces);
|
||||||
|
all_interfaces.append(modelMissingTypes(it, iface, true));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
dependencies.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((c.flags_field & ANNOTATION) != 0) {
|
||||||
|
ct.interfaces_field = List.of(syms.annotationType);
|
||||||
|
ct.all_interfaces_field = ct.interfaces_field;
|
||||||
|
} else {
|
||||||
|
ct.interfaces_field = interfaces.toList();
|
||||||
|
ct.all_interfaces_field = (all_interfaces == null)
|
||||||
|
? ct.interfaces_field : all_interfaces.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.fullname == names.java_lang_Object) {
|
||||||
|
if (tree.extending != null) {
|
||||||
|
chk.checkNonCyclic(tree.extending.pos(),
|
||||||
|
supertype);
|
||||||
|
ct.supertype_field = Type.noType;
|
||||||
|
}
|
||||||
|
else if (tree.implementing.nonEmpty()) {
|
||||||
|
chk.checkNonCyclic(tree.implementing.head.pos(),
|
||||||
|
ct.interfaces_field.head);
|
||||||
|
ct.interfaces_field = List.nil();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotations.
|
||||||
|
// In general, we cannot fully process annotations yet, but we
|
||||||
|
// can attribute the annotation types and then check to see if the
|
||||||
|
// @Deprecated annotation is present.
|
||||||
|
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
|
||||||
|
if (hasDeprecatedAnnotation(tree.mods.annotations))
|
||||||
|
c.flags_field |= DEPRECATED;
|
||||||
|
annotate.annotateLater(tree.mods.annotations, baseEnv,
|
||||||
|
c, tree.pos());
|
||||||
|
|
||||||
|
chk.checkNonCyclicDecl(tree);
|
||||||
|
|
||||||
|
// class type parameters use baseEnv but everything uses env
|
||||||
|
attr.attribTypeVariables(tree.typarams, baseEnv);
|
||||||
|
for (JCTypeParameter tp : tree.typarams)
|
||||||
|
annotate.annotateTypeLater(tp, baseEnv, sym, tree.pos());
|
||||||
|
|
||||||
|
// Add default constructor if needed.
|
||||||
|
if ((c.flags() & INTERFACE) == 0 &&
|
||||||
|
!TreeInfo.hasConstructors(tree.defs)) {
|
||||||
|
List<Type> argtypes = List.nil();
|
||||||
|
List<Type> typarams = List.nil();
|
||||||
|
List<Type> thrown = List.nil();
|
||||||
|
long ctorFlags = 0;
|
||||||
|
boolean based = false;
|
||||||
|
boolean addConstructor = true;
|
||||||
|
JCNewClass nc = null;
|
||||||
|
if (c.name.isEmpty()) {
|
||||||
|
nc = (JCNewClass)env.next.tree;
|
||||||
|
if (nc.constructor != null) {
|
||||||
|
addConstructor = nc.constructor.kind != ERR;
|
||||||
|
Type superConstrType = types.memberType(c.type,
|
||||||
|
nc.constructor);
|
||||||
|
argtypes = superConstrType.getParameterTypes();
|
||||||
|
typarams = superConstrType.getTypeArguments();
|
||||||
|
ctorFlags = nc.constructor.flags() & VARARGS;
|
||||||
|
if (nc.encl != null) {
|
||||||
|
argtypes = argtypes.prepend(nc.encl.type);
|
||||||
|
based = true;
|
||||||
|
}
|
||||||
|
thrown = superConstrType.getThrownTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addConstructor) {
|
||||||
|
MethodSymbol basedConstructor = nc != null ?
|
||||||
|
(MethodSymbol)nc.constructor : null;
|
||||||
|
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
|
||||||
|
basedConstructor,
|
||||||
|
typarams, argtypes, thrown,
|
||||||
|
ctorFlags, based);
|
||||||
|
tree.defs = tree.defs.prepend(constrDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enter symbols for 'this' into current scope.
|
||||||
|
VarSymbol thisSym =
|
||||||
|
new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
|
||||||
|
thisSym.pos = Position.FIRSTPOS;
|
||||||
|
env.info.scope.enter(thisSym);
|
||||||
|
// if this is a class, enter symbol for 'super' into current scope.
|
||||||
|
if ((c.flags_field & INTERFACE) == 0 &&
|
||||||
|
ct.supertype_field.hasTag(CLASS)) {
|
||||||
|
VarSymbol superSym =
|
||||||
|
new VarSymbol(FINAL | HASINIT, names._super,
|
||||||
|
ct.supertype_field, c);
|
||||||
|
superSym.pos = Position.FIRSTPOS;
|
||||||
|
env.info.scope.enter(superSym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that no package exists with same fully qualified name,
|
||||||
|
// but admit classes in the unnamed package which have the same
|
||||||
|
// name as a top-level package.
|
||||||
|
if (checkClash &&
|
||||||
|
c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
|
||||||
|
syms.packageExists(c.fullname)) {
|
||||||
|
log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
|
||||||
|
}
|
||||||
|
if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 &&
|
||||||
|
!env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) {
|
||||||
|
c.flags_field |= AUXILIARY;
|
||||||
|
}
|
||||||
|
} catch (CompletionFailure ex) {
|
||||||
|
chk.completionError(tree.pos(), ex);
|
||||||
} finally {
|
} finally {
|
||||||
isFirst = true;
|
deferredLintHandler.setPos(prevLintPos);
|
||||||
|
log.useSource(prev);
|
||||||
|
dependencies.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JCCompilationUnit toplevel : topLevels) {
|
// Enter all member fields and methods of a set of half completed
|
||||||
chk.checkImportsResolvable(toplevel);
|
// classes in a second phase.
|
||||||
}
|
if (wasFirst) {
|
||||||
|
Set<JCCompilationUnit> topLevels = new HashSet<>();
|
||||||
|
try {
|
||||||
|
while (halfcompleted.nonEmpty()) {
|
||||||
|
Env<AttrContext> toFinish = halfcompleted.next();
|
||||||
|
topLevels.add(toFinish.toplevel);
|
||||||
|
finish(toFinish);
|
||||||
|
if (allowTypeAnnos) {
|
||||||
|
typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
|
||||||
|
typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isFirst = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JCCompilationUnit toplevel : topLevels) {
|
||||||
|
chk.checkImportsResolvable(toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
annotate.enterDone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8054448
|
||||||
|
* @summary Verify that constant strings in nested classes in anonymous classes
|
||||||
|
* can be used in annotations.
|
||||||
|
* @compile FinalStringInNested.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FinalStringInNested {
|
||||||
|
|
||||||
|
public void f() {
|
||||||
|
Object o = new Object() {
|
||||||
|
@FinalStringInNested.Annotation(Nested.ID)
|
||||||
|
class Nested {
|
||||||
|
static final String ID = "B";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface Annotation {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user