MemberEnter.java revision 2800:1b58b3cc63bc
1139825Simp/* 21960Sdg * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. 31960Sdg * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41960Sdg * 51960Sdg * This code is free software; you can redistribute it and/or modify it 61960Sdg * under the terms of the GNU General Public License version 2 only, as 71960Sdg * published by the Free Software Foundation. Oracle designates this 81960Sdg * particular file as subject to the "Classpath" exception as provided 91960Sdg * by Oracle in the LICENSE file that accompanied this code. 101960Sdg * 111960Sdg * This code is distributed in the hope that it will be useful, but WITHOUT 121960Sdg * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131960Sdg * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141960Sdg * version 2 for more details (a copy is included in the LICENSE file that 151960Sdg * accompanied this code). 161960Sdg * 171960Sdg * You should have received a copy of the GNU General Public License version 181960Sdg * 2 along with this work; if not, write to the Free Software Foundation, 191960Sdg * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201960Sdg * 211960Sdg * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221960Sdg * or visit www.oracle.com if you need additional information or have any 231960Sdg * questions. 241960Sdg */ 251960Sdg 261960Sdgpackage com.sun.tools.javac.comp; 271960Sdg 281960Sdgimport javax.tools.JavaFileObject; 291960Sdg 301960Sdgimport com.sun.tools.javac.code.*; 311960Sdgimport com.sun.tools.javac.code.Scope.WriteableScope; 321960Sdgimport com.sun.tools.javac.tree.*; 3350477Speterimport com.sun.tools.javac.util.*; 341960Sdgimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 351960Sdg 362165Spaulimport com.sun.tools.javac.code.Symbol.*; 3715493Sbdeimport com.sun.tools.javac.code.Type.*; 382165Spaulimport com.sun.tools.javac.tree.JCTree.*; 3933057Sbde 40177633Sdfrimport static com.sun.tools.javac.code.Flags.*; 41177633Sdfrimport static com.sun.tools.javac.code.Kinds.*; 4233057Sbdeimport static com.sun.tools.javac.code.Kinds.Kind.*; 4333057Sbdeimport static com.sun.tools.javac.code.TypeTag.TYPEVAR; 44177633Sdfr 4533057Sbde/** Resolves field, method and constructor header, and constructs corresponding Symbols. 461960Sdg * 47177633Sdfr * <p><b>This is NOT part of any supported API. 48177633Sdfr * If you write code that depends on this, you do so at your own risk. 49177633Sdfr * This code and its internal interfaces are subject to change or 50177633Sdfr * deletion without notice.</b> 51177633Sdfr */ 52177633Sdfrpublic class MemberEnter extends JCTree.Visitor { 53177633Sdfr protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>(); 54177633Sdfr 55177633Sdfr /** A switch to determine whether we check for package/class conflicts 56177633Sdfr */ 57177633Sdfr final static boolean checkClash = true; 58177633Sdfr 59177633Sdfr private final Enter enter; 60177633Sdfr private final Log log; 611960Sdg private final Check chk; 62177633Sdfr private final Attr attr; 63177633Sdfr private final Symtab syms; 64177633Sdfr private final Annotate annotate; 65177633Sdfr private final Types types; 66177633Sdfr private final DeferredLintHandler deferredLintHandler; 67177633Sdfr 68177633Sdfr public static MemberEnter instance(Context context) { 6922521Sdyson MemberEnter instance = context.get(memberEnterKey); 70177633Sdfr if (instance == null) 71177633Sdfr instance = new MemberEnter(context); 72177633Sdfr return instance; 73177633Sdfr } 74177633Sdfr 75177633Sdfr protected MemberEnter(Context context) { 76177633Sdfr context.put(memberEnterKey, this); 77177633Sdfr enter = Enter.instance(context); 78177633Sdfr log = Log.instance(context); 79177633Sdfr chk = Check.instance(context); 80177633Sdfr attr = Attr.instance(context); 81177633Sdfr syms = Symtab.instance(context); 82177633Sdfr annotate = Annotate.instance(context); 83177633Sdfr types = Types.instance(context); 84177633Sdfr deferredLintHandler = DeferredLintHandler.instance(context); 85177633Sdfr } 86177633Sdfr 87177633Sdfr /** Construct method type from method signature. 88177633Sdfr * @param typarams The method's type parameters. 89177633Sdfr * @param params The method's value parameters. 90177633Sdfr * @param res The method's result type, 91177633Sdfr * null if it is a constructor. 92177633Sdfr * @param recvparam The method's receiver parameter, 93177633Sdfr * null if none given; TODO: or already set here? 94177633Sdfr * @param thrown The method's thrown exceptions. 95177633Sdfr * @param env The method's (local) environment. 96177633Sdfr */ 97177633Sdfr Type signature(MethodSymbol msym, 98177633Sdfr List<JCTypeParameter> typarams, 99177633Sdfr List<JCVariableDecl> params, 100177633Sdfr JCTree res, 101177633Sdfr JCVariableDecl recvparam, 102177633Sdfr List<JCExpression> thrown, 103177633Sdfr Env<AttrContext> env) { 104177633Sdfr 105177633Sdfr // Enter and attribute type parameters. 106177633Sdfr List<Type> tvars = enter.classEnter(typarams, env); 1071960Sdg attr.attribTypeVariables(typarams, env); 108177633Sdfr 109177633Sdfr // Enter and attribute value parameters. 110177633Sdfr ListBuffer<Type> argbuf = new ListBuffer<>(); 111177633Sdfr for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) { 112177633Sdfr memberEnter(l.head, env); 1131960Sdg argbuf.append(l.head.vartype.type); 114177633Sdfr } 1151960Sdg 11692719Salfred // Attribute result type, if one is given. 117177633Sdfr Type restype = res == null ? syms.voidType : attr.attribType(res, env); 118177633Sdfr 119177633Sdfr // Attribute receiver type, if one is given. 1201960Sdg Type recvtype; 12115493Sbde if (recvparam!=null) { 122 memberEnter(recvparam, env); 123 recvtype = recvparam.vartype.type; 124 } else { 125 recvtype = null; 126 } 127 128 // Attribute thrown exceptions. 129 ListBuffer<Type> thrownbuf = new ListBuffer<>(); 130 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) { 131 Type exc = attr.attribType(l.head, env); 132 if (!exc.hasTag(TYPEVAR)) { 133 exc = chk.checkClassType(l.head.pos(), exc); 134 } else if (exc.tsym.owner == msym) { 135 //mark inference variables in 'throws' clause 136 exc.tsym.flags_field |= THROWS; 137 } 138 thrownbuf.append(exc); 139 } 140 MethodType mtype = new MethodType(argbuf.toList(), 141 restype, 142 thrownbuf.toList(), 143 syms.methodClass); 144 mtype.recvtype = recvtype; 145 146 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); 147 } 148 149/* ******************************************************************** 150 * Visitor methods for member enter 151 *********************************************************************/ 152 153 /** Visitor argument: the current environment 154 */ 155 protected Env<AttrContext> env; 156 157 /** Enter field and method definitions and process import 158 * clauses, catching any completion failure exceptions. 159 */ 160 protected void memberEnter(JCTree tree, Env<AttrContext> env) { 161 Env<AttrContext> prevEnv = this.env; 162 try { 163 this.env = env; 164 tree.accept(this); 165 } catch (CompletionFailure ex) { 166 chk.completionError(tree.pos(), ex); 167 } finally { 168 this.env = prevEnv; 169 } 170 } 171 172 /** Enter members from a list of trees. 173 */ 174 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) { 175 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 176 memberEnter(l.head, env); 177 } 178 179 public void visitMethodDef(JCMethodDecl tree) { 180 WriteableScope enclScope = enter.enterScope(env); 181 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); 182 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); 183 tree.sym = m; 184 185 //if this is a default method, add the DEFAULT flag to the enclosing interface 186 if ((tree.mods.flags & DEFAULT) != 0) { 187 m.enclClass().flags_field |= DEFAULT; 188 } 189 190 Env<AttrContext> localEnv = methodEnv(tree, env); 191 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 192 try { 193 // Compute the method type 194 m.type = signature(m, tree.typarams, tree.params, 195 tree.restype, tree.recvparam, 196 tree.thrown, 197 localEnv); 198 } finally { 199 deferredLintHandler.setPos(prevLintPos); 200 } 201 202 if (types.isSignaturePolymorphic(m)) { 203 m.flags_field |= SIGNATURE_POLYMORPHIC; 204 } 205 206 // Set m.params 207 ListBuffer<VarSymbol> params = new ListBuffer<>(); 208 JCVariableDecl lastParam = null; 209 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 210 JCVariableDecl param = lastParam = l.head; 211 params.append(Assert.checkNonNull(param.sym)); 212 } 213 m.params = params.toList(); 214 215 // mark the method varargs, if necessary 216 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0) 217 m.flags_field |= Flags.VARARGS; 218 219 localEnv.info.scope.leave(); 220 if (chk.checkUnique(tree.pos(), m, enclScope)) { 221 enclScope.enter(m); 222 } 223 224 annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); 225 // Visit the signature of the method. Note that 226 // TypeAnnotate doesn't descend into the body. 227 annotate.annotateTypeLater(tree, localEnv, m, tree.pos()); 228 229 if (tree.defaultValue != null) 230 annotateDefaultValueLater(tree.defaultValue, localEnv, m, tree.pos()); 231 } 232 233 /** Create a fresh environment for method bodies. 234 * @param tree The method definition. 235 * @param env The environment current outside of the method definition. 236 */ 237 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) { 238 Env<AttrContext> localEnv = 239 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(tree.sym))); 240 localEnv.enclMethod = tree; 241 if (tree.sym.type != null) { 242 //when this is called in the enter stage, there's no type to be set 243 localEnv.info.returnResult = attr.new ResultInfo(KindSelector.VAL, 244 tree.sym.type.getReturnType()); 245 } 246 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 247 return localEnv; 248 } 249 250 public void visitVarDef(JCVariableDecl tree) { 251 Env<AttrContext> localEnv = env; 252 if ((tree.mods.flags & STATIC) != 0 || 253 (env.info.scope.owner.flags() & INTERFACE) != 0) { 254 localEnv = env.dup(tree, env.info.dup()); 255 localEnv.info.staticLevel++; 256 } 257 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 258 try { 259 if (TreeInfo.isEnumInit(tree)) { 260 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 261 } else { 262 attr.attribType(tree.vartype, localEnv); 263 if (TreeInfo.isReceiverParam(tree)) 264 checkReceiver(tree, localEnv); 265 } 266 } finally { 267 deferredLintHandler.setPos(prevLintPos); 268 } 269 270 if ((tree.mods.flags & VARARGS) != 0) { 271 //if we are entering a varargs parameter, we need to 272 //replace its type (a plain array type) with the more 273 //precise VarargsType --- we need to do it this way 274 //because varargs is represented in the tree as a 275 //modifier on the parameter declaration, and not as a 276 //distinct type of array node. 277 ArrayType atype = (ArrayType)tree.vartype.type; 278 tree.vartype.type = atype.makeVarargs(); 279 } 280 WriteableScope enclScope = enter.enterScope(env); 281 VarSymbol v = 282 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner); 283 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 284 tree.sym = v; 285 if (tree.init != null) { 286 v.flags_field |= HASINIT; 287 if ((v.flags_field & FINAL) != 0 && 288 needsLazyConstValue(tree.init)) { 289 Env<AttrContext> initEnv = getInitEnv(tree, env); 290 initEnv.info.enclVar = v; 291 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); 292 } 293 } 294 if (chk.checkUnique(tree.pos(), v, enclScope)) { 295 chk.checkTransparentVar(tree.pos(), v, enclScope); 296 enclScope.enter(v); 297 } 298 299 annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); 300 annotate.annotateTypeLater(tree.vartype, localEnv, v, tree.pos()); 301 302 v.pos = tree.pos; 303 } 304 // where 305 void checkType(JCTree tree, Type type, String diag) { 306 if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) { 307 log.error(tree, diag, type, tree.type); 308 } 309 } 310 void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { 311 attr.attribExpr(tree.nameexpr, localEnv); 312 MethodSymbol m = localEnv.enclMethod.sym; 313 if (m.isConstructor()) { 314 Type outertype = m.owner.owner.type; 315 if (outertype.hasTag(TypeTag.METHOD)) { 316 // we have a local inner class 317 outertype = m.owner.owner.owner.type; 318 } 319 if (outertype.hasTag(TypeTag.CLASS)) { 320 checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); 321 checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); 322 } else { 323 log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); 324 } 325 } else { 326 checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); 327 checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); 328 } 329 } 330 331 public boolean needsLazyConstValue(JCTree tree) { 332 InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 333 tree.accept(initTreeVisitor); 334 return initTreeVisitor.result; 335 } 336 337 /** Visitor class for expressions which might be constant expressions. 338 */ 339 static class InitTreeVisitor extends JCTree.Visitor { 340 341 private boolean result = true; 342 343 @Override 344 public void visitTree(JCTree tree) {} 345 346 @Override 347 public void visitNewClass(JCNewClass that) { 348 result = false; 349 } 350 351 @Override 352 public void visitNewArray(JCNewArray that) { 353 result = false; 354 } 355 356 @Override 357 public void visitLambda(JCLambda that) { 358 result = false; 359 } 360 361 @Override 362 public void visitReference(JCMemberReference that) { 363 result = false; 364 } 365 366 @Override 367 public void visitApply(JCMethodInvocation that) { 368 result = false; 369 } 370 371 @Override 372 public void visitSelect(JCFieldAccess tree) { 373 tree.selected.accept(this); 374 } 375 376 @Override 377 public void visitConditional(JCConditional tree) { 378 tree.cond.accept(this); 379 tree.truepart.accept(this); 380 tree.falsepart.accept(this); 381 } 382 383 @Override 384 public void visitParens(JCParens tree) { 385 tree.expr.accept(this); 386 } 387 388 @Override 389 public void visitTypeCast(JCTypeCast tree) { 390 tree.expr.accept(this); 391 } 392 } 393 394 /** Create a fresh environment for a variable's initializer. 395 * If the variable is a field, the owner of the environment's scope 396 * is be the variable itself, otherwise the owner is the method 397 * enclosing the variable definition. 398 * 399 * @param tree The variable definition. 400 * @param env The environment current outside of the variable definition. 401 */ 402 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 403 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 404 if (tree.sym.owner.kind == TYP) { 405 localEnv.info.scope = env.info.scope.dupUnshared(tree.sym); 406 } 407 if ((tree.mods.flags & STATIC) != 0 || 408 ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null)) 409 localEnv.info.staticLevel++; 410 return localEnv; 411 } 412 413 /** Default member enter visitor method: do nothing 414 */ 415 public void visitTree(JCTree tree) { 416 } 417 418 public void visitErroneous(JCErroneous tree) { 419 if (tree.errs != null) 420 memberEnter(tree.errs, env); 421 } 422 423 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 424 Env<AttrContext> mEnv = methodEnv(tree, env); 425 mEnv.info.lint = mEnv.info.lint.augment(tree.sym); 426 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 427 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 428 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 429 mEnv.info.scope.enterIfAbsent(l.head.sym); 430 return mEnv; 431 } 432 433 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 434 Env<AttrContext> iEnv = initEnv(tree, env); 435 return iEnv; 436 } 437 438 /** Queue processing of an attribute default value. */ 439 void annotateDefaultValueLater(final JCExpression defaultValue, 440 final Env<AttrContext> localEnv, 441 final MethodSymbol m, 442 final DiagnosticPosition deferPos) { 443 annotate.normal(new Annotate.Worker() { 444 @Override 445 public String toString() { 446 return "annotate " + m.owner + "." + 447 m + " default " + defaultValue; 448 } 449 450 @Override 451 public void run() { 452 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 453 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos); 454 try { 455 enterDefaultValue(defaultValue, localEnv, m); 456 } finally { 457 deferredLintHandler.setPos(prevLintPos); 458 log.useSource(prev); 459 } 460 } 461 }); 462 annotate.validate(new Annotate.Worker() { //validate annotations 463 @Override 464 public void run() { 465 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 466 try { 467 // if default value is an annotation, check it is a well-formed 468 // annotation value (e.g. no duplicate values, no missing values, etc.) 469 chk.validateAnnotationTree(defaultValue); 470 } finally { 471 log.useSource(prev); 472 } 473 } 474 }); 475 } 476 477 /** Enter a default value for an attribute method. */ 478 private void enterDefaultValue(final JCExpression defaultValue, 479 final Env<AttrContext> localEnv, 480 final MethodSymbol m) { 481 m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(), 482 defaultValue, 483 localEnv); 484 } 485 486} 487