1 /*
   2  * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.HashSet;
  29 import java.util.Set;
  30 import java.util.function.BiConsumer;
  31 
  32 import javax.tools.JavaFileObject;
  33 
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.code.Lint.LintCategory;
  36 import com.sun.tools.javac.code.Scope.ImportFilter;
  37 import com.sun.tools.javac.code.Scope.ImportScope;
  38 import com.sun.tools.javac.code.Scope.NamedImportScope;
  39 import com.sun.tools.javac.code.Scope.StarImportScope;
  40 import com.sun.tools.javac.code.Scope.WriteableScope;
  41 import com.sun.tools.javac.code.Source.Feature;
  42 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  43 import com.sun.tools.javac.jvm.Target;
  44 import com.sun.tools.javac.parser.Parser;
  45 import com.sun.tools.javac.parser.ParserFactory;
  46 import com.sun.tools.javac.tree.*;
  47 import com.sun.tools.javac.util.*;
  48 import com.sun.tools.javac.util.DefinedBy.Api;
  49 
  50 import com.sun.tools.javac.code.Symbol.*;
  51 import com.sun.tools.javac.code.Type.*;
  52 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  53 import com.sun.tools.javac.tree.JCTree.*;
  54 
  55 import static com.sun.tools.javac.code.Flags.*;
  56 import static com.sun.tools.javac.code.Flags.ANNOTATION;
  57 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
  58 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  59 import static com.sun.tools.javac.code.Kinds.Kind.*;
  60 import static com.sun.tools.javac.code.TypeTag.CLASS;
  61 import static com.sun.tools.javac.code.TypeTag.ERROR;
  62 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  63 
  64 import static com.sun.tools.javac.code.TypeTag.*;
  65 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  66 
  67 import com.sun.tools.javac.util.Dependencies.CompletionCause;
  68 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  69 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  70 
  71 /** This is the second phase of Enter, in which classes are completed
  72  *  by resolving their headers and entering their members in the into
  73  *  the class scope. See Enter for an overall overview.
  74  *
  75  *  This class uses internal phases to process the classes. When a phase
  76  *  processes classes, the lower phases are not invoked until all classes
  77  *  pass through the current phase. Note that it is possible that upper phases
  78  *  are run due to recursive completion. The internal phases are:
  79  *  - ImportPhase: shallow pass through imports, adds information about imports
  80  *                 the NamedImportScope and StarImportScope, but avoids queries
  81  *                 about class hierarchy.
  82  *  - HierarchyPhase: resolves the supertypes of the given class. Does not handle
  83  *                    type parameters of the class or type argument of the supertypes.
  84  *  - HeaderPhase: finishes analysis of the header of the given class by resolving
  85  *                 type parameters, attributing supertypes including type arguments
  86  *                 and scheduling full annotation attribution. This phase also adds
  87  *                 a synthetic default constructor if needed and synthetic "this" field.
  88  *  - MembersPhase: resolves headers for fields, methods and constructors in the given class.
  89  *                  Also generates synthetic enum members.
  90  *
  91  *  <p><b>This is NOT part of any supported API.
  92  *  If you write code that depends on this, you do so at your own risk.
  93  *  This code and its internal interfaces are subject to change or
  94  *  deletion without notice.</b>
  95  */
  96 public class TypeEnter implements Completer {
  97     protected static final Context.Key<TypeEnter> typeEnterKey = new Context.Key<>();
  98 
  99     /** A switch to determine whether we check for package/class conflicts
 100      */
 101     static final boolean checkClash = true;
 102 
 103     private final Names names;
 104     private final Enter enter;
 105     private final MemberEnter memberEnter;
 106     private final Log log;
 107     private final Check chk;
 108     private final Attr attr;
 109     private final Symtab syms;
 110     private final TreeMaker make;
 111     private final Todo todo;
 112     private final Annotate annotate;
 113     private final TypeAnnotations typeAnnotations;
 114     private final Types types;
 115     private final DeferredLintHandler deferredLintHandler;
 116     private final Lint lint;
 117     private final TypeEnvs typeEnvs;
 118     private final Dependencies dependencies;
 119     private final ParserFactory parserFactory;
 120     private final Preview preview;
 121 
 122     public static TypeEnter instance(Context context) {
 123         TypeEnter instance = context.get(typeEnterKey);
 124         if (instance == null)
 125             instance = new TypeEnter(context);
 126         return instance;
 127     }
 128 
 129     @SuppressWarnings("this-escape")
 130     protected TypeEnter(Context context) {
 131         context.put(typeEnterKey, this);
 132         names = Names.instance(context);
 133         enter = Enter.instance(context);
 134         memberEnter = MemberEnter.instance(context);
 135         log = Log.instance(context);
 136         chk = Check.instance(context);
 137         attr = Attr.instance(context);
 138         syms = Symtab.instance(context);
 139         make = TreeMaker.instance(context);
 140         todo = Todo.instance(context);
 141         annotate = Annotate.instance(context);
 142         typeAnnotations = TypeAnnotations.instance(context);
 143         types = Types.instance(context);
 144         deferredLintHandler = DeferredLintHandler.instance(context);
 145         lint = Lint.instance(context);
 146         typeEnvs = TypeEnvs.instance(context);
 147         dependencies = Dependencies.instance(context);
 148         parserFactory = ParserFactory.instance(context);
 149         preview = Preview.instance(context);
 150         Source source = Source.instance(context);
 151         allowDeprecationOnImport = Feature.DEPRECATION_ON_IMPORT.allowedInSource(source);
 152     }
 153 
 154     /**
 155      * Switch: should deprecation warnings be issued on import
 156      */
 157     boolean allowDeprecationOnImport;
 158 
 159     /** A flag to disable completion from time to time during member
 160      *  enter, as we only need to look up types.  This avoids
 161      *  unnecessarily deep recursion.
 162      */
 163     boolean completionEnabled = true;
 164 
 165     /* Verify Imports:
 166      */
 167     protected void ensureImportsChecked(List<JCCompilationUnit> trees) {
 168         // if there remain any unimported toplevels (these must have
 169         // no classes at all), process their import statements as well.
 170         for (JCCompilationUnit tree : trees) {
 171             if (!tree.starImportScope.isFilled()) {
 172                 Env<AttrContext> topEnv = enter.topLevelEnv(tree);
 173                 finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); });
 174             }
 175         }
 176     }
 177 
 178 /* ********************************************************************
 179  * Source completer
 180  *********************************************************************/
 181 
 182     /** Complete entering a class.
 183      *  @param sym         The symbol of the class to be completed.
 184      */
 185     @Override
 186     public void complete(Symbol sym) throws CompletionFailure {
 187         // Suppress some (recursive) MemberEnter invocations
 188         if (!completionEnabled) {
 189             // Re-install same completer for next time around and return.
 190             Assert.check((sym.flags() & Flags.COMPOUND) == 0);
 191             sym.completer = this;
 192             return;
 193         }
 194 
 195         try {
 196             annotate.blockAnnotations();
 197             sym.flags_field |= UNATTRIBUTED;
 198 
 199             List<Env<AttrContext>> queue;
 200 
 201             dependencies.push((ClassSymbol) sym, CompletionCause.MEMBER_ENTER);
 202             try {
 203                 queue = completeClass.completeEnvs(List.of(typeEnvs.get((ClassSymbol) sym)));
 204             } finally {
 205                 dependencies.pop();
 206             }
 207 
 208             if (!queue.isEmpty()) {
 209                 Set<JCCompilationUnit> seen = new HashSet<>();
 210 
 211                 for (Env<AttrContext> env : queue) {
 212                     if (env.toplevel.defs.contains(env.enclClass) && seen.add(env.toplevel)) {
 213                         finishImports(env.toplevel, () -> {});
 214                     }
 215                 }
 216             }
 217         } finally {
 218             annotate.unblockAnnotations();
 219         }
 220     }
 221 
 222     void finishImports(JCCompilationUnit toplevel, Runnable resolve) {
 223         JavaFileObject prev = log.useSource(toplevel.sourcefile);
 224         try {
 225             resolve.run();
 226             chk.checkImportsUnique(toplevel);
 227             chk.checkImportsResolvable(toplevel);
 228             chk.checkImportedPackagesObservable(toplevel);
 229             toplevel.namedImportScope.finalizeScope();
 230             toplevel.starImportScope.finalizeScope();
 231         } catch (CompletionFailure cf) {
 232             chk.completionError(toplevel.pos(), cf);
 233         } finally {
 234             log.useSource(prev);
 235         }
 236     }
 237 
 238     abstract class Phase {
 239         private final ListBuffer<Env<AttrContext>> queue = new ListBuffer<>();
 240         private final Phase next;
 241         private final CompletionCause phaseName;
 242 
 243         Phase(CompletionCause phaseName, Phase next) {
 244             this.phaseName = phaseName;
 245             this.next = next;
 246         }
 247 
 248         public final List<Env<AttrContext>> completeEnvs(List<Env<AttrContext>> envs) {
 249             boolean firstToComplete = queue.isEmpty();
 250 
 251             Phase prevTopLevelPhase = topLevelPhase;
 252             boolean success = false;
 253 
 254             try {
 255                 topLevelPhase = this;
 256                 doCompleteEnvs(envs);
 257                 success = true;
 258             } finally {
 259                 topLevelPhase = prevTopLevelPhase;
 260                 if (!success && firstToComplete) {
 261                     //an exception was thrown, e.g. BreakAttr:
 262                     //the queue would become stale, clear it:
 263                     queue.clear();
 264                 }
 265             }
 266 
 267             if (firstToComplete) {
 268                 List<Env<AttrContext>> out = queue.toList();
 269 
 270                 queue.clear();
 271                 return next != null ? next.completeEnvs(out) : out;
 272             } else {
 273                 return List.nil();
 274             }
 275         }
 276 
 277         protected void doCompleteEnvs(List<Env<AttrContext>> envs) {
 278             for (Env<AttrContext> env : envs) {
 279                 JCClassDecl tree = (JCClassDecl)env.tree;
 280 
 281                 queue.add(env);
 282 
 283                 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
 284                 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
 285                 try {
 286                     dependencies.push(env.enclClass.sym, phaseName);
 287                     runPhase(env);
 288                 } catch (CompletionFailure ex) {
 289                     chk.completionError(tree.pos(), ex);
 290                 } finally {
 291                     dependencies.pop();
 292                     deferredLintHandler.setPos(prevLintPos);
 293                     log.useSource(prev);
 294                 }
 295             }
 296         }
 297 
 298         protected abstract void runPhase(Env<AttrContext> env);
 299     }
 300 
 301     private final ImportsPhase completeClass = new ImportsPhase();
 302     private Phase topLevelPhase;
 303 
 304     /**Analyze import clauses.
 305      */
 306     private final class ImportsPhase extends Phase {
 307 
 308         public ImportsPhase() {
 309             super(CompletionCause.IMPORTS_PHASE, new HierarchyPhase());
 310         }
 311 
 312         Env<AttrContext> env;
 313         ImportFilter staticImportFilter;
 314         ImportFilter typeImportFilter;
 315         BiConsumer<JCImport, CompletionFailure> cfHandler =
 316                 (imp, cf) -> chk.completionError(imp.pos(), cf);
 317 
 318         @Override
 319         protected void runPhase(Env<AttrContext> env) {
 320             JCClassDecl tree = env.enclClass;
 321             ClassSymbol sym = tree.sym;
 322 
 323             // If sym is a toplevel-class, make sure any import
 324             // clauses in its source file have been seen.
 325             if (sym.owner.kind == PCK) {
 326                 resolveImports(env.toplevel, env.enclosing(TOPLEVEL));
 327                 todo.append(env);
 328             }
 329 
 330             if (sym.owner.kind == TYP)
 331                 sym.owner.complete();
 332         }
 333 
 334         private void importJavaLang(JCCompilationUnit tree, Env<AttrContext> env, ImportFilter typeImportFilter) {
 335             // Import-on-demand java.lang.
 336             PackageSymbol javaLang = syms.enterPackage(syms.java_base, names.java_lang);
 337             if (javaLang.members().isEmpty() && !javaLang.exists()) {
 338                 log.error(Errors.NoJavaLang);
 339                 throw new Abort();
 340             }
 341             importAll(make.at(tree.pos()).Import(make.Select(make.QualIdent(javaLang.owner), javaLang), false),
 342                 javaLang, env);
 343         }
 344 
 345         private void staticImports(JCCompilationUnit tree, Env<AttrContext> env, ImportFilter staticImportFilter) {
 346              if (preview.isEnabled() && preview.isPreview(Feature.STRING_TEMPLATES)) {
 347                 Lint prevLint = chk.setLint(lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL, LintCategory.PREVIEW));
 348                 boolean prevPreviewCheck = chk.disablePreviewCheck;
 349 
 350                 try {
 351                     chk.disablePreviewCheck = true;
 352                     String autoImports = """
 353                             import static java.lang.StringTemplate.STR;
 354                             """;
 355                     Parser parser = parserFactory.newParser(autoImports, false, false, false, false);
 356                     JCCompilationUnit importTree = parser.parseCompilationUnit();
 357 
 358                     for (JCImport imp : importTree.getImports()) {
 359                         doImport(imp);
 360                     }
 361                 } finally {
 362                     chk.setLint(prevLint);
 363                     chk.disablePreviewCheck = prevPreviewCheck;
 364                 }
 365             }
 366         }
 367 
 368         private void resolveImports(JCCompilationUnit tree, Env<AttrContext> env) {
 369             if (tree.starImportScope.isFilled()) {
 370                 // we must have already processed this toplevel
 371                 return;
 372             }
 373 
 374             ImportFilter prevStaticImportFilter = staticImportFilter;
 375             ImportFilter prevTypeImportFilter = typeImportFilter;
 376             DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
 377             Lint prevLint = chk.setLint(lint);
 378             Env<AttrContext> prevEnv = this.env;
 379             try {
 380                 this.env = env;
 381                 final PackageSymbol packge = env.toplevel.packge;
 382                 this.staticImportFilter =
 383                         (origin, sym) -> sym.isStatic() &&
 384                                          chk.importAccessible(sym, packge) &&
 385                                          sym.isMemberOf((TypeSymbol) origin.owner, types);
 386                 this.typeImportFilter =
 387                         (origin, sym) -> sym.kind == TYP &&
 388                                          chk.importAccessible(sym, packge);
 389 
 390                 importJavaLang(tree, env, typeImportFilter);
 391                 staticImports(tree, env, staticImportFilter);
 392 
 393                 JCModuleDecl decl = tree.getModuleDecl();
 394 
 395                 // Process the package def and all import clauses.
 396                 if (tree.getPackage() != null && decl == null)
 397                     checkClassPackageClash(tree.getPackage());
 398 
 399                 for (JCImport imp : tree.getImports()) {
 400                     doImport(imp);
 401                 }
 402 
 403                 if (decl != null) {
 404                     DiagnosticPosition prevCheckDeprecatedLintPos = deferredLintHandler.setPos(decl.pos());
 405                     try {
 406                         //check @Deprecated:
 407                         markDeprecated(decl.sym, decl.mods.annotations, env);
 408                     } finally {
 409                         deferredLintHandler.setPos(prevCheckDeprecatedLintPos);
 410                     }
 411                     // process module annotations
 412                     annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle, decl.pos());
 413                 }
 414             } finally {
 415                 this.env = prevEnv;
 416                 chk.setLint(prevLint);
 417                 deferredLintHandler.setPos(prevLintPos);
 418                 this.staticImportFilter = prevStaticImportFilter;
 419                 this.typeImportFilter = prevTypeImportFilter;
 420             }
 421         }
 422 
 423         private void checkClassPackageClash(JCPackageDecl tree) {
 424             // check that no class exists with same fully qualified name as
 425             // toplevel package
 426             if (checkClash && tree.pid != null) {
 427                 Symbol p = env.toplevel.packge;
 428                 while (p.owner != syms.rootPackage) {
 429                     p.owner.complete(); // enter all class members of p
 430                     //need to lookup the owning module/package:
 431                     PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, p.owner.getQualifiedName());
 432                     if (syms.getClass(pack.modle, p.getQualifiedName()) != null) {
 433                         log.error(tree.pos,
 434                                   Errors.PkgClashesWithClassOfSameName(p));
 435                     }
 436                     p = p.owner;
 437                 }
 438             }
 439             // process package annotations
 440             annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree.pos());
 441         }
 442 
 443         private void doImport(JCImport tree) {
 444             JCFieldAccess imp = tree.qualid;
 445             Name name = TreeInfo.name(imp);
 446 
 447             // Create a local environment pointing to this tree to disable
 448             // effects of other imports in Resolve.findGlobalType
 449             Env<AttrContext> localEnv = env.dup(tree);
 450 
 451             TypeSymbol p = attr.attribImportQualifier(tree, localEnv).tsym;
 452             if (name == names.asterisk) {
 453                 // Import on demand.
 454                 chk.checkCanonical(imp.selected);
 455                 if (tree.staticImport)
 456                     importStaticAll(tree, p, env);
 457                 else
 458                     importAll(tree, p, env);
 459             } else {
 460                 // Named type import.
 461                 if (tree.staticImport) {
 462                     importNamedStatic(tree, p, name, localEnv);
 463                     chk.checkCanonical(imp.selected);
 464                 } else {
 465                     Type importedType = attribImportType(imp, localEnv);
 466                     Type originalType = importedType.getOriginalType();
 467                     TypeSymbol c = originalType.hasTag(CLASS) ? originalType.tsym : importedType.tsym;
 468                     chk.checkCanonical(imp);
 469                     importNamed(tree.pos(), c, env, tree);
 470                 }
 471             }
 472         }
 473 
 474         Type attribImportType(JCTree tree, Env<AttrContext> env) {
 475             Assert.check(completionEnabled);
 476             Lint prevLint = chk.setLint(allowDeprecationOnImport ?
 477                     lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL, LintCategory.PREVIEW));
 478             try {
 479                 // To prevent deep recursion, suppress completion of some
 480                 // types.
 481                 completionEnabled = false;
 482                 return attr.attribType(tree, env);
 483             } finally {
 484                 completionEnabled = true;
 485                 chk.setLint(prevLint);
 486             }
 487         }
 488 
 489         /** Import all classes of a class or package on demand.
 490          *  @param imp           The import that is being handled.
 491          *  @param tsym          The class or package the members of which are imported.
 492          *  @param env           The env in which the imported classes will be entered.
 493          */
 494         private void importAll(JCImport imp,
 495                                final TypeSymbol tsym,
 496                                Env<AttrContext> env) {
 497             env.toplevel.starImportScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler);
 498         }
 499 
 500         /** Import all static members of a class or package on demand.
 501          *  @param imp           The import that is being handled.
 502          *  @param tsym          The class or package the members of which are imported.
 503          *  @param env           The env in which the imported classes will be entered.
 504          */
 505         private void importStaticAll(JCImport imp,
 506                                      final TypeSymbol tsym,
 507                                      Env<AttrContext> env) {
 508             final StarImportScope toScope = env.toplevel.starImportScope;
 509             final TypeSymbol origin = tsym;
 510 
 511             toScope.importAll(types, origin.members(), staticImportFilter, imp, cfHandler);
 512         }
 513 
 514         /** Import statics types of a given name.  Non-types are handled in Attr.
 515          *  @param imp           The import that is being handled.
 516          *  @param tsym          The class from which the name is imported.
 517          *  @param name          The (simple) name being imported.
 518          *  @param env           The environment containing the named import
 519          *                  scope to add to.
 520          */
 521         private void importNamedStatic(final JCImport imp,
 522                                        final TypeSymbol tsym,
 523                                        final Name name,
 524                                        final Env<AttrContext> env) {
 525             if (tsym.kind != TYP) {
 526                 log.error(DiagnosticFlag.RECOVERABLE, imp.pos(), Errors.StaticImpOnlyClassesAndInterfaces);
 527                 return;
 528             }
 529 
 530             final NamedImportScope toScope = env.toplevel.namedImportScope;
 531             final Scope originMembers = tsym.members();
 532 
 533             imp.importScope = toScope.importByName(types, originMembers, name, staticImportFilter, imp, cfHandler);
 534         }
 535 
 536         /** Import given class.
 537          *  @param pos           Position to be used for error reporting.
 538          *  @param tsym          The class to be imported.
 539          *  @param env           The environment containing the named import
 540          *                  scope to add to.
 541          */
 542         private void importNamed(DiagnosticPosition pos, final Symbol tsym, Env<AttrContext> env, JCImport imp) {
 543             if (tsym.kind == TYP)
 544                 imp.importScope = env.toplevel.namedImportScope.importType(tsym.owner.members(), tsym.owner.members(), tsym);
 545         }
 546 
 547     }
 548 
 549     /**Defines common utility methods used by the HierarchyPhase and HeaderPhase.
 550      */
 551     private abstract class AbstractHeaderPhase extends Phase {
 552 
 553         public AbstractHeaderPhase(CompletionCause phaseName, Phase next) {
 554             super(phaseName, next);
 555         }
 556 
 557         protected Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
 558             WriteableScope baseScope = WriteableScope.create(tree.sym);
 559             //import already entered local classes into base scope
 560             for (Symbol sym : env.outer.info.scope.getSymbols(NON_RECURSIVE)) {
 561                 if (sym.isDirectlyOrIndirectlyLocal()) {
 562                     baseScope.enter(sym);
 563                 }
 564             }
 565             //import current type-parameters into base scope
 566             if (tree.typarams != null)
 567                 for (List<JCTypeParameter> typarams = tree.typarams;
 568                      typarams.nonEmpty();
 569                      typarams = typarams.tail)
 570                     baseScope.enter(typarams.head.type.tsym);
 571             Env<AttrContext> outer = env.outer; // the base clause can't see members of this class
 572             Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope));
 573             localEnv.baseClause = true;
 574             localEnv.outer = outer;
 575             localEnv.info.isSelfCall = false;
 576             return localEnv;
 577         }
 578 
 579         /** Generate a base clause for an enum type.
 580          *  @param pos              The position for trees and diagnostics, if any
 581          *  @param c                The class symbol of the enum
 582          */
 583         protected  JCExpression enumBase(int pos, ClassSymbol c) {
 584             JCExpression result = make.at(pos).
 585                 TypeApply(make.QualIdent(syms.enumSym),
 586                           List.of(make.Type(c.type)));
 587             return result;
 588         }
 589 
 590         /** Generate a base clause for a record type.
 591          *  @param pos              The position for trees and diagnostics, if any
 592          *  @param c                The class symbol of the record
 593          */
 594         protected  JCExpression recordBase(int pos, ClassSymbol c) {
 595             JCExpression result = make.at(pos).
 596                 QualIdent(syms.recordType.tsym);
 597             return result;
 598         }
 599 
 600         protected Type modelMissingTypes(Env<AttrContext> env, Type t, final JCExpression tree, final boolean interfaceExpected) {
 601             if (!t.hasTag(ERROR))
 602                 return t;
 603 
 604             return new ErrorType(t.getOriginalType(), t.tsym) {
 605                 private Type modelType;
 606 
 607                 @Override
 608                 public Type getModelType() {
 609                     if (modelType == null)
 610                         modelType = new Synthesizer(env.toplevel.modle, getOriginalType(), interfaceExpected).visit(tree);
 611                     return modelType;
 612                 }
 613             };
 614         }
 615             // where:
 616             private class Synthesizer extends JCTree.Visitor {
 617                 ModuleSymbol msym;
 618                 Type originalType;
 619                 boolean interfaceExpected;
 620                 List<ClassSymbol> synthesizedSymbols = List.nil();
 621                 Type result;
 622 
 623                 Synthesizer(ModuleSymbol msym, Type originalType, boolean interfaceExpected) {
 624                     this.msym = msym;
 625                     this.originalType = originalType;
 626                     this.interfaceExpected = interfaceExpected;
 627                 }
 628 
 629                 Type visit(JCTree tree) {
 630                     tree.accept(this);
 631                     return result;
 632                 }
 633 
 634                 List<Type> visit(List<? extends JCTree> trees) {
 635                     ListBuffer<Type> lb = new ListBuffer<>();
 636                     for (JCTree t: trees)
 637                         lb.append(visit(t));
 638                     return lb.toList();
 639                 }
 640 
 641                 @Override
 642                 public void visitTree(JCTree tree) {
 643                     result = syms.errType;
 644                 }
 645 
 646                 @Override
 647                 public void visitIdent(JCIdent tree) {
 648                     if (!tree.type.hasTag(ERROR)) {
 649                         result = tree.type;
 650                     } else {
 651                         result = synthesizeClass(tree.name, msym.unnamedPackage).type;
 652                     }
 653                 }
 654 
 655                 @Override
 656                 public void visitSelect(JCFieldAccess tree) {
 657                     if (!tree.type.hasTag(ERROR)) {
 658                         result = tree.type;
 659                     } else {
 660                         Type selectedType;
 661                         boolean prev = interfaceExpected;
 662                         try {
 663                             interfaceExpected = false;
 664                             selectedType = visit(tree.selected);
 665                         } finally {
 666                             interfaceExpected = prev;
 667                         }
 668                         ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym);
 669                         result = c.type;
 670                     }
 671                 }
 672 
 673                 @Override
 674                 public void visitTypeApply(JCTypeApply tree) {
 675                     if (!tree.type.hasTag(ERROR)) {
 676                         result = tree.type;
 677                     } else {
 678                         ClassType clazzType = (ClassType) visit(tree.clazz);
 679                         if (synthesizedSymbols.contains(clazzType.tsym))
 680                             synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size());
 681                         final List<Type> actuals = visit(tree.arguments);
 682                         result = new ErrorType(tree.type, clazzType.tsym) {
 683                             @Override @DefinedBy(Api.LANGUAGE_MODEL)
 684                             public List<Type> getTypeArguments() {
 685                                 return actuals;
 686                             }
 687                         };
 688                     }
 689                 }
 690 
 691                 ClassSymbol synthesizeClass(Name name, Symbol owner) {
 692                     int flags = interfaceExpected ? INTERFACE : 0;
 693                     ClassSymbol c = new ClassSymbol(flags, name, owner);
 694                     c.members_field = new Scope.ErrorScope(c);
 695                     c.type = new ErrorType(originalType, c) {
 696                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 697                         public List<Type> getTypeArguments() {
 698                             return typarams_field;
 699                         }
 700                     };
 701                     synthesizedSymbols = synthesizedSymbols.prepend(c);
 702                     return c;
 703                 }
 704 
 705                 void synthesizeTyparams(ClassSymbol sym, int n) {
 706                     ClassType ct = (ClassType) sym.type;
 707                     Assert.check(ct.typarams_field.isEmpty());
 708                     if (n == 1) {
 709                         TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType);
 710                         ct.typarams_field = ct.typarams_field.prepend(v);
 711                     } else {
 712                         for (int i = n; i > 0; i--) {
 713                             TypeVar v = new TypeVar(names.fromString("T" + i), sym,
 714                                                     syms.botType);
 715                             ct.typarams_field = ct.typarams_field.prepend(v);
 716                         }
 717                     }
 718                 }
 719             }
 720 
 721         protected void attribSuperTypes(Env<AttrContext> env, Env<AttrContext> baseEnv) {
 722             JCClassDecl tree = env.enclClass;
 723             ClassSymbol sym = tree.sym;
 724             ClassType ct = (ClassType)sym.type;
 725             // Determine supertype.
 726             Type supertype;
 727             JCExpression extending;
 728 
 729             if (tree.extending != null) {
 730                 extending = clearTypeParams(tree.extending);
 731                 supertype = attr.attribBase(extending, baseEnv, true, false, true);
 732                 if (supertype == syms.recordType) {
 733                     log.error(tree, Errors.InvalidSupertypeRecord(supertype.tsym));
 734                 }
 735             } else {
 736                 extending = null;
 737                 supertype = ((tree.mods.flags & Flags.ENUM) != 0)
 738                 ? attr.attribBase(extending = enumBase(tree.pos, sym), baseEnv,
 739                                   true, false, false)
 740                 : (sym.fullname == names.java_lang_Object)
 741                 ? Type.noType
 742                 : sym.isRecord()
 743                 ? attr.attribBase(extending = recordBase(tree.pos, sym), baseEnv,
 744                                   true, false, false)
 745                 : syms.objectType;
 746             }
 747             ct.supertype_field = modelMissingTypes(baseEnv, supertype, extending, false);
 748 
 749             // Determine interfaces.
 750             ListBuffer<Type> interfaces = new ListBuffer<>();
 751             ListBuffer<Type> all_interfaces = null; // lazy init
 752             List<JCExpression> interfaceTrees = tree.implementing;
 753             for (JCExpression iface : interfaceTrees) {
 754                 iface = clearTypeParams(iface);
 755                 Type it = attr.attribBase(iface, baseEnv, false, true, true);
 756                 if (it.hasTag(CLASS)) {
 757                     interfaces.append(it);
 758                     if (all_interfaces != null) all_interfaces.append(it);
 759                 } else {
 760                     if (all_interfaces == null)
 761                         all_interfaces = new ListBuffer<Type>().appendList(interfaces);
 762                     all_interfaces.append(modelMissingTypes(baseEnv, it, iface, true));
 763                 }
 764             }
 765 
 766             if ((sym.flags_field & ANNOTATION) != 0) {
 767                 ct.interfaces_field = List.of(syms.annotationType);
 768                 ct.all_interfaces_field = ct.interfaces_field;
 769             }  else {
 770                 ct.interfaces_field = interfaces.toList();
 771                 ct.all_interfaces_field = (all_interfaces == null)
 772                         ? ct.interfaces_field : all_interfaces.toList();
 773             }
 774         }
 775             //where:
 776             protected JCExpression clearTypeParams(JCExpression superType) {
 777                 return superType;
 778             }
 779     }
 780 
 781     private final class HierarchyPhase extends AbstractHeaderPhase implements Completer {
 782 
 783         public HierarchyPhase() {
 784             super(CompletionCause.HIERARCHY_PHASE, new HeaderPhase());
 785         }
 786 
 787         @Override
 788         protected void doCompleteEnvs(List<Env<AttrContext>> envs) {
 789             //The ClassSymbols in the envs list may not be in the dependency order.
 790             //To get proper results, for every class or interface C, the supertypes of
 791             //C must be processed by the HierarchyPhase phase before C.
 792             //To achieve that, the HierarchyPhase is registered as the Completer for
 793             //all the classes first, and then all the classes are completed.
 794             for (Env<AttrContext> env : envs) {
 795                 env.enclClass.sym.completer = this;
 796             }
 797             for (Env<AttrContext> env : envs) {
 798                 env.enclClass.sym.complete();
 799             }
 800         }
 801 
 802         @Override
 803         protected void runPhase(Env<AttrContext> env) {
 804             JCClassDecl tree = env.enclClass;
 805             ClassSymbol sym = tree.sym;
 806             ClassType ct = (ClassType)sym.type;
 807 
 808             Env<AttrContext> baseEnv = baseEnv(tree, env);
 809 
 810             attribSuperTypes(env, baseEnv);
 811 
 812             if (sym.fullname == names.java_lang_Object) {
 813                 if (tree.extending != null) {
 814                     chk.checkNonCyclic(tree.extending.pos(),
 815                                        ct.supertype_field);
 816                     ct.supertype_field = Type.noType;
 817                 }
 818                 else if (tree.implementing.nonEmpty()) {
 819                     chk.checkNonCyclic(tree.implementing.head.pos(),
 820                                        ct.interfaces_field.head);
 821                     ct.interfaces_field = List.nil();
 822                 }
 823             }
 824 
 825             markDeprecated(sym, tree.mods.annotations, baseEnv);
 826 
 827             chk.checkNonCyclicDecl(tree);
 828         }
 829             //where:
 830             @Override
 831             protected JCExpression clearTypeParams(JCExpression superType) {
 832                 switch (superType.getTag()) {
 833                     case TYPEAPPLY:
 834                         return ((JCTypeApply) superType).clazz;
 835                 }
 836 
 837                 return superType;
 838             }
 839 
 840         @Override
 841         public void complete(Symbol sym) throws CompletionFailure {
 842             Assert.check((topLevelPhase instanceof ImportsPhase) ||
 843                          (topLevelPhase == this));
 844 
 845             if (topLevelPhase != this) {
 846                 //only do the processing based on dependencies in the HierarchyPhase:
 847                 sym.completer = this;
 848                 return ;
 849             }
 850 
 851             Env<AttrContext> env = typeEnvs.get((ClassSymbol) sym);
 852 
 853             super.doCompleteEnvs(List.of(env));
 854         }
 855 
 856     }
 857 
 858     private final class HeaderPhase extends AbstractHeaderPhase {
 859 
 860         public HeaderPhase() {
 861             super(CompletionCause.HEADER_PHASE, new RecordPhase());
 862         }
 863 
 864         @Override
 865         protected void runPhase(Env<AttrContext> env) {
 866             JCClassDecl tree = env.enclClass;
 867             ClassSymbol sym = tree.sym;
 868             ClassType ct = (ClassType)sym.type;
 869 
 870             // create an environment for evaluating the base clauses
 871             Env<AttrContext> baseEnv = baseEnv(tree, env);
 872 
 873             if (tree.extending != null)
 874                 annotate.queueScanTreeAndTypeAnnotate(tree.extending, baseEnv, sym, tree.pos());
 875             for (JCExpression impl : tree.implementing)
 876                 annotate.queueScanTreeAndTypeAnnotate(impl, baseEnv, sym, tree.pos());
 877             annotate.flush();
 878 
 879             attribSuperTypes(env, baseEnv);
 880 
 881             fillPermits(tree, baseEnv);
 882 
 883             Set<Symbol> interfaceSet = new HashSet<>();
 884 
 885             for (JCExpression iface : tree.implementing) {
 886                 Type it = iface.type;
 887                 if (it.hasTag(CLASS))
 888                     chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
 889             }
 890 
 891             annotate.annotateLater(tree.mods.annotations, baseEnv,
 892                         sym, tree.pos());
 893             attr.attribTypeVariables(tree.typarams, baseEnv, false);
 894 
 895             for (JCTypeParameter tp : tree.typarams)
 896                 annotate.queueScanTreeAndTypeAnnotate(tp, baseEnv, sym, tree.pos());
 897 
 898             // check that no package exists with same fully qualified name,
 899             // but admit classes in the unnamed package which have the same
 900             // name as a top-level package.
 901             if (checkClash &&
 902                 sym.owner.kind == PCK && sym.owner != env.toplevel.modle.unnamedPackage &&
 903                 syms.packageExists(env.toplevel.modle, sym.fullname)) {
 904                 log.error(tree.pos, Errors.ClashWithPkgOfSameName(Kinds.kindName(sym),sym));
 905             }
 906             if (sym.owner.kind == PCK && (sym.flags_field & PUBLIC) == 0 &&
 907                 !env.toplevel.sourcefile.isNameCompatible(sym.name.toString(),JavaFileObject.Kind.SOURCE)) {
 908                 sym.flags_field |= AUXILIARY;
 909             }
 910         }
 911 
 912         private void fillPermits(JCClassDecl tree, Env<AttrContext> baseEnv) {
 913             ClassSymbol sym = tree.sym;
 914 
 915             //fill in implicit permits in supertypes:
 916             if (!sym.isAnonymous() || sym.isEnum()) {
 917                 for (Type supertype : types.directSupertypes(sym.type)) {
 918                     if (supertype.tsym.kind == TYP) {
 919                         ClassSymbol supClass = (ClassSymbol) supertype.tsym;
 920                         Env<AttrContext> supClassEnv = enter.getEnv(supClass);
 921                         if (supClass.isSealed() &&
 922                             !supClass.isPermittedExplicit &&
 923                             supClassEnv != null &&
 924                             supClassEnv.toplevel == baseEnv.toplevel) {
 925                             supClass.permitted = supClass.permitted.append(sym);
 926                         }
 927                     }
 928                 }
 929             }
 930             // attribute (explicit) permits of the current class:
 931             if (sym.isPermittedExplicit) {
 932                 ListBuffer<Symbol> permittedSubtypeSymbols = new ListBuffer<>();
 933                 List<JCExpression> permittedTrees = tree.permitting;
 934                 for (JCExpression permitted : permittedTrees) {
 935                     Type pt = attr.attribBase(permitted, baseEnv, false, false, false);
 936                     permittedSubtypeSymbols.append(pt.tsym);
 937                 }
 938                 sym.permitted = permittedSubtypeSymbols.toList();
 939             }
 940         }
 941     }
 942 
 943     private abstract class AbstractMembersPhase extends Phase {
 944 
 945         public AbstractMembersPhase(CompletionCause completionCause, Phase next) {
 946             super(completionCause, next);
 947         }
 948 
 949         private boolean completing;
 950         private List<Env<AttrContext>> todo = List.nil();
 951 
 952         @Override
 953         protected void doCompleteEnvs(List<Env<AttrContext>> envs) {
 954             todo = todo.prependList(envs);
 955             if (completing) {
 956                 return ; //the top-level invocation will handle all envs
 957             }
 958             boolean prevCompleting = completing;
 959             completing = true;
 960             try {
 961                 while (todo.nonEmpty()) {
 962                     Env<AttrContext> head = todo.head;
 963                     todo = todo.tail;
 964                     super.doCompleteEnvs(List.of(head));
 965                 }
 966             } finally {
 967                 completing = prevCompleting;
 968             }
 969         }
 970 
 971         void enterThisAndSuper(ClassSymbol sym, Env<AttrContext> env) {
 972             ClassType ct = (ClassType)sym.type;
 973             // enter symbols for 'this' into current scope.
 974             VarSymbol thisSym =
 975                     new VarSymbol(FINAL | HASINIT, names._this, sym.type, sym);
 976             thisSym.pos = Position.FIRSTPOS;
 977             env.info.scope.enter(thisSym);
 978             // if this is a class, enter symbol for 'super' into current scope.
 979             if ((sym.flags_field & INTERFACE) == 0 &&
 980                     ct.supertype_field.hasTag(CLASS)) {
 981                 VarSymbol superSym =
 982                         new VarSymbol(FINAL | HASINIT, names._super,
 983                                 ct.supertype_field, sym);
 984                 superSym.pos = Position.FIRSTPOS;
 985                 env.info.scope.enter(superSym);
 986             }
 987         }
 988     }
 989 
 990     private final class RecordPhase extends AbstractMembersPhase {
 991 
 992         public RecordPhase() {
 993             super(CompletionCause.RECORD_PHASE, new MembersPhase());
 994         }
 995 
 996         @Override
 997         protected void runPhase(Env<AttrContext> env) {
 998             JCClassDecl tree = env.enclClass;
 999             ClassSymbol sym = tree.sym;
1000             if ((sym.flags_field & RECORD) != 0) {
1001                 List<JCVariableDecl> fields = TreeInfo.recordFields(tree);
1002 
1003                 for (JCVariableDecl field : fields) {
1004                     /** Some notes regarding the code below. Annotations applied to elements of a record header are propagated
1005                      *  to other elements which, when applicable, not explicitly declared by the user: the canonical constructor,
1006                      *  accessors, fields and record components. Of all these the only ones that can't be explicitly declared are
1007                      *  the fields and the record components.
1008                      *
1009                      *  Now given that annotations are propagated to all possible targets  regardless of applicability,
1010                      *  annotations not applicable to a given element should be removed. See Check::validateAnnotation. Once
1011                      *  annotations are removed we could lose the whole picture, that's why original annotations are stored in
1012                      *  the record component, see RecordComponent::originalAnnos, but there is no real AST representing a record
1013                      *  component so if there is an annotation processing round it could be that we need to reenter a record for
1014                      *  which we need to re-attribute its annotations. This is why one of the things the code below is doing is
1015                      *  copying the original annotations from the record component to the corresponding field, again this applies
1016                      *  only if APs are present.
1017                      *
1018                      *  First, we find the record component by comparing its name and position with current field,
1019                      *  if any, and we mark it. Then we copy the annotations to the field so that annotations applicable only to the record component
1020                      *  can be attributed, as if declared in the field, and then stored in the metadata associated to the record
1021                      *  component. The invariance we need to keep here is that record components must be scheduled for
1022                      *  annotation only once during this process.
1023                      */
1024                     RecordComponent rc = sym.findRecordComponentToRemove(field);
1025 
1026                     if (rc != null && (rc.getOriginalAnnos().length() != field.mods.annotations.length())) {
1027                         TreeCopier<JCTree> tc = new TreeCopier<>(make.at(field.pos));
1028                         List<JCAnnotation> originalAnnos = tc.copy(rc.getOriginalAnnos());
1029                         field.mods.annotations = originalAnnos;
1030                     }
1031 
1032                     memberEnter.memberEnter(field, env);
1033 
1034                     JCVariableDecl rcDecl = new TreeCopier<JCTree>(make.at(field.pos)).copy(field);
1035                     sym.createRecordComponent(rc, rcDecl, field.sym);
1036                 }
1037 
1038                 enterThisAndSuper(sym, env);
1039 
1040                 // lets enter all constructors
1041                 for (JCTree def : tree.defs) {
1042                     if (TreeInfo.isConstructor(def)) {
1043                         memberEnter.memberEnter(def, env);
1044                     }
1045                 }
1046             }
1047         }
1048     }
1049 
1050     /** Enter member fields and methods of a class
1051      */
1052     private final class MembersPhase extends AbstractMembersPhase {
1053 
1054         public MembersPhase() {
1055             super(CompletionCause.MEMBERS_PHASE, null);
1056         }
1057 
1058         @Override
1059         protected void runPhase(Env<AttrContext> env) {
1060             JCClassDecl tree = env.enclClass;
1061             ClassSymbol sym = tree.sym;
1062             ClassType ct = (ClassType)sym.type;
1063 
1064             JCTree defaultConstructor = null;
1065 
1066             // Add default constructor if needed.
1067             DefaultConstructorHelper helper = getDefaultConstructorHelper(env);
1068             if (helper != null) {
1069                 chk.checkDefaultConstructor(sym, tree.pos());
1070                 defaultConstructor = defaultConstructor(make.at(tree.pos), helper);
1071                 tree.defs = tree.defs.prepend(defaultConstructor);
1072             }
1073             if (!sym.isRecord()) {
1074                 enterThisAndSuper(sym, env);
1075             }
1076 
1077             if (!tree.typarams.isEmpty()) {
1078                 for (JCTypeParameter tvar : tree.typarams) {
1079                     chk.checkNonCyclic(tvar, (TypeVar)tvar.type);
1080                 }
1081             }
1082 
1083             finishClass(tree, defaultConstructor, env);
1084 
1085             typeAnnotations.organizeTypeAnnotationsSignatures(env, (JCClassDecl)env.tree);
1086             typeAnnotations.validateTypeAnnotationsSignatures(env, (JCClassDecl)env.tree);
1087         }
1088 
1089         DefaultConstructorHelper getDefaultConstructorHelper(Env<AttrContext> env) {
1090             JCClassDecl tree = env.enclClass;
1091             ClassSymbol sym = tree.sym;
1092             DefaultConstructorHelper helper = null;
1093             boolean isClassWithoutInit = (sym.flags() & INTERFACE) == 0 && !TreeInfo.hasConstructors(tree.defs);
1094             boolean isRecord = sym.isRecord();
1095             if (isClassWithoutInit && !isRecord) {
1096                 helper = new BasicConstructorHelper(sym);
1097                 if (sym.name.isEmpty()) {
1098                     JCNewClass nc = (JCNewClass)env.next.tree;
1099                     if (nc.constructor != null) {
1100                         if (nc.constructor.kind != ERR) {
1101                             helper = new AnonClassConstructorHelper(sym, (MethodSymbol)nc.constructor, nc.encl);
1102                         } else {
1103                             helper = null;
1104                         }
1105                     }
1106                 }
1107             }
1108             if (isRecord) {
1109                 JCMethodDecl canonicalInit = null;
1110                 if (isClassWithoutInit || (canonicalInit = getCanonicalConstructorDecl(env.enclClass)) == null) {
1111                     helper = new RecordConstructorHelper(sym, TreeInfo.recordFields(tree));
1112                 }
1113                 if (canonicalInit != null) {
1114                     canonicalInit.sym.flags_field |= Flags.RECORD;
1115                 }
1116             }
1117             return helper;
1118         }
1119 
1120         /** Enter members for a class.
1121          */
1122         void finishClass(JCClassDecl tree, JCTree defaultConstructor, Env<AttrContext> env) {
1123             if ((tree.mods.flags & Flags.ENUM) != 0 &&
1124                 !tree.sym.type.hasTag(ERROR) &&
1125                 (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) {
1126                 addEnumMembers(tree, env);
1127             }
1128             boolean isRecord = (tree.sym.flags_field & RECORD) != 0;
1129             List<JCTree> alreadyEntered = null;
1130             if (isRecord) {
1131                 alreadyEntered = List.convert(JCTree.class, TreeInfo.recordFields(tree));
1132                 alreadyEntered = alreadyEntered.prependList(tree.defs.stream()
1133                         .filter(t -> TreeInfo.isConstructor(t) && t != defaultConstructor).collect(List.collector()));
1134             }
1135             List<JCTree> defsToEnter = isRecord ?
1136                     tree.defs.diff(alreadyEntered) : tree.defs;
1137             memberEnter.memberEnter(defsToEnter, env);
1138             if (isRecord) {
1139                 addRecordMembersIfNeeded(tree, env);
1140             }
1141             if (tree.sym.isAnnotationType()) {
1142                 Assert.check(tree.sym.isCompleted());
1143                 tree.sym.setAnnotationTypeMetadata(new AnnotationTypeMetadata(tree.sym, annotate.annotationTypeSourceCompleter()));
1144             }
1145 
1146             if (tree.sym != syms.objectType.tsym && tree.sym != syms.recordType.tsym) {
1147                 if ((tree.sym.flags() & (ABSTRACT | INTERFACE | VALUE_CLASS)) == 0) {
1148                     tree.sym.flags_field |= IDENTITY_TYPE;
1149                 }
1150                 if ((tree.sym.flags() & (ABSTRACT | IDENTITY_TYPE | INTERFACE)) == ABSTRACT) {
1151                     if (abstractClassHasImplicitIdentity(tree)) {
1152                         tree.sym.flags_field |= IDENTITY_TYPE;
1153                     }
1154                 }
1155             }
1156         }
1157 
1158             // where
1159             private boolean abstractClassHasImplicitIdentity(JCClassDecl tree) {
1160 
1161                 Type t = tree.sym.type;
1162 
1163                 if (t == null || t.tsym == null || t.tsym.kind == ERR)
1164                     return false;
1165 
1166                 if ((t.tsym.flags() & HASINITBLOCK) != 0) {
1167                     return true;
1168                 }
1169 
1170                 // No instance fields and no arged constructors both mean inner classes cannot be value class supers.
1171                 Type encl = t.getEnclosingType();
1172                 if (encl != null && encl.hasTag(CLASS)) {
1173                     return true;
1174                 }
1175                 for (Symbol s : t.tsym.members().getSymbols(NON_RECURSIVE)) {
1176                     switch (s.kind) {
1177                         case VAR:
1178                             if ((s.flags() & STATIC) == 0) {
1179                                 return true;
1180                             }
1181                             break;
1182                         case MTH:
1183                             if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
1184                                 return true;
1185                             } else if (s.isInitOrVNew()) {
1186                                 MethodSymbol m = (MethodSymbol)s;
1187                                 if (m.getParameters().size() > 0
1188                                         || m.getTypeParameters().size() > 0
1189                                         || m.type.getThrownTypes().nonEmpty()
1190                                         || (m.flags() & EMPTYNOARGCONSTR) == 0
1191                                         || (Check.protection(m.flags()) > Check.protection(m.owner.flags()))) {
1192                                     return true;
1193                                 }
1194                             }
1195                             break;
1196                     }
1197                 }
1198                 return false;
1199             }
1200 
1201 
1202         private void addAccessor(JCVariableDecl tree, Env<AttrContext> env) {
1203             MethodSymbol implSym = lookupMethod(env.enclClass.sym, tree.sym.name, List.nil());
1204             RecordComponent rec = ((ClassSymbol) tree.sym.owner).getRecordComponent(tree.sym);
1205             if (implSym == null || (implSym.flags_field & GENERATED_MEMBER) != 0) {
1206                 /* here we are pushing the annotations present in the corresponding field down to the accessor
1207                  * it could be that some of those annotations are not applicable to the accessor, they will be striped
1208                  * away later at Check::validateAnnotation
1209                  */
1210                 TreeCopier<JCTree> tc = new TreeCopier<JCTree>(make.at(tree.pos));
1211                 List<JCAnnotation> originalAnnos = rec.getOriginalAnnos().isEmpty() ?
1212                         rec.getOriginalAnnos() :
1213                         tc.copy(rec.getOriginalAnnos());
1214                 JCVariableDecl recordField = TreeInfo.recordFields((JCClassDecl) env.tree).stream().filter(rf -> rf.name == tree.name).findAny().get();
1215                 JCMethodDecl getter = make.at(tree.pos).
1216                         MethodDef(
1217                                 make.Modifiers(PUBLIC | Flags.GENERATED_MEMBER, originalAnnos),
1218                           tree.sym.name,
1219                           /* we need to special case for the case when the user declared the type as an ident
1220                            * if we don't do that then we can have issues if type annotations are applied to the
1221                            * return type: javac issues an error if a type annotation is applied to java.lang.String
1222                            * but applying a type annotation to String is kosher
1223                            */
1224                           tc.copy(recordField.vartype),
1225                           List.nil(),
1226                           List.nil(),
1227                           List.nil(), // thrown
1228                           null,
1229                           null);
1230                 memberEnter.memberEnter(getter, env);
1231                 rec.accessor = getter.sym;
1232                 rec.accessorMeth = getter;
1233             } else if (implSym != null) {
1234                 rec.accessor = implSym;
1235             }
1236         }
1237 
1238         /** Add the implicit members for an enum type
1239          *  to the symbol table.
1240          */
1241         private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) {
1242             JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass));
1243 
1244             JCMethodDecl values = make.
1245                 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
1246                           names.values,
1247                           valuesType,
1248                           List.nil(),
1249                           List.nil(),
1250                           List.nil(),
1251                           null,
1252                           null);
1253             memberEnter.memberEnter(values, env);
1254 
1255             JCMethodDecl valueOf = make.
1256                 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
1257                           names.valueOf,
1258                           make.Type(tree.sym.type),
1259                           List.nil(),
1260                           List.of(make.VarDef(make.Modifiers(Flags.PARAMETER |
1261                                                              Flags.MANDATED),
1262                                                 names.fromString("name"),
1263                                                 make.Type(syms.stringType), null)),
1264                           List.nil(),
1265                           null,
1266                           null);
1267             memberEnter.memberEnter(valueOf, env);
1268         }
1269 
1270         JCMethodDecl getCanonicalConstructorDecl(JCClassDecl tree) {
1271             // let's check if there is a constructor with exactly the same arguments as the record components
1272             List<Type> recordComponentErasedTypes = types.erasure(TreeInfo.recordFields(tree).map(vd -> vd.sym.type));
1273             JCMethodDecl canonicalDecl = null;
1274             for (JCTree def : tree.defs) {
1275                 if (TreeInfo.isConstructor(def)) {
1276                     JCMethodDecl mdecl = (JCMethodDecl)def;
1277                     if (types.isSameTypes(types.erasure(mdecl.params.stream().map(v -> v.sym.type).collect(List.collector())), recordComponentErasedTypes)) {
1278                         canonicalDecl = mdecl;
1279                         break;
1280                     }
1281                 }
1282             }
1283             return canonicalDecl;
1284         }
1285 
1286         /** Add the implicit members for a record
1287          *  to the symbol table.
1288          */
1289         private void addRecordMembersIfNeeded(JCClassDecl tree, Env<AttrContext> env) {
1290             if (lookupMethod(tree.sym, names.toString, List.nil()) == null) {
1291                 JCMethodDecl toString = make.
1292                     MethodDef(make.Modifiers(Flags.PUBLIC | Flags.RECORD | Flags.FINAL | Flags.GENERATED_MEMBER),
1293                               names.toString,
1294                               make.Type(syms.stringType),
1295                               List.nil(),
1296                               List.nil(),
1297                               List.nil(),
1298                               null,
1299                               null);
1300                 memberEnter.memberEnter(toString, env);
1301             }
1302 
1303             if (lookupMethod(tree.sym, names.hashCode, List.nil()) == null) {
1304                 JCMethodDecl hashCode = make.
1305                     MethodDef(make.Modifiers(Flags.PUBLIC | Flags.RECORD | Flags.FINAL | Flags.GENERATED_MEMBER),
1306                               names.hashCode,
1307                               make.Type(syms.intType),
1308                               List.nil(),
1309                               List.nil(),
1310                               List.nil(),
1311                               null,
1312                               null);
1313                 memberEnter.memberEnter(hashCode, env);
1314             }
1315 
1316             if (lookupMethod(tree.sym, names.equals, List.of(syms.objectType)) == null) {
1317                 JCMethodDecl equals = make.
1318                     MethodDef(make.Modifiers(Flags.PUBLIC | Flags.RECORD | Flags.FINAL | Flags.GENERATED_MEMBER),
1319                               names.equals,
1320                               make.Type(syms.booleanType),
1321                               List.nil(),
1322                               List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
1323                                                 names.fromString("o"),
1324                                                 make.Type(syms.objectType), null)),
1325                               List.nil(),
1326                               null,
1327                               null);
1328                 memberEnter.memberEnter(equals, env);
1329             }
1330 
1331             // fields can't be varargs, lets remove the flag
1332             List<JCVariableDecl> recordFields = TreeInfo.recordFields(tree);
1333             for (JCVariableDecl field: recordFields) {
1334                 field.mods.flags &= ~Flags.VARARGS;
1335                 field.sym.flags_field &= ~Flags.VARARGS;
1336             }
1337             // now lets add the accessors
1338             recordFields.stream()
1339                     .filter(vd -> (lookupMethod(syms.objectType.tsym, vd.name, List.nil()) == null))
1340                     .forEach(vd -> addAccessor(vd, env));
1341         }
1342     }
1343 
1344     private MethodSymbol lookupMethod(TypeSymbol tsym, Name name, List<Type> argtypes) {
1345         for (Symbol s : tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) {
1346             if (types.isSameTypes(s.type.getParameterTypes(), argtypes)) {
1347                 return (MethodSymbol) s;
1348             }
1349         }
1350         return null;
1351     }
1352 
1353 /* ***************************************************************************
1354  * tree building
1355  ****************************************************************************/
1356 
1357     interface DefaultConstructorHelper {
1358        Type constructorType();
1359        MethodSymbol constructorSymbol();
1360        Type enclosingType();
1361        TypeSymbol owner();
1362        List<Name> superArgs();
1363        default JCMethodDecl finalAdjustment(JCMethodDecl md) { return md; }
1364     }
1365 
1366     class BasicConstructorHelper implements DefaultConstructorHelper {
1367 
1368         TypeSymbol owner;
1369         Type constructorType;
1370         MethodSymbol constructorSymbol;
1371 
1372         BasicConstructorHelper(TypeSymbol owner) {
1373             this.owner = owner;
1374         }
1375 
1376         @Override
1377         public Type constructorType() {
1378             if (constructorType == null) {
1379                 constructorType = new MethodType(List.nil(), syms.voidType, List.nil(), syms.methodClass);
1380             }
1381             return constructorType;
1382         }
1383 
1384         @Override
1385         public MethodSymbol constructorSymbol() {
1386             if (constructorSymbol == null) {
1387                 long flags;
1388                 if ((owner().flags() & ENUM) != 0 &&
1389                     (types.supertype(owner().type).tsym == syms.enumSym)) {
1390                     // constructors of true enums are private
1391                     flags = PRIVATE | GENERATEDCONSTR;
1392                 } else {
1393                     flags = (owner().flags() & AccessFlags) | GENERATEDCONSTR;
1394                 }
1395                 Name constructorName = owner().isConcreteValueClass() ? names.vnew : names.init;
1396                 constructorSymbol = new MethodSymbol(flags, constructorName,
1397                     constructorType(), owner());
1398             }
1399             return constructorSymbol;
1400         }
1401 
1402         @Override
1403         public Type enclosingType() {
1404             return Type.noType;
1405     }
1406 
1407         @Override
1408         public TypeSymbol owner() {
1409             return owner;
1410         }
1411 
1412         @Override
1413         public List<Name> superArgs() {
1414             return List.nil();
1415             }
1416     }
1417 
1418     class AnonClassConstructorHelper extends BasicConstructorHelper {
1419 
1420         MethodSymbol constr;
1421         Type encl;
1422         boolean based = false;
1423 
1424         AnonClassConstructorHelper(TypeSymbol owner, MethodSymbol constr, JCExpression encl) {
1425             super(owner);
1426             this.constr = constr;
1427             this.encl = encl != null ? encl.type : Type.noType;
1428         }
1429 
1430         @Override
1431         public Type constructorType() {
1432             if (constructorType == null) {
1433                 Type ctype = types.memberType(owner.type, constr);
1434                 if (!enclosingType().hasTag(NONE)) {
1435                     ctype = types.createMethodTypeWithParameters(ctype, ctype.getParameterTypes().prepend(enclosingType()));
1436                     based = true;
1437                 }
1438                 constructorType = ctype;
1439             }
1440             return constructorType;
1441         }
1442 
1443         @Override
1444         public MethodSymbol constructorSymbol() {
1445             MethodSymbol csym = super.constructorSymbol();
1446             csym.flags_field |= ANONCONSTR | (constr.flags() & VARARGS);
1447             csym.flags_field |= based ? ANONCONSTR_BASED : 0;
1448             ListBuffer<VarSymbol> params = new ListBuffer<>();
1449             List<Type> argtypes = constructorType().getParameterTypes();
1450             if (!enclosingType().hasTag(NONE)) {
1451                 argtypes = argtypes.tail;
1452                 params = params.prepend(new VarSymbol(PARAMETER, make.paramName(0), enclosingType(), csym));
1453             }
1454             if (constr.params != null) {
1455                 for (VarSymbol p : constr.params) {
1456                     params.add(new VarSymbol(PARAMETER | p.flags(), p.name, argtypes.head, csym));
1457                     argtypes = argtypes.tail;
1458                 }
1459             }
1460             csym.params = params.toList();
1461             return csym;
1462         }
1463 
1464         @Override
1465         public Type enclosingType() {
1466             return encl;
1467         }
1468 
1469         @Override
1470         public List<Name> superArgs() {
1471             List<JCVariableDecl> params = make.Params(constructorSymbol());
1472             if (!enclosingType().hasTag(NONE)) {
1473                 params = params.tail;
1474             }
1475             return params.map(vd -> vd.name);
1476         }
1477     }
1478 
1479     class RecordConstructorHelper extends BasicConstructorHelper {
1480         boolean lastIsVarargs;
1481         List<JCVariableDecl> recordFieldDecls;
1482 
1483         RecordConstructorHelper(ClassSymbol owner, List<JCVariableDecl> recordFieldDecls) {
1484             super(owner);
1485             this.recordFieldDecls = recordFieldDecls;
1486             this.lastIsVarargs = owner.getRecordComponents().stream().anyMatch(rc -> rc.isVarargs());
1487         }
1488 
1489         @Override
1490         public Type constructorType() {
1491             if (constructorType == null) {
1492                 ListBuffer<Type> argtypes = new ListBuffer<>();
1493                 JCVariableDecl lastField = recordFieldDecls.last();
1494                 for (JCVariableDecl field : recordFieldDecls) {
1495                     argtypes.add(field == lastField && lastIsVarargs ? types.elemtype(field.sym.type) : field.sym.type);
1496                 }
1497 
1498                 constructorType = new MethodType(argtypes.toList(), syms.voidType, List.nil(), syms.methodClass);
1499             }
1500             return constructorType;
1501         }
1502 
1503         @Override
1504         public MethodSymbol constructorSymbol() {
1505             MethodSymbol csym = super.constructorSymbol();
1506             /* if we have to generate a default constructor for records we will treat it as the compact one
1507              * to trigger field initialization later on
1508              */
1509             csym.flags_field |= GENERATEDCONSTR;
1510             ListBuffer<VarSymbol> params = new ListBuffer<>();
1511             JCVariableDecl lastField = recordFieldDecls.last();
1512             for (JCVariableDecl field : recordFieldDecls) {
1513                 params.add(new VarSymbol(
1514                         GENERATED_MEMBER | PARAMETER | RECORD | (field == lastField && lastIsVarargs ? Flags.VARARGS : 0),
1515                         field.name, field.sym.type, csym));
1516             }
1517             csym.params = params.toList();
1518             csym.flags_field |= RECORD;
1519             return csym;
1520         }
1521 
1522         @Override
1523         public JCMethodDecl finalAdjustment(JCMethodDecl md) {
1524             List<JCVariableDecl> tmpRecordFieldDecls = recordFieldDecls;
1525             for (JCVariableDecl arg : md.params) {
1526                 /* at this point we are passing all the annotations in the field to the corresponding
1527                  * parameter in the constructor.
1528                  */
1529                 RecordComponent rc = ((ClassSymbol) owner).getRecordComponent(arg.sym);
1530                 TreeCopier<JCTree> tc = new TreeCopier<JCTree>(make.at(arg.pos));
1531                 arg.mods.annotations = rc.getOriginalAnnos().isEmpty() ?
1532                         List.nil() :
1533                         tc.copy(rc.getOriginalAnnos());
1534                 arg.vartype = tc.copy(tmpRecordFieldDecls.head.vartype);
1535                 tmpRecordFieldDecls = tmpRecordFieldDecls.tail;
1536             }
1537             return md;
1538         }
1539     }
1540 
1541     JCTree defaultConstructor(TreeMaker make, DefaultConstructorHelper helper) {
1542         Type initType = helper.constructorType();
1543         MethodSymbol initSym = helper.constructorSymbol();
1544         ListBuffer<JCStatement> stats = new ListBuffer<>();
1545         if (helper.owner().type != syms.objectType) {
1546             JCExpression meth;
1547             if (!helper.enclosingType().hasTag(NONE)) {
1548                 meth = make.Select(make.Ident(initSym.params.head), names._super);
1549             } else {
1550                 meth = make.Ident(names._super);
1551             }
1552             List<JCExpression> typeargs = initType.getTypeArguments().nonEmpty() ?
1553                     make.Types(initType.getTypeArguments()) : null;
1554             JCStatement superCall = make.Exec(make.Apply(typeargs, meth, helper.superArgs().map(make::Ident)));
1555             stats.add(superCall);
1556         }
1557         JCMethodDecl result = make.MethodDef(initSym, make.Block(0, stats.toList()));
1558         return helper.finalAdjustment(result);
1559     }
1560 
1561     /**
1562      * Mark sym deprecated if annotations contain @Deprecated annotation.
1563      */
1564     public void markDeprecated(Symbol sym, List<JCAnnotation> annotations, Env<AttrContext> env) {
1565         // In general, we cannot fully process annotations yet,  but we
1566         // can attribute the annotation types and then check to see if the
1567         // @Deprecated annotation is present.
1568         attr.attribAnnotationTypes(annotations, env);
1569         handleDeprecatedAnnotations(annotations, sym);
1570     }
1571 
1572     /**
1573      * If a list of annotations contains a reference to java.lang.Deprecated,
1574      * set the DEPRECATED flag.
1575      * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
1576      **/
1577     private void handleDeprecatedAnnotations(List<JCAnnotation> annotations, Symbol sym) {
1578         for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
1579             JCAnnotation a = al.head;
1580             if (a.annotationType.type == syms.deprecatedType) {
1581                 sym.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
1582                 setFlagIfAttributeTrue(a, sym, names.forRemoval, DEPRECATED_REMOVAL);
1583             } else if (a.annotationType.type == syms.previewFeatureType) {
1584                 sym.flags_field |= Flags.PREVIEW_API;
1585                 setFlagIfAttributeTrue(a, sym, names.reflective, Flags.PREVIEW_REFLECTIVE);
1586             }
1587         }
1588     }
1589     //where:
1590         private void setFlagIfAttributeTrue(JCAnnotation a, Symbol sym, Name attribute, long flag) {
1591             a.args.stream()
1592                     .filter(e -> e.hasTag(ASSIGN))
1593                     .map(e -> (JCAssign) e)
1594                     .filter(assign -> TreeInfo.name(assign.lhs) == attribute)
1595                     .findFirst()
1596                     .ifPresent(assign -> {
1597                         JCExpression rhs = TreeInfo.skipParens(assign.rhs);
1598                         if (rhs.hasTag(LITERAL)
1599                                 && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
1600                             sym.flags_field |= flag;
1601                         }
1602                     });
1603         }
1604 }