src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
author Dusan Balek <dbalek@netbeans.org>
Fri, 01 Sep 2017 15:28:56 +0200
changeset 5961 740e1ee04027
parent 5754 17c07ac3d164
child 5963 9cc61f487a6d
permissions -rw-r--r--
Issue #270308 - NullPointerException at com.sun.tools.javac.comp.Annotate.getAnnotationArrayValue - fixed.
duke@0
     1
/*
vromero@5655
     2
 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
duke@0
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0
     4
 *
duke@0
     5
 * This code is free software; you can redistribute it and/or modify it
duke@0
     6
 * under the terms of the GNU General Public License version 2 only, as
ohair@961
     7
 * published by the Free Software Foundation.  Oracle designates this
duke@0
     8
 * particular file as subject to the "Classpath" exception as provided
ohair@961
     9
 * by Oracle in the LICENSE file that accompanied this code.
duke@0
    10
 *
duke@0
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
duke@0
    14
 * version 2 for more details (a copy is included in the LICENSE file that
duke@0
    15
 * accompanied this code).
duke@0
    16
 *
duke@0
    17
 * You should have received a copy of the GNU General Public License version
duke@0
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0
    20
 *
ohair@961
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@961
    22
 * or visit www.oracle.com if you need additional information or have any
ohair@961
    23
 * questions.
duke@0
    24
 */
duke@0
    25
duke@0
    26
package com.sun.tools.javac.comp;
duke@0
    27
jjg@4454
    28
import com.sun.tools.javac.code.*;
jjg@4454
    29
import com.sun.tools.javac.code.Attribute.Compound;
jjg@4454
    30
import com.sun.tools.javac.code.Attribute.TypeCompound;
jjg@4454
    31
import com.sun.tools.javac.code.Scope.WriteableScope;
jjg@4454
    32
import com.sun.tools.javac.code.Symbol.*;
jjg@4454
    33
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
alundblad@4460
    34
import com.sun.tools.javac.resources.CompilerProperties.Errors;
jjg@4454
    35
import com.sun.tools.javac.tree.JCTree;
jjg@4454
    36
import com.sun.tools.javac.tree.JCTree.*;
jjg@4454
    37
import com.sun.tools.javac.tree.TreeInfo;
jjg@4454
    38
import com.sun.tools.javac.tree.TreeMaker;
jjg@4454
    39
import com.sun.tools.javac.tree.TreeScanner;
jjg@4454
    40
import com.sun.tools.javac.util.*;
jjg@4454
    41
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
jjg@4454
    42
import com.sun.tools.javac.util.List;
jjg@2372
    43
emc@3879
    44
import javax.tools.JavaFileObject;
jjg@4454
    45
import java.util.*;
emc@3879
    46
jjg@4454
    47
import static com.sun.tools.javac.code.Flags.SYNTHETIC;
alanb@5550
    48
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
jjg@4454
    49
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
vromero@5655
    50
import static com.sun.tools.javac.code.Kinds.Kind.PCK;
jjg@4454
    51
import static com.sun.tools.javac.code.Kinds.Kind.VAR;
jjg@4454
    52
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
jjg@2213
    53
import static com.sun.tools.javac.code.TypeTag.ARRAY;
jjg@2213
    54
import static com.sun.tools.javac.code.TypeTag.CLASS;
jjg@4454
    55
import static com.sun.tools.javac.tree.JCTree.Tag.ANNOTATION;
jjg@4454
    56
import static com.sun.tools.javac.tree.JCTree.Tag.ASSIGN;
jjg@4454
    57
import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
jjg@4454
    58
import static com.sun.tools.javac.tree.JCTree.Tag.NEWARRAY;
jlahoda@5330
    59
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
jjg@1972
    60
jjg@4454
    61
/** Enter annotations onto symbols and types (and trees).
jjg@4454
    62
 *
jjg@4454
    63
 *  This is also a pseudo stage in the compiler taking care of scheduling when annotations are
jjg@4454
    64
 *  entered.
duke@0
    65
 *
jjg@971
    66
 *  <p><b>This is NOT part of any supported API.
jjg@971
    67
 *  If you write code that depends on this, you do so at your own risk.
duke@0
    68
 *  This code and its internal interfaces are subject to change or
duke@0
    69
 *  deletion without notice.</b>
duke@0
    70
 */
duke@0
    71
public class Annotate {
briangoetz@3808
    72
    protected static final Context.Key<Annotate> annotateKey = new Context.Key<>();
duke@0
    73
duke@0
    74
    public static Annotate instance(Context context) {
duke@0
    75
        Annotate instance = context.get(annotateKey);
duke@0
    76
        if (instance == null)
duke@0
    77
            instance = new Annotate(context);
duke@0
    78
        return instance;
duke@0
    79
    }
duke@0
    80
emc@3879
    81
    private final Attr attr;
jjg@4454
    82
    private final Check chk;
jjg@4454
    83
    private final ConstFold cfolder;
jjg@4454
    84
    private final DeferredLintHandler deferredLintHandler;
jjg@4454
    85
    private final Enter enter;
jjg@4454
    86
    private final Lint lint;
jjg@4454
    87
    private final Log log;
jjg@4454
    88
    private final Names names;
jjg@4454
    89
    private final Resolve resolve;
emc@3879
    90
    private final TreeMaker make;
emc@3879
    91
    private final Symtab syms;
jjg@4454
    92
    private final TypeEnvs typeEnvs;
emc@3879
    93
    private final Types types;
emc@3879
    94
jjg@4454
    95
    private final Attribute theUnfinishedDefaultValue;
jjg@4454
    96
    private final boolean allowRepeatedAnnos;
dlsmith@5396
    97
    private final String sourceName;
duke@0
    98
duke@0
    99
    protected Annotate(Context context) {
duke@0
   100
        context.put(annotateKey, this);
jjg@4454
   101
duke@0
   102
        attr = Attr.instance(context);
jjg@4454
   103
        chk = Check.instance(context);
jjg@4454
   104
        cfolder = ConstFold.instance(context);
jjg@4454
   105
        deferredLintHandler = DeferredLintHandler.instance(context);
jjg@4454
   106
        enter = Enter.instance(context);
jjg@4454
   107
        log = Log.instance(context);
jjg@4454
   108
        lint = Lint.instance(context);
duke@0
   109
        make = TreeMaker.instance(context);
jjg@4454
   110
        names = Names.instance(context);
jjg@4454
   111
        resolve = Resolve.instance(context);
duke@0
   112
        syms = Symtab.instance(context);
jjg@4454
   113
        typeEnvs = TypeEnvs.instance(context);
duke@0
   114
        types = Types.instance(context);
jjg@4454
   115
jjg@4454
   116
        theUnfinishedDefaultValue =  new Attribute.Error(syms.errType);
jjg@4454
   117
jjg@4454
   118
        Source source = Source.instance(context);
emc@3879
   119
        allowRepeatedAnnos = source.allowRepeatedAnnotations();
dlsmith@5396
   120
        sourceName = source.name;
jlahoda@5675
   121
jlahoda@5675
   122
        blockCount = 1;
duke@0
   123
    }
duke@0
   124
jjg@4454
   125
    /** Semaphore to delay annotation processing */
jjg@4454
   126
    private int blockCount = 0;
duke@0
   127
jjg@4454
   128
    /** Called when annotations processing needs to be postponed. */
jjg@4454
   129
    public void blockAnnotations() {
jjg@4454
   130
        blockCount++;
jjg@2372
   131
    }
duke@0
   132
jjg@4454
   133
    /** Called when annotation processing can be resumed. */
jjg@4454
   134
    public void unblockAnnotations() {
jjg@4454
   135
        blockCount--;
jjg@4454
   136
        if (blockCount == 0)
jjg@4454
   137
            flush();
duke@0
   138
    }
duke@0
   139
emc@3160
   140
    /** Variant which allows for a delayed flush of annotations.
emc@3160
   141
     * Needed by ClassReader */
jjg@4454
   142
    public void unblockAnnotationsNoFlush() {
jjg@4454
   143
        blockCount--;
emc@3160
   144
    }
emc@3160
   145
jjg@4454
   146
    /** are we blocking annotation processing? */
jjg@4454
   147
    public boolean annotationsBlocked() {return blockCount > 0; }
jjg@4454
   148
jlahoda@5675
   149
    public void enterDone() {
jlahoda@5675
   150
        unblockAnnotations();
jlahoda@5675
   151
    }
jlahoda@5675
   152
jjg@4454
   153
    public List<TypeCompound> fromAnnotations(List<JCAnnotation> annotations) {
jjg@4454
   154
        if (annotations.isEmpty()) {
jjg@4454
   155
            return List.nil();
jjg@4454
   156
        }
jjg@4454
   157
jjg@4454
   158
        ListBuffer<TypeCompound> buf = new ListBuffer<>();
jjg@4454
   159
        for (JCAnnotation anno : annotations) {
jjg@4454
   160
            Assert.checkNonNull(anno.attribute);
jjg@4454
   161
            buf.append((TypeCompound) anno.attribute);
jjg@4454
   162
        }
jjg@4454
   163
        return buf.toList();
jjg@4454
   164
    }
jjg@4454
   165
jjg@4454
   166
    /** Annotate (used for everything else) */
jjg@4454
   167
    public void normal(Runnable r) {
jjg@4454
   168
        q.append(r);
jjg@4454
   169
    }
jjg@4454
   170
jjg@4454
   171
    /** Validate, triggers after 'normal' */
jjg@4454
   172
    public void validate(Runnable a) {
jjg@4454
   173
        validateQ.append(a);
jjg@4454
   174
    }
jjg@4454
   175
jjg@4454
   176
    /** Flush all annotation queues */
duke@0
   177
    public void flush() {
jjg@4454
   178
        if (annotationsBlocked()) return;
jjg@4454
   179
        if (isFlushing()) return;
jjg@4454
   180
jjg@4454
   181
        startFlushing();
duke@0
   182
        try {
jjg@2372
   183
            while (q.nonEmpty()) {
jlahoda@3157
   184
                q.next().run();
jjg@2372
   185
            }
jjg@2372
   186
            while (typesQ.nonEmpty()) {
jlahoda@3157
   187
                typesQ.next().run();
jjg@2372
   188
            }
jjg@4454
   189
            while (afterTypesQ.nonEmpty()) {
jjg@4454
   190
                afterTypesQ.next().run();
jjg@2372
   191
            }
jlahoda@3135
   192
            while (validateQ.nonEmpty()) {
jlahoda@3157
   193
                validateQ.next().run();
jlahoda@3135
   194
            }
duke@0
   195
        } finally {
jjg@4454
   196
            doneFlushing();
duke@0
   197
        }
duke@0
   198
    }
duke@0
   199
jjg@4454
   200
    private ListBuffer<Runnable> q = new ListBuffer<>();
jjg@4454
   201
    private ListBuffer<Runnable> validateQ = new ListBuffer<>();
jjg@4454
   202
jjg@4454
   203
    private int flushCount = 0;
dbalek@5618
   204
    public boolean isFlushing() { return flushCount > 0; }
jjg@4454
   205
    private void startFlushing() { flushCount++; }
jjg@4454
   206
    private void doneFlushing() { flushCount--; }
jjg@4454
   207
jjg@4454
   208
    ListBuffer<Runnable> typesQ = new ListBuffer<>();
jjg@4454
   209
    ListBuffer<Runnable> afterTypesQ = new ListBuffer<>();
jjg@4454
   210
jjg@4454
   211
jjg@4454
   212
    public void typeAnnotation(Runnable a) {
jjg@4454
   213
        typesQ.append(a);
jjg@4454
   214
    }
jjg@4454
   215
jjg@4454
   216
    public void afterTypes(Runnable a) {
jjg@4454
   217
        afterTypesQ.append(a);
duke@0
   218
    }
duke@0
   219
jfranck@2156
   220
    /**
jjg@4454
   221
     * Queue annotations for later attribution and entering. This is probably the method you are looking for.
jjg@4454
   222
     *
jjg@4454
   223
     * @param annotations the list of JCAnnotations to attribute and enter
jjg@4454
   224
     * @param localEnv    the enclosing env
jjg@4454
   225
     * @param s           ths Symbol on which to enter the annotations
jjg@4454
   226
     * @param deferPos    report errors here
jjg@4454
   227
     */
jjg@4454
   228
    public void annotateLater(List<JCAnnotation> annotations, Env<AttrContext> localEnv,
jjg@4454
   229
            Symbol s, DiagnosticPosition deferPos)
jjg@4454
   230
    {
jjg@4454
   231
        if (annotations.isEmpty()) {
jjg@4454
   232
            return;
jjg@4454
   233
        }
jjg@4454
   234
jjg@4454
   235
        s.resetAnnotations(); // mark Annotations as incomplete for now
jjg@4454
   236
alundblad@4902
   237
        normal(() -> {
vromero@5655
   238
            // Packages are unusual, in that they are the only type of declaration that can legally appear
vromero@5655
   239
            // more than once in a compilation, and in all cases refer to the same underlying symbol.
vromero@5655
   240
            // This means they are the only kind of declaration that syntactically may have multiple sets
vromero@5655
   241
            // of annotations, each on a different package declaration, even though that is ultimately
vromero@5655
   242
            // forbidden by JLS 8 section 7.4.
vromero@5655
   243
            // The corollary here is that all of the annotations on a package symbol may have already
vromero@5655
   244
            // been handled, meaning that the set of annotations pending completion is now empty.
vromero@5655
   245
            Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
alundblad@4902
   246
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
alundblad@4902
   247
            DiagnosticPosition prevLintPos =
alundblad@4902
   248
                    deferPos != null
alundblad@4902
   249
                            ? deferredLintHandler.setPos(deferPos)
alundblad@4902
   250
                            : deferredLintHandler.immediate();
alundblad@4902
   251
            Lint prevLint = deferPos != null ? null : chk.setLint(lint);
alundblad@4902
   252
            try {
alundblad@4902
   253
                if (s.hasAnnotations() && annotations.nonEmpty())
alundblad@4902
   254
                    log.error(annotations.head.pos, "already.annotated", Kinds.kindName(s), s);
jjg@4454
   255
alundblad@4902
   256
                Assert.checkNonNull(s, "Symbol argument to actualEnterAnnotations is null");
jjg@4454
   257
alundblad@4902
   258
                // false is passed as fifth parameter since annotateLater is
alundblad@4902
   259
                // never called for a type parameter
alundblad@4902
   260
                annotateNow(s, annotations, localEnv, false, false);
alundblad@4902
   261
            } finally {
alundblad@4902
   262
                if (prevLint != null)
alundblad@4902
   263
                    chk.setLint(prevLint);
alundblad@4902
   264
                deferredLintHandler.setPos(prevLintPos);
alundblad@4902
   265
                log.useSource(prev);
jjg@4454
   266
            }
jjg@4454
   267
        });
jjg@4454
   268
alundblad@4902
   269
        validate(() -> { //validate annotations
alundblad@4902
   270
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
alundblad@4902
   271
            try {
alundblad@4902
   272
                chk.validateAnnotations(annotations, s);
alundblad@4902
   273
            } finally {
alundblad@4902
   274
                log.useSource(prev);
jjg@4454
   275
            }
jjg@4454
   276
        });
jjg@4454
   277
    }
jjg@4454
   278
jjg@4454
   279
jjg@4454
   280
    /** Queue processing of an attribute default value. */
jjg@4454
   281
    public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv,
jjg@4454
   282
            MethodSymbol m, DiagnosticPosition deferPos)
jjg@4454
   283
    {
alundblad@4902
   284
        normal(() -> {
alundblad@4902
   285
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
alundblad@4902
   286
            DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos);
alundblad@4902
   287
            try {
alundblad@4902
   288
                enterDefaultValue(defaultValue, localEnv, m);
alundblad@4902
   289
            } finally {
alundblad@4902
   290
                deferredLintHandler.setPos(prevLintPos);
alundblad@4902
   291
                log.useSource(prev);
jjg@4454
   292
            }
jjg@4454
   293
        });
jjg@4454
   294
alundblad@4902
   295
        validate(() -> { //validate annotations
alundblad@4902
   296
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
alundblad@4902
   297
            try {
alundblad@4902
   298
                // if default value is an annotation, check it is a well-formed
alundblad@4902
   299
                // annotation value (e.g. no duplicate values, no missing values, etc.)
alundblad@4902
   300
                chk.validateAnnotationTree(defaultValue);
alundblad@4902
   301
            } finally {
alundblad@4902
   302
                log.useSource(prev);
jjg@4454
   303
            }
jjg@4454
   304
        });
jjg@4454
   305
    }
jjg@4454
   306
jjg@4454
   307
    /** Enter a default value for an annotation element. */
jjg@4454
   308
    private void enterDefaultValue(JCExpression defaultValue,
jjg@4454
   309
            Env<AttrContext> localEnv, MethodSymbol m) {
jjg@4454
   310
        m.defaultValue = attributeAnnotationValue(m.type.getReturnType(), defaultValue, localEnv);
jjg@4454
   311
    }
jjg@4454
   312
jjg@4454
   313
    /**
jjg@4454
   314
     * Gather up annotations into a map from type symbols to lists of Compound attributes,
jjg@4454
   315
     * then continue on with repeating annotations processing.
jjg@4454
   316
     */
jjg@4454
   317
    private <T extends Attribute.Compound> void annotateNow(Symbol toAnnotate,
alundblad@4477
   318
            List<JCAnnotation> withAnnotations, Env<AttrContext> env, boolean typeAnnotations,
alundblad@4477
   319
            boolean isTypeParam)
jjg@4454
   320
    {
jjg@4454
   321
        Map<TypeSymbol, ListBuffer<T>> annotated = new LinkedHashMap<>();
jjg@4454
   322
        Map<T, DiagnosticPosition> pos = new HashMap<>();
jjg@4454
   323
jjg@4454
   324
        for (List<JCAnnotation> al = withAnnotations; !al.isEmpty(); al = al.tail) {
jjg@4454
   325
            JCAnnotation a = al.head;
jjg@4454
   326
jjg@4454
   327
            T c;
jjg@4454
   328
            if (typeAnnotations) {
jjg@4454
   329
                @SuppressWarnings("unchecked")
jjg@4454
   330
                T tmp = (T)attributeTypeAnnotation(a, syms.annotationType, env);
jjg@4454
   331
                c = tmp;
jjg@4454
   332
            } else {
jjg@4454
   333
                @SuppressWarnings("unchecked")
jjg@4454
   334
                T tmp = (T)attributeAnnotation(a, syms.annotationType, env);
jjg@4454
   335
                c = tmp;
jjg@4454
   336
            }
jjg@4454
   337
jjg@4454
   338
            Assert.checkNonNull(c, "Failed to create annotation");
jjg@4454
   339
jjg@4454
   340
            if (annotated.containsKey(a.type.tsym)) {
jjg@4454
   341
                if (!allowRepeatedAnnos) {
dlsmith@5396
   342
                    log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), "repeatable.annotations.not.supported.in.source", sourceName);
jjg@4454
   343
                }
jjg@4454
   344
                ListBuffer<T> l = annotated.get(a.type.tsym);
jjg@4454
   345
                l = l.append(c);
jjg@4454
   346
                annotated.put(a.type.tsym, l);
jjg@4454
   347
                pos.put(c, a.pos());
jjg@4454
   348
            } else {
jjg@4454
   349
                annotated.put(a.type.tsym, ListBuffer.of(c));
jjg@4454
   350
                pos.put(c, a.pos());
jjg@4454
   351
            }
jjg@4454
   352
jjg@4454
   353
            // Note: @Deprecated has no effect on local variables and parameters
jjg@4454
   354
            if (!c.type.isErroneous()
alanb@5550
   355
                    && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
jjg@4454
   356
                    && types.isSameType(c.type, syms.deprecatedType)) {
alanb@5550
   357
                toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
jjg@5468
   358
                Attribute fr = c.member(names.forRemoval);
jjg@5468
   359
                if (fr instanceof Attribute.Constant) {
jjg@5468
   360
                    Attribute.Constant v = (Attribute.Constant) fr;
jjg@5468
   361
                    if (v.type == syms.booleanType && ((Integer) v.value) != 0) {
jjg@5468
   362
                        toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
jjg@5468
   363
                    }
jjg@5468
   364
                }
jjg@4454
   365
            }
jjg@4454
   366
        }
jjg@4454
   367
jjg@4454
   368
        List<T> buf = List.nil();
jjg@4454
   369
        for (ListBuffer<T> lb : annotated.values()) {
jjg@4454
   370
            if (lb.size() == 1) {
jjg@4454
   371
                buf = buf.prepend(lb.first());
jjg@4454
   372
            } else {
jjg@4454
   373
                AnnotationContext<T> ctx = new AnnotationContext<>(env, annotated, pos, typeAnnotations);
alundblad@4477
   374
                T res = makeContainerAnnotation(lb.toList(), ctx, toAnnotate, isTypeParam);
jjg@4454
   375
                if (res != null)
jjg@4454
   376
                    buf = buf.prepend(res);
jjg@4454
   377
            }
jjg@4454
   378
        }
jjg@4454
   379
jjg@4454
   380
        if (typeAnnotations) {
jjg@4454
   381
            @SuppressWarnings("unchecked")
jjg@4454
   382
            List<TypeCompound> attrs = (List<TypeCompound>)buf.reverse();
jjg@4454
   383
            toAnnotate.appendUniqueTypeAttributes(attrs);
jjg@4454
   384
        } else {
jjg@4454
   385
            @SuppressWarnings("unchecked")
jjg@4454
   386
            List<Attribute.Compound> attrs =  (List<Attribute.Compound>)buf.reverse();
jjg@4454
   387
            toAnnotate.resetAnnotations();
jjg@4454
   388
            toAnnotate.setDeclarationAttributes(attrs);
jjg@4454
   389
        }
jjg@4454
   390
    }
jjg@4454
   391
jjg@4454
   392
    /**
jjg@4454
   393
     * Attribute and store a semantic representation of the annotation tree {@code tree} into the
jjg@4454
   394
     * tree.attribute field.
jjg@4454
   395
     *
jjg@4454
   396
     * @param tree the tree representing an annotation
jjg@4454
   397
     * @param expectedAnnotationType the expected (super)type of the annotation
jjg@4454
   398
     * @param env the current env in where the annotation instance is found
jjg@4454
   399
     */
jjg@4454
   400
    public Attribute.Compound attributeAnnotation(JCAnnotation tree, Type expectedAnnotationType,
jjg@4454
   401
                                                  Env<AttrContext> env)
jjg@4454
   402
    {
jjg@4454
   403
        // The attribute might have been entered if it is Target or Repetable
jjg@4454
   404
        // Because TreeCopier does not copy type, redo this if type is null
jjg@4454
   405
        if (tree.attribute != null && tree.type != null)
jjg@4454
   406
            return tree.attribute;
jjg@4454
   407
jjg@4454
   408
        List<Pair<MethodSymbol, Attribute>> elems = attributeAnnotationValues(tree, expectedAnnotationType, env);
jjg@4454
   409
        Attribute.Compound ac = new Attribute.Compound(tree.type, elems);
jjg@4454
   410
jjg@4454
   411
        return tree.attribute = ac;
jjg@4454
   412
    }
jjg@4454
   413
jjg@4454
   414
    /** Attribute and store a semantic representation of the type annotation tree {@code tree} into
jjg@4454
   415
     * the tree.attribute field.
jjg@4454
   416
     *
jjg@4454
   417
     * @param a the tree representing an annotation
jjg@4454
   418
     * @param expectedAnnotationType the expected (super)type of the annotation
jjg@4454
   419
     * @param env the the current env in where the annotation instance is found
jjg@4454
   420
     */
jjg@4454
   421
    public Attribute.TypeCompound attributeTypeAnnotation(JCAnnotation a, Type expectedAnnotationType,
jjg@4454
   422
                                                          Env<AttrContext> env)
jjg@4454
   423
    {
jjg@4454
   424
        // The attribute might have been entered if it is Target or Repetable
jjg@4454
   425
        // Because TreeCopier does not copy type, redo this if type is null
jjg@4454
   426
        if (a.attribute == null || a.type == null || !(a.attribute instanceof Attribute.TypeCompound)) {
jjg@4454
   427
            // Create a new TypeCompound
jjg@4454
   428
            List<Pair<MethodSymbol,Attribute>> elems =
jjg@4454
   429
                    attributeAnnotationValues(a, expectedAnnotationType, env);
jjg@4454
   430
jjg@4454
   431
            Attribute.TypeCompound tc =
jjg@4454
   432
                    new Attribute.TypeCompound(a.type, elems, TypeAnnotationPosition.unknown);
jjg@4454
   433
            a.attribute = tc;
jjg@4454
   434
            return tc;
jjg@4454
   435
        } else {
jjg@4454
   436
            // Use an existing TypeCompound
jjg@4454
   437
            return (Attribute.TypeCompound)a.attribute;
jjg@4454
   438
        }
jjg@4454
   439
    }
jjg@4454
   440
jjg@4454
   441
    /**
jjg@4454
   442
     *  Attribute annotation elements creating a list of pairs of the Symbol representing that
jjg@4454
   443
     *  element and the value of that element as an Attribute. */
jjg@4454
   444
    private List<Pair<MethodSymbol, Attribute>> attributeAnnotationValues(JCAnnotation a,
jjg@4454
   445
            Type expected, Env<AttrContext> env)
jjg@4454
   446
    {
jjg@4454
   447
        // The annotation might have had its type attributed (but not
jjg@4454
   448
        // checked) by attr.attribAnnotationTypes during MemberEnter,
jjg@4454
   449
        // in which case we do not need to do it again.
jjg@4454
   450
        Type at = (a.annotationType.type != null ?
jjg@4454
   451
                a.annotationType.type : attr.attribType(a.annotationType, env));
jjg@4454
   452
        a.type = chk.checkType(a.annotationType.pos(), at, expected);
jjg@4454
   453
jjg@4454
   454
        boolean isError = a.type.isErroneous();
jjg@4454
   455
        if (!a.type.tsym.isAnnotationType() && !isError) {
jjg@4454
   456
            log.error(a.annotationType.pos(),
jjg@4454
   457
                    "not.annotation.type", a.type.toString());
jjg@4454
   458
            isError = true;
jjg@4454
   459
        }
jjg@4454
   460
jjg@4454
   461
        // List of name=value pairs (or implicit "value=" if size 1)
jjg@4454
   462
        List<JCExpression> args = a.args;
jjg@4454
   463
jjg@4454
   464
        boolean elidedValue = false;
jjg@4454
   465
        // special case: elided "value=" assumed
jjg@4454
   466
        if (args.length() == 1 && !args.head.hasTag(ASSIGN)) {
dbalek@4733
   467
            args.head = make.at(Position.NOPOS).
jjg@4454
   468
                    Assign(make.Ident(names.value), args.head);
jjg@4454
   469
            elidedValue = true;
jjg@4454
   470
        }
jjg@4454
   471
jjg@4454
   472
        ListBuffer<Pair<MethodSymbol,Attribute>> buf = new ListBuffer<>();
jjg@4454
   473
        for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
jjg@4454
   474
            Pair<MethodSymbol, Attribute> p = attributeAnnotationNameValuePair(tl.head, a.type, isError, env, elidedValue);
jjg@4454
   475
            if (p != null && !p.fst.type.isErroneous())
jjg@4454
   476
                buf.append(p);
jjg@4454
   477
        }
jjg@4454
   478
        return buf.toList();
jjg@4454
   479
    }
jjg@4454
   480
jjg@4454
   481
    // where
jjg@4454
   482
    private Pair<MethodSymbol, Attribute> attributeAnnotationNameValuePair(JCExpression nameValuePair,
jjg@4454
   483
            Type thisAnnotationType, boolean badAnnotation, Env<AttrContext> env, boolean elidedValue)
jjg@4454
   484
    {
jjg@4454
   485
        if (!nameValuePair.hasTag(ASSIGN)) {
jjg@4454
   486
            log.error(nameValuePair.pos(), "annotation.value.must.be.name.value");
jjg@4454
   487
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
jjg@4454
   488
            return null;
jjg@4454
   489
        }
jjg@4454
   490
        JCAssign assign = (JCAssign)nameValuePair;
jjg@4454
   491
        if (!assign.lhs.hasTag(IDENT)) {
jjg@4454
   492
            log.error(nameValuePair.pos(), "annotation.value.must.be.name.value");
jjg@4454
   493
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
jjg@4454
   494
            return null;
jjg@4454
   495
        }
jjg@4454
   496
jjg@4454
   497
        // Resolve element to MethodSym
jjg@4454
   498
        JCIdent left = (JCIdent)assign.lhs;
jjg@4454
   499
        Symbol method = resolve.resolveQualifiedMethod(elidedValue ? assign.rhs.pos() : left.pos(),
jjg@4454
   500
                env, thisAnnotationType,
mcimadamore@5586
   501
                left.name, List.nil(), null);
jjg@4454
   502
        left.sym = method;
jjg@4454
   503
        left.type = method.type;
jjg@4454
   504
        if (method.owner != thisAnnotationType.tsym && !badAnnotation)
jjg@4454
   505
            log.error(left.pos(), "no.annotation.member", left.name, thisAnnotationType);
jjg@4454
   506
        Type resultType = method.type.getReturnType();
jjg@4454
   507
jjg@4454
   508
        // Compute value part
jjg@4454
   509
        Attribute value = attributeAnnotationValue(resultType, assign.rhs, env);
jjg@4454
   510
        nameValuePair.type = resultType;
jjg@4454
   511
jjg@4454
   512
        return method.type.isErroneous() ? null : new Pair<>((MethodSymbol)method, value);
jjg@4454
   513
jjg@4454
   514
    }
jjg@4454
   515
jjg@4454
   516
    /** Attribute an annotation element value */
jjg@4454
   517
    private Attribute attributeAnnotationValue(Type expectedElementType, JCExpression tree,
jjg@4454
   518
            Env<AttrContext> env)
jjg@4454
   519
    {
jjg@4454
   520
        //first, try completing the symbol for the annotation value - if acompletion
jjg@4454
   521
        //error is thrown, we should recover gracefully, and display an
jjg@4454
   522
        //ordinary resolution diagnostic.
jjg@4454
   523
        try {
jjg@4454
   524
            expectedElementType.tsym.complete();
jjg@4454
   525
        } catch(CompletionFailure e) {
jjg@4454
   526
            log.error(tree.pos(), "cant.resolve", Kinds.kindName(e.sym), e.sym);
jjg@4454
   527
            expectedElementType = syms.errType;
jjg@4454
   528
        }
jjg@4454
   529
jjg@4454
   530
        if (expectedElementType.hasTag(ARRAY)) {
jjg@4454
   531
            return getAnnotationArrayValue(expectedElementType, tree, env);
jjg@4454
   532
jjg@4454
   533
        }
jjg@4454
   534
jjg@4454
   535
        //error recovery
jjg@4454
   536
        if (tree.hasTag(NEWARRAY)) {
jjg@4454
   537
            if (!expectedElementType.isErroneous())
jjg@4454
   538
                log.error(tree.pos(), "annotation.value.not.allowable.type");
jjg@4454
   539
            JCNewArray na = (JCNewArray)tree;
jjg@4454
   540
            if (na.elemtype != null) {
jjg@4454
   541
                log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
jjg@4454
   542
            }
jjg@4454
   543
            for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
jjg@4454
   544
                attributeAnnotationValue(syms.errType,
jjg@4454
   545
                        l.head,
jjg@4454
   546
                        env);
jjg@4454
   547
            }
jjg@4454
   548
            return new Attribute.Error(syms.errType);
jjg@4454
   549
        }
jjg@4454
   550
jjg@4454
   551
        if (expectedElementType.tsym.isAnnotationType()) {
jjg@4454
   552
            if (tree.hasTag(ANNOTATION)) {
jjg@4454
   553
                return attributeAnnotation((JCAnnotation)tree, expectedElementType, env);
jjg@4454
   554
            } else {
jjg@4454
   555
                log.error(tree.pos(), "annotation.value.must.be.annotation");
jjg@4454
   556
                expectedElementType = syms.errType;
jjg@4454
   557
            }
jjg@4454
   558
        }
jjg@4454
   559
jjg@4454
   560
        //error recovery
jjg@4454
   561
        if (tree.hasTag(ANNOTATION)) {
jjg@4454
   562
            if (!expectedElementType.isErroneous())
jjg@4454
   563
                log.error(tree.pos(), "annotation.not.valid.for.type", expectedElementType);
jjg@4454
   564
            attributeAnnotation((JCAnnotation)tree, syms.errType, env);
jjg@4454
   565
            return new Attribute.Error(((JCAnnotation)tree).annotationType.type);
jjg@4454
   566
        }
jjg@4454
   567
jjg@4454
   568
        if (expectedElementType.isPrimitive() ||
jjg@4454
   569
                (types.isSameType(expectedElementType, syms.stringType) && !expectedElementType.hasTag(TypeTag.ERROR))) {
jjg@4454
   570
            return getAnnotationPrimitiveValue(expectedElementType, tree, env);
jjg@4454
   571
        }
jjg@4454
   572
jjg@4454
   573
        if (expectedElementType.tsym == syms.classType.tsym) {
jjg@4454
   574
            return getAnnotationClassValue(expectedElementType, tree, env);
jjg@4454
   575
        }
jjg@4454
   576
jjg@4454
   577
        if (expectedElementType.hasTag(CLASS) &&
jjg@4454
   578
                (expectedElementType.tsym.flags() & Flags.ENUM) != 0) {
jjg@4454
   579
            return getAnnotationEnumValue(expectedElementType, tree, env);
jjg@4454
   580
        }
jjg@4454
   581
jjg@4454
   582
        //error recovery:
jjg@4454
   583
        if (!expectedElementType.isErroneous())
jjg@4454
   584
            log.error(tree.pos(), "annotation.value.not.allowable.type");
jjg@4454
   585
        return new Attribute.Error(attr.attribExpr(tree, env, expectedElementType));
jjg@4454
   586
    }
jjg@4454
   587
jjg@4454
   588
    private Attribute getAnnotationEnumValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   589
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   590
        Symbol sym = TreeInfo.symbol(tree);
jjg@4454
   591
        if (sym == null ||
jjg@4454
   592
                TreeInfo.nonstaticSelect(tree) ||
jjg@4454
   593
                sym.kind != VAR ||
jjg@4454
   594
                (sym.flags() & Flags.ENUM) == 0) {
jjg@4454
   595
            log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
jjg@4454
   596
            return new Attribute.Error(result.getOriginalType());
jjg@4454
   597
        }
jjg@4454
   598
        VarSymbol enumerator = (VarSymbol) sym;
jjg@4454
   599
        return new Attribute.Enum(expectedElementType, enumerator);
jjg@4454
   600
    }
jjg@4454
   601
jjg@4454
   602
    private Attribute getAnnotationClassValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   603
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   604
        if (result.isErroneous()) {
jjg@4454
   605
            // Does it look like an unresolved class literal?
jjg@4454
   606
            if (TreeInfo.name(tree) == names._class &&
jjg@4454
   607
                    ((JCFieldAccess) tree).selected.type.isErroneous()) {
jjg@4454
   608
                Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
jjg@4454
   609
                return new Attribute.UnresolvedClass(expectedElementType,
jjg@4454
   610
                        types.createErrorType(n,
jjg@4454
   611
                                syms.unknownSymbol, syms.classType));
jjg@4454
   612
            } else {
jjg@4454
   613
                return new Attribute.Error(result.getOriginalType());
jjg@4454
   614
            }
jjg@4454
   615
        }
jjg@4454
   616
jjg@4454
   617
        // Class literals look like field accesses of a field named class
jjg@4454
   618
        // at the tree level
jjg@4454
   619
        if (TreeInfo.name(tree) != names._class) {
jjg@4454
   620
            log.error(tree.pos(), "annotation.value.must.be.class.literal");
jjg@4454
   621
            return new Attribute.Error(syms.errType);
jjg@4454
   622
        }
jjg@4454
   623
        return new Attribute.Class(types,
jjg@4454
   624
                (((JCFieldAccess) tree).selected).type);
jjg@4454
   625
    }
jjg@4454
   626
jjg@4454
   627
    private Attribute getAnnotationPrimitiveValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   628
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   629
        if (result.isErroneous())
jjg@4454
   630
            return new Attribute.Error(result.getOriginalType());
jjg@4454
   631
        if (result.constValue() == null) {
jjg@4454
   632
            log.error(tree.pos(), "attribute.value.must.be.constant");
jjg@4454
   633
            return new Attribute.Error(expectedElementType);
jjg@4454
   634
        }
jjg@4454
   635
        result = cfolder.coerce(result, expectedElementType);
jjg@4454
   636
        return new Attribute.Constant(expectedElementType, result.constValue());
jjg@4454
   637
    }
jjg@4454
   638
jjg@4454
   639
    private Attribute getAnnotationArrayValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   640
        // Special case, implicit array
jjg@4454
   641
        if (!tree.hasTag(NEWARRAY)) {
jjg@4454
   642
            tree = make.at(tree.pos).
mcimadamore@5586
   643
                    NewArray(null, List.nil(), List.of(tree));
jjg@4454
   644
        }
jjg@4454
   645
jjg@4454
   646
        JCNewArray na = (JCNewArray)tree;
jjg@4454
   647
        if (na.elemtype != null) {
jjg@4454
   648
            log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
jjg@4454
   649
        }
jjg@4454
   650
        ListBuffer<Attribute> buf = new ListBuffer<>();
dbalek@5961
   651
        if (na.elems != null) {
dbalek@5961
   652
            for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
dbalek@5961
   653
                buf.append(attributeAnnotationValue(types.elemtype(expectedElementType),
dbalek@5961
   654
                        l.head,
dbalek@5961
   655
                        env));
dbalek@5961
   656
            }
jjg@4454
   657
        }
jjg@4454
   658
        na.type = expectedElementType;
jjg@4454
   659
        return new Attribute.
jjg@4454
   660
                Array(expectedElementType, buf.toArray(new Attribute[buf.length()]));
jjg@4454
   661
    }
jjg@4454
   662
jjg@4454
   663
    /* *********************************
jjg@4454
   664
     * Support for repeating annotations
jjg@4454
   665
     ***********************************/
jjg@4454
   666
jjg@4454
   667
    /**
jfranck@2156
   668
     * This context contains all the information needed to synthesize new
jjg@4454
   669
     * annotations trees for repeating annotations.
jfranck@2156
   670
     */
emc@3932
   671
    private class AnnotationContext<T extends Attribute.Compound> {
jfranck@2156
   672
        public final Env<AttrContext> env;
jjg@2372
   673
        public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
jjg@2372
   674
        public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
jjg@2372
   675
        public final boolean isTypeCompound;
jfranck@2156
   676
emc@3932
   677
        public AnnotationContext(Env<AttrContext> env,
emc@3932
   678
                                 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
emc@3932
   679
                                 Map<T, JCDiagnostic.DiagnosticPosition> pos,
emc@3932
   680
                                 boolean isTypeCompound) {
jjg@2162
   681
            Assert.checkNonNull(env);
jjg@2162
   682
            Assert.checkNonNull(annotated);
jjg@2162
   683
            Assert.checkNonNull(pos);
jfranck@2156
   684
jfranck@2156
   685
            this.env = env;
jfranck@2156
   686
            this.annotated = annotated;
jfranck@2156
   687
            this.pos = pos;
jjg@2372
   688
            this.isTypeCompound = isTypeCompound;
jfranck@2156
   689
        }
emc@3932
   690
    }
emc@3932
   691
jfranck@2156
   692
    /* Process repeated annotations. This method returns the
jfranck@2156
   693
     * synthesized container annotation or null IFF all repeating
jfranck@2156
   694
     * annotation are invalid.  This method reports errors/warnings.
jfranck@2156
   695
     */
jfranck@4203
   696
    private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
alundblad@4477
   697
            AnnotationContext<T> ctx, Symbol on, boolean isTypeParam)
jjg@4454
   698
    {
jjg@2372
   699
        T firstOccurrence = annotations.head;
jfranck@2156
   700
        List<Attribute> repeated = List.nil();
jfranck@2288
   701
        Type origAnnoType = null;
jfranck@2156
   702
        Type arrayOfOrigAnnoType = null;
jfranck@2156
   703
        Type targetContainerType = null;
jfranck@2156
   704
        MethodSymbol containerValueSymbol = null;
jfranck@2156
   705
jjg@4454
   706
        Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1
jfranck@2156
   707
jfranck@2538
   708
        int count = 0;
jjg@4454
   709
        for (List<T> al = annotations; !al.isEmpty(); al = al.tail) {
jfranck@2538
   710
            count++;
jfranck@4203
   711
jfranck@2538
   712
            // There must be more than a single anno in the annotation list
jfranck@2538
   713
            Assert.check(count > 1 || !al.tail.isEmpty());
jfranck@2538
   714
jjg@2372
   715
            T currentAnno = al.head;
jfranck@2156
   716
jfranck@2156
   717
            origAnnoType = currentAnno.type;
jfranck@2156
   718
            if (arrayOfOrigAnnoType == null) {
jfranck@2156
   719
                arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
jjg@2372
   720
            }
jfranck@2156
   721
jfranck@2538
   722
            // Only report errors if this isn't the first occurrence I.E. count > 1
jfranck@2538
   723
            boolean reportError = count > 1;
jfranck@2538
   724
            Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError);
jfranck@2156
   725
            if (currentContainerType == null) {
jfranck@2156
   726
                continue;
jfranck@2156
   727
            }
jfranck@2156
   728
            // Assert that the target Container is == for all repeated
jfranck@2156
   729
            // annos of the same annotation type, the types should
jfranck@2156
   730
            // come from the same Symbol, i.e. be '=='
jfranck@2156
   731
            Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
jfranck@2156
   732
            targetContainerType = currentContainerType;
jfranck@2156
   733
jfranck@2156
   734
            containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));
jfranck@2156
   735
jfranck@2156
   736
            if (containerValueSymbol == null) { // Check of CA type failed
jfranck@2156
   737
                // errors are already reported
jfranck@2156
   738
                continue;
jfranck@2156
   739
            }
jfranck@2156
   740
jfranck@2156
   741
            repeated = repeated.prepend(currentAnno);
jfranck@2156
   742
        }
jfranck@2156
   743
jjg@4454
   744
        if (!repeated.isEmpty() && targetContainerType == null) {
jjg@4454
   745
            log.error(ctx.pos.get(annotations.head), "duplicate.annotation.invalid.repeated", origAnnoType);
jjg@4454
   746
            return null;
jjg@4454
   747
        }
jjg@4454
   748
jfranck@2156
   749
        if (!repeated.isEmpty()) {
jfranck@2156
   750
            repeated = repeated.reverse();
alundblad@4477
   751
            DiagnosticPosition pos = ctx.pos.get(firstOccurrence);
alundblad@4477
   752
            TreeMaker m = make.at(pos);
jfranck@2156
   753
            Pair<MethodSymbol, Attribute> p =
vromero@3810
   754
                    new Pair<MethodSymbol, Attribute>(containerValueSymbol,
jjg@4454
   755
                            new Attribute.Array(arrayOfOrigAnnoType, repeated));
jjg@2372
   756
            if (ctx.isTypeCompound) {
jfranck@4203
   757
                /* TODO: the following code would be cleaner:
jfranck@4203
   758
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
jfranck@4203
   759
                        ((Attribute.TypeCompound)annotations.head).position);
jfranck@4203
   760
                JCTypeAnnotation annoTree = m.TypeAnnotation(at);
jjg@4454
   761
                at = attributeTypeAnnotation(annoTree, targetContainerType, ctx.env);
jfranck@4203
   762
                */
jfranck@4203
   763
                // However, we directly construct the TypeCompound to keep the
jfranck@4203
   764
                // direct relation to the contained TypeCompounds.
jfranck@4203
   765
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
jfranck@4203
   766
                        ((Attribute.TypeCompound)annotations.head).position);
jfranck@4203
   767
alundblad@4477
   768
                JCAnnotation annoTree = m.TypeAnnotation(at);
alundblad@4477
   769
                if (!chk.validateAnnotationDeferErrors(annoTree))
alundblad@4477
   770
                    log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
alundblad@4477
   771
alundblad@4477
   772
                if (!chk.isTypeAnnotation(annoTree, isTypeParam)) {
alundblad@4477
   773
                    log.error(pos, isTypeParam ? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
alundblad@4477
   774
                                               : Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
alundblad@4477
   775
                }
jfranck@4203
   776
jjg@2372
   777
                at.setSynthesized(true);
jfranck@2288
   778
jjg@2372
   779
                @SuppressWarnings("unchecked")
jjg@2372
   780
                T x = (T) at;
jjg@2372
   781
                return x;
jjg@2372
   782
            } else {
jfranck@4203
   783
                Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
jjg@2372
   784
                JCAnnotation annoTree = m.Annotation(c);
jjg@2372
   785
alundblad@4460
   786
                if (!chk.annotationApplicable(annoTree, on)) {
alundblad@4460
   787
                    log.error(annoTree.pos(),
alundblad@4460
   788
                              Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on));
alundblad@4460
   789
                }
jjg@2372
   790
jjg@2372
   791
                if (!chk.validateAnnotationDeferErrors(annoTree))
jjg@2372
   792
                    log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
jjg@2372
   793
jjg@4454
   794
                c = attributeAnnotation(annoTree, targetContainerType, ctx.env);
jjg@2372
   795
                c.setSynthesized(true);
jjg@2372
   796
jjg@2372
   797
                @SuppressWarnings("unchecked")
jjg@2372
   798
                T x = (T) c;
jjg@2372
   799
                return x;
jjg@2372
   800
            }
jfranck@2156
   801
        } else {
jfranck@2156
   802
            return null; // errors should have been reported elsewhere
jfranck@2156
   803
        }
jfranck@2156
   804
    }
jfranck@2156
   805
jjg@4454
   806
    /**
jjg@4454
   807
     * Fetches the actual Type that should be the containing annotation.
jjg@4454
   808
     */
jfranck@2156
   809
    private Type getContainingType(Attribute.Compound currentAnno,
jjg@4454
   810
                                   DiagnosticPosition pos,
jjg@4454
   811
                                   boolean reportError)
jfranck@2156
   812
    {
jfranck@2156
   813
        Type origAnnoType = currentAnno.type;
jfranck@2156
   814
        TypeSymbol origAnnoDecl = origAnnoType.tsym;
jfranck@2156
   815
jjg@2339
   816
        // Fetch the Repeatable annotation from the current
jfranck@2156
   817
        // annotation's declaration, or null if it has none
jjg@4454
   818
        Attribute.Compound ca = origAnnoDecl.getAnnotationTypeMetadata().getRepeatable();
jjg@2339
   819
        if (ca == null) { // has no Repeatable annotation
jfranck@2538
   820
            if (reportError)
jfranck@2538
   821
                log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType);
jfranck@2156
   822
            return null;
jfranck@2156
   823
        }
jfranck@2156
   824
jfranck@2156
   825
        return filterSame(extractContainingType(ca, pos, origAnnoDecl),
jjg@4454
   826
                origAnnoType);
jfranck@2156
   827
    }
jfranck@2156
   828
jfranck@2156
   829
    // returns null if t is same as 's', returns 't' otherwise
jfranck@2156
   830
    private Type filterSame(Type t, Type s) {
jfranck@2156
   831
        if (t == null || s == null) {
jfranck@2156
   832
            return t;
jfranck@2156
   833
        }
jfranck@2156
   834
jfranck@2156
   835
        return types.isSameType(t, s) ? null : t;
jfranck@2156
   836
    }
jfranck@2156
   837
jfranck@2156
   838
    /** Extract the actual Type to be used for a containing annotation. */
jfranck@2156
   839
    private Type extractContainingType(Attribute.Compound ca,
jjg@4454
   840
                                       DiagnosticPosition pos,
jjg@4454
   841
                                       TypeSymbol annoDecl)
jfranck@2156
   842
    {
jjg@2339
   843
        // The next three checks check that the Repeatable annotation
jfranck@2156
   844
        // on the declaration of the annotation type that is repeating is
jfranck@2156
   845
        // valid.
jfranck@2156
   846
jjg@2339
   847
        // Repeatable must have at least one element
jfranck@2156
   848
        if (ca.values.isEmpty()) {
jjg@2339
   849
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   850
            return null;
jfranck@2156
   851
        }
jfranck@2156
   852
        Pair<MethodSymbol,Attribute> p = ca.values.head;
jfranck@2156
   853
        Name name = p.fst.name;
jfranck@2156
   854
        if (name != names.value) { // should contain only one element, named "value"
jjg@2339
   855
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   856
            return null;
jfranck@2156
   857
        }
jfranck@2156
   858
        if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
jjg@2339
   859
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   860
            return null;
jfranck@2156
   861
        }
jfranck@2156
   862
jfranck@2156
   863
        return ((Attribute.Class)p.snd).getValue();
jfranck@2156
   864
    }
jfranck@2156
   865
jfranck@2156
   866
    /* Validate that the suggested targetContainerType Type is a valid
jfranck@2156
   867
     * container type for repeated instances of originalAnnoType
jfranck@2156
   868
     * annotations. Return null and report errors if this is not the
jfranck@2156
   869
     * case, return the MethodSymbol of the value element in
jfranck@2156
   870
     * targetContainerType if it is suitable (this is needed to
jfranck@2156
   871
     * synthesize the container). */
jfranck@2156
   872
    private MethodSymbol validateContainer(Type targetContainerType,
jfranck@2156
   873
                                           Type originalAnnoType,
jfranck@2156
   874
                                           DiagnosticPosition pos) {
jfranck@2156
   875
        MethodSymbol containerValueSymbol = null;
jfranck@2156
   876
        boolean fatalError = false;
jfranck@2156
   877
jfranck@2156
   878
        // Validate that there is a (and only 1) value method
jfranck@2156
   879
        Scope scope = targetContainerType.tsym.members();
jfranck@2156
   880
        int nr_value_elems = 0;
jfranck@2156
   881
        boolean error = false;
jlahoda@4103
   882
        for(Symbol elm : scope.getSymbolsByName(names.value)) {
jfranck@2156
   883
            nr_value_elems++;
jfranck@2156
   884
jfranck@2156
   885
            if (nr_value_elems == 1 &&
jjg@4454
   886
                    elm.kind == MTH) {
jfranck@2156
   887
                containerValueSymbol = (MethodSymbol)elm;
jfranck@2156
   888
            } else {
jfranck@2156
   889
                error = true;
jfranck@2156
   890
            }
jfranck@2156
   891
        }
jfranck@2156
   892
        if (error) {
jfranck@2156
   893
            log.error(pos,
jjg@4454
   894
                    "invalid.repeatable.annotation.multiple.values",
jjg@4454
   895
                    targetContainerType,
jjg@4454
   896
                    nr_value_elems);
jfranck@2156
   897
            return null;
jfranck@2156
   898
        } else if (nr_value_elems == 0) {
jfranck@2156
   899
            log.error(pos,
jjg@4454
   900
                    "invalid.repeatable.annotation.no.value",
jjg@4454
   901
                    targetContainerType);
jfranck@2156
   902
            return null;
jfranck@2156
   903
        }
jfranck@2156
   904
jfranck@2156
   905
        // validate that the 'value' element is a method
jfranck@2156
   906
        // probably "impossible" to fail this
emc@4248
   907
        if (containerValueSymbol.kind != MTH) {
jfranck@2156
   908
            log.error(pos,
jjg@4454
   909
                    "invalid.repeatable.annotation.invalid.value",
jjg@4454
   910
                    targetContainerType);
jfranck@2156
   911
            fatalError = true;
jfranck@2156
   912
        }
jfranck@2156
   913
jfranck@2156
   914
        // validate that the 'value' element has the correct return type
jfranck@2156
   915
        // i.e. array of original anno
jfranck@2156
   916
        Type valueRetType = containerValueSymbol.type.getReturnType();
jfranck@2156
   917
        Type expectedType = types.makeArrayType(originalAnnoType);
jfranck@2156
   918
        if (!(types.isArray(valueRetType) &&
jjg@4454
   919
                types.isSameType(expectedType, valueRetType))) {
jfranck@2156
   920
            log.error(pos,
jjg@4454
   921
                    "invalid.repeatable.annotation.value.return",
jjg@4454
   922
                    targetContainerType,
jjg@4454
   923
                    valueRetType,
jjg@4454
   924
                    expectedType);
jfranck@2156
   925
            fatalError = true;
jfranck@2156
   926
        }
jfranck@2156
   927
jfranck@2156
   928
        return fatalError ? null : containerValueSymbol;
jfranck@2156
   929
    }
emc@3879
   930
jjg@4454
   931
    private <T extends Attribute.Compound> T makeContainerAnnotation(List<T> toBeReplaced,
alundblad@4477
   932
            AnnotationContext<T> ctx, Symbol sym, boolean isTypeParam)
jjg@4454
   933
    {
emc@3932
   934
        // Process repeated annotations
emc@3932
   935
        T validRepeated =
alundblad@4477
   936
                processRepeatedAnnotations(toBeReplaced, ctx, sym, isTypeParam);
emc@3932
   937
emc@3932
   938
        if (validRepeated != null) {
emc@3932
   939
            // Check that the container isn't manually
emc@3932
   940
            // present along with repeated instances of
emc@3932
   941
            // its contained annotation.
emc@3932
   942
            ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
emc@3932
   943
            if (manualContainer != null) {
jjg@4454
   944
                log.error(ctx.pos.get(manualContainer.first()),
jjg@4454
   945
                        "invalid.repeatable.annotation.repeated.and.container.present",
emc@3932
   946
                        manualContainer.first().type.tsym);
emc@3932
   947
            }
emc@3932
   948
        }
emc@3932
   949
emc@3932
   950
        // A null return will delete the Placeholder
emc@3932
   951
        return validRepeated;
emc@3932
   952
    }
emc@3932
   953
jjg@4454
   954
    /********************
jjg@4454
   955
     * Type annotations *
jjg@4454
   956
     ********************/
emc@3879
   957
jjg@4454
   958
    /**
jjg@4454
   959
     * Attribute the list of annotations and enter them onto s.
emc@3879
   960
     */
jjg@4454
   961
    public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env,
alundblad@4477
   962
            Symbol s, DiagnosticPosition deferPos, boolean isTypeParam)
jjg@4454
   963
    {
jfranck@4203
   964
        Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
emc@3882
   965
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
emc@3882
   966
        DiagnosticPosition prevLintPos = null;
emc@3879
   967
emc@3882
   968
        if (deferPos != null) {
emc@3882
   969
            prevLintPos = deferredLintHandler.setPos(deferPos);
emc@3882
   970
        }
emc@3882
   971
        try {
alundblad@4477
   972
            annotateNow(s, annotations, env, true, isTypeParam);
emc@3882
   973
        } finally {
emc@3882
   974
            if (prevLintPos != null)
emc@3882
   975
                deferredLintHandler.setPos(prevLintPos);
emc@3882
   976
            log.useSource(prev);
emc@3879
   977
        }
emc@3879
   978
    }
emc@3879
   979
jjg@4454
   980
    /**
jjg@4454
   981
     * Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
jjg@4454
   982
     */
jjg@4454
   983
    public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym,
jjg@4454
   984
            DiagnosticPosition deferPos)
jjg@4454
   985
    {
emc@3887
   986
        Assert.checkNonNull(sym);
alundblad@4902
   987
        normal(() -> tree.accept(new TypeAnnotate(env, sym, deferPos)));
jjg@4454
   988
    }
jjg@4454
   989
jjg@4454
   990
    /**
jjg@4454
   991
     * Apply the annotations to the particular type.
jjg@4454
   992
     */
jjg@4454
   993
    public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) {
alundblad@4902
   994
        typeAnnotation(() -> {
alundblad@4902
   995
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
alundblad@4902
   996
            Assert.check(annotations.size() == compounds.size());
alundblad@4902
   997
            storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
jjg@4454
   998
        });
jjg@4454
   999
    }
jjg@4454
  1000
jjg@4454
  1001
    /**
jjg@4454
  1002
     * Apply the annotations to the particular type.
jjg@4454
  1003
     */
jjg@4454
  1004
    public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) {
alundblad@4902
  1005
        typeAnnotation(() -> {
alundblad@4902
  1006
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
alundblad@4902
  1007
            Assert.check(annotations.size() == compounds.size());
jjg@4454
  1008
        });
emc@3879
  1009
    }
emc@3879
  1010
emc@3879
  1011
    /**
jfranck@4203
  1012
     * We need to use a TreeScanner, because it is not enough to visit the top-level
jfranck@4203
  1013
     * annotations. We also need to visit type arguments, etc.
emc@3879
  1014
     */
jfranck@4203
  1015
    private class TypeAnnotate extends TreeScanner {
jfranck@4203
  1016
        private final Env<AttrContext> env;
jfranck@4203
  1017
        private final Symbol sym;
jfranck@4203
  1018
        private DiagnosticPosition deferPos;
emc@3879
  1019
jjg@4454
  1020
        public TypeAnnotate(Env<AttrContext> env, Symbol sym, DiagnosticPosition deferPos) {
jfranck@4203
  1021
jfranck@4203
  1022
            this.env = env;
jfranck@4203
  1023
            this.sym = sym;
jfranck@4203
  1024
            this.deferPos = deferPos;
emc@3879
  1025
        }
emc@3879
  1026
emc@3879
  1027
        @Override
jjg@4454
  1028
        public void visitAnnotatedType(JCAnnotatedType tree) {
alundblad@4477
  1029
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
jjg@4454
  1030
            scan(tree.underlyingType);
emc@3879
  1031
        }
emc@3879
  1032
emc@3879
  1033
        @Override
jjg@4454
  1034
        public void visitTypeParameter(JCTypeParameter tree) {
alundblad@4477
  1035
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, true);
jjg@4454
  1036
            scan(tree.bounds);
emc@3879
  1037
        }
emc@3879
  1038
emc@3879
  1039
        @Override
jjg@4454
  1040
        public void visitNewArray(JCNewArray tree) {
alundblad@4477
  1041
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
jfranck@4203
  1042
            for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
alundblad@4477
  1043
                enterTypeAnnotations(dimAnnos, env, sym, deferPos, false);
jjg@4454
  1044
            scan(tree.elemtype);
jjg@4454
  1045
            scan(tree.elems);
emc@3879
  1046
        }
emc@3879
  1047
emc@3879
  1048
        @Override
jjg@4454
  1049
        public void visitMethodDef(JCMethodDecl tree) {
jfranck@4203
  1050
            scan(tree.mods);
jfranck@4203
  1051
            scan(tree.restype);
jfranck@4203
  1052
            scan(tree.typarams);
jfranck@4203
  1053
            scan(tree.recvparam);
jfranck@4203
  1054
            scan(tree.params);
jfranck@4203
  1055
            scan(tree.thrown);
jfranck@4203
  1056
            scan(tree.defaultValue);
jfranck@4203
  1057
            // Do not annotate the body, just the signature.
emc@3879
  1058
        }
emc@3879
  1059
emc@3879
  1060
        @Override
jjg@4454
  1061
        public void visitVarDef(JCVariableDecl tree) {
jfranck@4203
  1062
            DiagnosticPosition prevPos = deferPos;
jfranck@4203
  1063
            deferPos = tree.pos();
jfranck@4203
  1064
            try {
emc@4248
  1065
                if (sym != null && sym.kind == VAR) {
jfranck@4203
  1066
                    // Don't visit a parameter once when the sym is the method
jfranck@4203
  1067
                    // and once when the sym is the parameter.
jfranck@4203
  1068
                    scan(tree.mods);
jfranck@4203
  1069
                    scan(tree.vartype);
jfranck@4203
  1070
                }
jfranck@4203
  1071
                scan(tree.init);
jfranck@4203
  1072
            } finally {
jfranck@4203
  1073
                deferPos = prevPos;
emc@3879
  1074
            }
emc@3879
  1075
        }
emc@3879
  1076
emc@3879
  1077
        @Override
emc@3879
  1078
        public void visitClassDef(JCClassDecl tree) {
jfranck@4203
  1079
            // We can only hit a classdef if it is declared within
jfranck@4203
  1080
            // a method. Ignore it - the class will be visited
jfranck@4203
  1081
            // separately later.
emc@3879
  1082
        }
emc@3879
  1083
emc@3879
  1084
        @Override
emc@3879
  1085
        public void visitNewClass(JCNewClass tree) {
sadayapalam@4647
  1086
            scan(tree.encl);
sadayapalam@4647
  1087
            scan(tree.typeargs);
sadayapalam@4647
  1088
            scan(tree.clazz);
sadayapalam@4647
  1089
            scan(tree.args);
sadayapalam@4647
  1090
            // the anonymous class instantiation if any will be visited separately.
emc@4248
  1091
        }
dbalek@4731
  1092
dbalek@4731
  1093
        @Override
dbalek@4731
  1094
        public void visitErroneous(JCErroneous tree) {
dbalek@4731
  1095
            scan(tree.errs);
dbalek@4731
  1096
        }
emc@4248
  1097
    }
jjg@4454
  1098
jjg@4454
  1099
    /*********************
jjg@4454
  1100
     * Completer support *
jjg@4454
  1101
     *********************/
jjg@4454
  1102
jjg@4454
  1103
    private AnnotationTypeCompleter theSourceCompleter = new AnnotationTypeCompleter() {
jjg@4454
  1104
        @Override
jjg@4454
  1105
        public void complete(ClassSymbol sym) throws CompletionFailure {
jjg@4454
  1106
            Env<AttrContext> context = typeEnvs.get(sym);
jjg@4454
  1107
            Annotate.this.attributeAnnotationType(context);
jjg@4454
  1108
        }
jjg@4454
  1109
    };
jjg@4454
  1110
jjg@4454
  1111
    /* Last stage completer to enter just enough annotations to have a prototype annotation type.
jjg@4454
  1112
     * This currently means entering @Target and @Repetable.
jjg@4454
  1113
     */
jjg@4454
  1114
    public AnnotationTypeCompleter annotationTypeSourceCompleter() {
jjg@4454
  1115
        return theSourceCompleter;
jjg@4454
  1116
    }
jjg@4454
  1117
jjg@4454
  1118
    private void attributeAnnotationType(Env<AttrContext> env) {
jjg@4454
  1119
        Assert.check(((JCClassDecl)env.tree).sym.isAnnotationType(),
jjg@4454
  1120
                "Trying to annotation type complete a non-annotation type");
jjg@4454
  1121
jjg@4454
  1122
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
jjg@4454
  1123
        try {
jjg@4454
  1124
            JCClassDecl tree = (JCClassDecl)env.tree;
jjg@4454
  1125
            AnnotationTypeVisitor v = new AnnotationTypeVisitor(attr, chk, syms, typeEnvs);
jjg@4454
  1126
            v.scanAnnotationType(tree);
jjg@4454
  1127
            tree.sym.getAnnotationTypeMetadata().setRepeatable(v.repeatable);
jjg@4454
  1128
            tree.sym.getAnnotationTypeMetadata().setTarget(v.target);
jjg@4454
  1129
        } finally {
jjg@4454
  1130
            log.useSource(prev);
jjg@4454
  1131
        }
jjg@4454
  1132
    }
jjg@4454
  1133
jjg@4454
  1134
    public Attribute unfinishedDefaultValue() {
jjg@4454
  1135
        return theUnfinishedDefaultValue;
jjg@4454
  1136
    }
jjg@4454
  1137
jjg@4454
  1138
    public static interface AnnotationTypeCompleter {
jjg@4454
  1139
        void complete(ClassSymbol sym) throws CompletionFailure;
jjg@4454
  1140
    }
jjg@4454
  1141
jjg@4454
  1142
    /** Visitor to determine a prototype annotation type for a class declaring an annotation type.
jjg@4454
  1143
     *
jjg@4454
  1144
     *  <p><b>This is NOT part of any supported API.
jjg@4454
  1145
     *  If you write code that depends on this, you do so at your own risk.
jjg@4454
  1146
     *  This code and its internal interfaces are subject to change or
jjg@4454
  1147
     *  deletion without notice.</b>
jjg@4454
  1148
     */
jjg@4454
  1149
    public class AnnotationTypeVisitor extends TreeScanner {
jjg@4454
  1150
        private Env<AttrContext> env;
jjg@4454
  1151
jjg@4454
  1152
        private final Attr attr;
jjg@4454
  1153
        private final Check check;
jjg@4454
  1154
        private final Symtab tab;
jjg@4454
  1155
        private final TypeEnvs typeEnvs;
jjg@4454
  1156
jjg@4454
  1157
        private Compound target;
jjg@4454
  1158
        private Compound repeatable;
jjg@4454
  1159
jjg@4454
  1160
        public AnnotationTypeVisitor(Attr attr, Check check, Symtab tab, TypeEnvs typeEnvs) {
jjg@4454
  1161
            this.attr = attr;
jjg@4454
  1162
            this.check = check;
jjg@4454
  1163
            this.tab = tab;
jjg@4454
  1164
            this.typeEnvs = typeEnvs;
jjg@4454
  1165
        }
jjg@4454
  1166
jjg@4454
  1167
        public Compound getRepeatable() {
jjg@4454
  1168
            return repeatable;
jjg@4454
  1169
        }
jjg@4454
  1170
jjg@4454
  1171
        public Compound getTarget() {
jjg@4454
  1172
            return target;
jjg@4454
  1173
        }
jjg@4454
  1174
jjg@4454
  1175
        public void scanAnnotationType(JCClassDecl decl) {
jjg@4454
  1176
            visitClassDef(decl);
jjg@4454
  1177
        }
jjg@4454
  1178
jjg@4454
  1179
        @Override
jjg@4454
  1180
        public void visitClassDef(JCClassDecl tree) {
jjg@4454
  1181
            Env<AttrContext> prevEnv = env;
jjg@4454
  1182
            env = typeEnvs.get(tree.sym);
jjg@4454
  1183
            try {
jjg@4454
  1184
                scan(tree.mods); // look for repeatable and target
jjg@4454
  1185
                // don't descend into body
jjg@4454
  1186
            } finally {
jjg@4454
  1187
                env = prevEnv;
jjg@4454
  1188
            }
jjg@4454
  1189
        }
jjg@4454
  1190
jjg@4454
  1191
        @Override
jjg@4454
  1192
        public void visitAnnotation(JCAnnotation tree) {
jjg@4454
  1193
            Type t = tree.annotationType.type;
jjg@4454
  1194
            if (t == null) {
jjg@4454
  1195
                t = attr.attribType(tree.annotationType, env);
jjg@4454
  1196
                tree.annotationType.type = t = check.checkType(tree.annotationType.pos(), t, tab.annotationType);
jjg@4454
  1197
            }
jjg@4454
  1198
jjg@4454
  1199
            if (t == tab.annotationTargetType) {
jjg@4454
  1200
                target = Annotate.this.attributeAnnotation(tree, tab.annotationTargetType, env);
jjg@4454
  1201
            } else if (t == tab.repeatableType) {
jjg@4454
  1202
                repeatable = Annotate.this.attributeAnnotation(tree, tab.repeatableType, env);
emc@3879
  1203
            }
emc@3879
  1204
        }
dbalek@4427
  1205
dbalek@4427
  1206
        @Override
dbalek@4427
  1207
        public void visitErroneous(JCErroneous tree) {
dbalek@4427
  1208
            scan(tree.errs);
dbalek@4427
  1209
        }
emc@3879
  1210
    }
jjg@4454
  1211
jjg@4454
  1212
    /** Represents the semantics of an Annotation Type.
jjg@4454
  1213
     *
jjg@4454
  1214
     *  <p><b>This is NOT part of any supported API.
jjg@4454
  1215
     *  If you write code that depends on this, you do so at your own risk.
jjg@4454
  1216
     *  This code and its internal interfaces are subject to change or
jjg@4454
  1217
     *  deletion without notice.</b>
jjg@4454
  1218
     */
jjg@4454
  1219
    public static class AnnotationTypeMetadata {
jjg@4454
  1220
        final ClassSymbol metaDataFor;
jjg@4454
  1221
        private Compound target;
jjg@4454
  1222
        private Compound repeatable;
jjg@4454
  1223
        private AnnotationTypeCompleter annotationTypeCompleter;
jjg@4454
  1224
jjg@4454
  1225
        public AnnotationTypeMetadata(ClassSymbol metaDataFor, AnnotationTypeCompleter annotationTypeCompleter) {
jjg@4454
  1226
            this.metaDataFor = metaDataFor;
jjg@4454
  1227
            this.annotationTypeCompleter = annotationTypeCompleter;
jjg@4454
  1228
        }
jjg@4454
  1229
jjg@4454
  1230
        private void init() {
jjg@4454
  1231
            // Make sure metaDataFor is member entered
alundblad@4474
  1232
            while (!metaDataFor.isCompleted())
jjg@4454
  1233
                metaDataFor.complete();
jjg@4454
  1234
jjg@4454
  1235
            if (annotationTypeCompleter != null) {
jjg@4454
  1236
                AnnotationTypeCompleter c = annotationTypeCompleter;
jjg@4454
  1237
                annotationTypeCompleter = null;
jjg@4454
  1238
                c.complete(metaDataFor);
jjg@4454
  1239
            }
jjg@4454
  1240
        }
jjg@4454
  1241
jjg@4454
  1242
        public void complete() {
jjg@4454
  1243
            init();
jjg@4454
  1244
        }
jjg@4454
  1245
jjg@4454
  1246
        public Compound getRepeatable() {
jjg@4454
  1247
            init();
jjg@4454
  1248
            return repeatable;
jjg@4454
  1249
        }
jjg@4454
  1250
jjg@4454
  1251
        public void setRepeatable(Compound repeatable) {
jjg@4454
  1252
            Assert.checkNull(this.repeatable);
jjg@4454
  1253
            this.repeatable = repeatable;
jjg@4454
  1254
        }
jjg@4454
  1255
jjg@4454
  1256
        public Compound getTarget() {
jjg@4454
  1257
            init();
jjg@4454
  1258
            return target;
jjg@4454
  1259
        }
jjg@4454
  1260
jjg@4454
  1261
        public void setTarget(Compound target) {
jjg@4454
  1262
            Assert.checkNull(this.target);
jjg@4454
  1263
                this.target = target;
jjg@4454
  1264
        }
jjg@4454
  1265
jjg@4454
  1266
        public Set<MethodSymbol> getAnnotationElements() {
jjg@4454
  1267
            init();
jjg@4454
  1268
            Set<MethodSymbol> members = new LinkedHashSet<>();
jjg@4454
  1269
            WriteableScope s = metaDataFor.members();
jjg@4454
  1270
            Iterable<Symbol> ss = s.getSymbols(NON_RECURSIVE);
jjg@4454
  1271
            for (Symbol sym : ss)
jjg@4454
  1272
                if (sym.kind == MTH &&
jjg@4454
  1273
                        sym.name != sym.name.table.names.clinit &&
jjg@4454
  1274
                        (sym.flags() & SYNTHETIC) == 0)
jjg@4454
  1275
                    members.add((MethodSymbol)sym);
jjg@4454
  1276
            return members;
jjg@4454
  1277
        }
jjg@4454
  1278
jjg@4454
  1279
        public Set<MethodSymbol> getAnnotationElementsWithDefault() {
jjg@4454
  1280
            init();
jjg@4454
  1281
            Set<MethodSymbol> members = getAnnotationElements();
jjg@4454
  1282
            Set<MethodSymbol> res = new LinkedHashSet<>();
jjg@4454
  1283
            for (MethodSymbol m : members)
jjg@4454
  1284
                if (m.defaultValue != null)
jjg@4454
  1285
                    res.add(m);
jjg@4454
  1286
            return res;
jjg@4454
  1287
        }
jjg@4454
  1288
jjg@4454
  1289
        @Override
jjg@4454
  1290
        public String toString() {
jjg@4454
  1291
            return "Annotation type for: " + metaDataFor;
jjg@4454
  1292
        }
jjg@4454
  1293
jjg@4454
  1294
        public boolean isMetadataForAnnotationType() { return true; }
jjg@4454
  1295
jjg@4454
  1296
        public static AnnotationTypeMetadata notAnAnnotationType() {
jjg@4454
  1297
            return NOT_AN_ANNOTATION_TYPE;
jjg@4454
  1298
        }
jjg@4454
  1299
jjg@4454
  1300
        private static final AnnotationTypeMetadata NOT_AN_ANNOTATION_TYPE =
jjg@4454
  1301
                new AnnotationTypeMetadata(null, null) {
jjg@4454
  1302
                    @Override
jjg@4454
  1303
                    public void complete() {
jjg@4454
  1304
                    } // do nothing
jjg@4454
  1305
jjg@4454
  1306
                    @Override
jjg@4454
  1307
                    public String toString() {
jjg@4454
  1308
                        return "Not an annotation type";
jjg@4454
  1309
                    }
jjg@4454
  1310
jjg@4454
  1311
                    @Override
jjg@4454
  1312
                    public Set<MethodSymbol> getAnnotationElements() {
jjg@4454
  1313
                        return new LinkedHashSet<>(0);
jjg@4454
  1314
                    }
jjg@4454
  1315
jjg@4454
  1316
                    @Override
jjg@4454
  1317
                    public Set<MethodSymbol> getAnnotationElementsWithDefault() {
jjg@4454
  1318
                        return new LinkedHashSet<>(0);
jjg@4454
  1319
                    }
jjg@4454
  1320
jjg@4454
  1321
                    @Override
jjg@4454
  1322
                    public boolean isMetadataForAnnotationType() {
jjg@4454
  1323
                        return false;
jjg@4454
  1324
                    }
jjg@4454
  1325
jjg@4454
  1326
                    @Override
jjg@4454
  1327
                    public Compound getTarget() {
jjg@4454
  1328
                        return null;
jjg@4454
  1329
                    }
jjg@4454
  1330
jjg@4454
  1331
                    @Override
jjg@4454
  1332
                    public Compound getRepeatable() {
jjg@4454
  1333
                        return null;
jjg@4454
  1334
                    }
jjg@4454
  1335
                };
jjg@4454
  1336
    }
jlahoda@5675
  1337
jlahoda@5675
  1338
    public void newRound() {
jlahoda@5675
  1339
        blockCount = 1;
jlahoda@5675
  1340
    }
jfranck@2156
  1341
}