src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
author Dusan Balek <dbalek@netbeans.org>
Fri, 22 Sep 2017 16:50:49 +0200
changeset 5963 9cc61f487a6d
parent 5961 740e1ee04027
permissions -rw-r--r--
Issue #269467 - Editor does not show error with code that does not compile - 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
dbalek@5963
   466
        if (args.length() == 1) {
dbalek@5963
   467
            if (!args.head.hasTag(ASSIGN)) {
dbalek@5963
   468
                args.head = make.at(Position.NOPOS).
dbalek@5963
   469
                        Assign(make.Ident(names.value), args.head);
dbalek@5963
   470
                elidedValue = true;
dbalek@5963
   471
            } else if (args.head.pos == Position.NOPOS) {
dbalek@5963
   472
                elidedValue = true;
dbalek@5963
   473
            }
jjg@4454
   474
        }
jjg@4454
   475
jjg@4454
   476
        ListBuffer<Pair<MethodSymbol,Attribute>> buf = new ListBuffer<>();
jjg@4454
   477
        for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
jjg@4454
   478
            Pair<MethodSymbol, Attribute> p = attributeAnnotationNameValuePair(tl.head, a.type, isError, env, elidedValue);
jjg@4454
   479
            if (p != null && !p.fst.type.isErroneous())
jjg@4454
   480
                buf.append(p);
jjg@4454
   481
        }
jjg@4454
   482
        return buf.toList();
jjg@4454
   483
    }
jjg@4454
   484
jjg@4454
   485
    // where
jjg@4454
   486
    private Pair<MethodSymbol, Attribute> attributeAnnotationNameValuePair(JCExpression nameValuePair,
jjg@4454
   487
            Type thisAnnotationType, boolean badAnnotation, Env<AttrContext> env, boolean elidedValue)
jjg@4454
   488
    {
jjg@4454
   489
        if (!nameValuePair.hasTag(ASSIGN)) {
jjg@4454
   490
            log.error(nameValuePair.pos(), "annotation.value.must.be.name.value");
jjg@4454
   491
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
jjg@4454
   492
            return null;
jjg@4454
   493
        }
jjg@4454
   494
        JCAssign assign = (JCAssign)nameValuePair;
jjg@4454
   495
        if (!assign.lhs.hasTag(IDENT)) {
jjg@4454
   496
            log.error(nameValuePair.pos(), "annotation.value.must.be.name.value");
jjg@4454
   497
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
jjg@4454
   498
            return null;
jjg@4454
   499
        }
jjg@4454
   500
jjg@4454
   501
        // Resolve element to MethodSym
jjg@4454
   502
        JCIdent left = (JCIdent)assign.lhs;
jjg@4454
   503
        Symbol method = resolve.resolveQualifiedMethod(elidedValue ? assign.rhs.pos() : left.pos(),
jjg@4454
   504
                env, thisAnnotationType,
mcimadamore@5586
   505
                left.name, List.nil(), null);
jjg@4454
   506
        left.sym = method;
jjg@4454
   507
        left.type = method.type;
jjg@4454
   508
        if (method.owner != thisAnnotationType.tsym && !badAnnotation)
jjg@4454
   509
            log.error(left.pos(), "no.annotation.member", left.name, thisAnnotationType);
jjg@4454
   510
        Type resultType = method.type.getReturnType();
jjg@4454
   511
jjg@4454
   512
        // Compute value part
jjg@4454
   513
        Attribute value = attributeAnnotationValue(resultType, assign.rhs, env);
jjg@4454
   514
        nameValuePair.type = resultType;
jjg@4454
   515
jjg@4454
   516
        return method.type.isErroneous() ? null : new Pair<>((MethodSymbol)method, value);
jjg@4454
   517
jjg@4454
   518
    }
jjg@4454
   519
jjg@4454
   520
    /** Attribute an annotation element value */
jjg@4454
   521
    private Attribute attributeAnnotationValue(Type expectedElementType, JCExpression tree,
jjg@4454
   522
            Env<AttrContext> env)
jjg@4454
   523
    {
jjg@4454
   524
        //first, try completing the symbol for the annotation value - if acompletion
jjg@4454
   525
        //error is thrown, we should recover gracefully, and display an
jjg@4454
   526
        //ordinary resolution diagnostic.
jjg@4454
   527
        try {
jjg@4454
   528
            expectedElementType.tsym.complete();
jjg@4454
   529
        } catch(CompletionFailure e) {
jjg@4454
   530
            log.error(tree.pos(), "cant.resolve", Kinds.kindName(e.sym), e.sym);
jjg@4454
   531
            expectedElementType = syms.errType;
jjg@4454
   532
        }
jjg@4454
   533
jjg@4454
   534
        if (expectedElementType.hasTag(ARRAY)) {
jjg@4454
   535
            return getAnnotationArrayValue(expectedElementType, tree, env);
jjg@4454
   536
jjg@4454
   537
        }
jjg@4454
   538
jjg@4454
   539
        //error recovery
jjg@4454
   540
        if (tree.hasTag(NEWARRAY)) {
jjg@4454
   541
            if (!expectedElementType.isErroneous())
jjg@4454
   542
                log.error(tree.pos(), "annotation.value.not.allowable.type");
jjg@4454
   543
            JCNewArray na = (JCNewArray)tree;
jjg@4454
   544
            if (na.elemtype != null) {
jjg@4454
   545
                log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
jjg@4454
   546
            }
jjg@4454
   547
            for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
jjg@4454
   548
                attributeAnnotationValue(syms.errType,
jjg@4454
   549
                        l.head,
jjg@4454
   550
                        env);
jjg@4454
   551
            }
jjg@4454
   552
            return new Attribute.Error(syms.errType);
jjg@4454
   553
        }
jjg@4454
   554
jjg@4454
   555
        if (expectedElementType.tsym.isAnnotationType()) {
jjg@4454
   556
            if (tree.hasTag(ANNOTATION)) {
jjg@4454
   557
                return attributeAnnotation((JCAnnotation)tree, expectedElementType, env);
jjg@4454
   558
            } else {
jjg@4454
   559
                log.error(tree.pos(), "annotation.value.must.be.annotation");
jjg@4454
   560
                expectedElementType = syms.errType;
jjg@4454
   561
            }
jjg@4454
   562
        }
jjg@4454
   563
jjg@4454
   564
        //error recovery
jjg@4454
   565
        if (tree.hasTag(ANNOTATION)) {
jjg@4454
   566
            if (!expectedElementType.isErroneous())
jjg@4454
   567
                log.error(tree.pos(), "annotation.not.valid.for.type", expectedElementType);
jjg@4454
   568
            attributeAnnotation((JCAnnotation)tree, syms.errType, env);
jjg@4454
   569
            return new Attribute.Error(((JCAnnotation)tree).annotationType.type);
jjg@4454
   570
        }
jjg@4454
   571
jjg@4454
   572
        if (expectedElementType.isPrimitive() ||
jjg@4454
   573
                (types.isSameType(expectedElementType, syms.stringType) && !expectedElementType.hasTag(TypeTag.ERROR))) {
jjg@4454
   574
            return getAnnotationPrimitiveValue(expectedElementType, tree, env);
jjg@4454
   575
        }
jjg@4454
   576
jjg@4454
   577
        if (expectedElementType.tsym == syms.classType.tsym) {
jjg@4454
   578
            return getAnnotationClassValue(expectedElementType, tree, env);
jjg@4454
   579
        }
jjg@4454
   580
jjg@4454
   581
        if (expectedElementType.hasTag(CLASS) &&
jjg@4454
   582
                (expectedElementType.tsym.flags() & Flags.ENUM) != 0) {
jjg@4454
   583
            return getAnnotationEnumValue(expectedElementType, tree, env);
jjg@4454
   584
        }
jjg@4454
   585
jjg@4454
   586
        //error recovery:
jjg@4454
   587
        if (!expectedElementType.isErroneous())
jjg@4454
   588
            log.error(tree.pos(), "annotation.value.not.allowable.type");
jjg@4454
   589
        return new Attribute.Error(attr.attribExpr(tree, env, expectedElementType));
jjg@4454
   590
    }
jjg@4454
   591
jjg@4454
   592
    private Attribute getAnnotationEnumValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   593
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   594
        Symbol sym = TreeInfo.symbol(tree);
jjg@4454
   595
        if (sym == null ||
jjg@4454
   596
                TreeInfo.nonstaticSelect(tree) ||
jjg@4454
   597
                sym.kind != VAR ||
jjg@4454
   598
                (sym.flags() & Flags.ENUM) == 0) {
jjg@4454
   599
            log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
jjg@4454
   600
            return new Attribute.Error(result.getOriginalType());
jjg@4454
   601
        }
jjg@4454
   602
        VarSymbol enumerator = (VarSymbol) sym;
jjg@4454
   603
        return new Attribute.Enum(expectedElementType, enumerator);
jjg@4454
   604
    }
jjg@4454
   605
jjg@4454
   606
    private Attribute getAnnotationClassValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   607
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   608
        if (result.isErroneous()) {
jjg@4454
   609
            // Does it look like an unresolved class literal?
jjg@4454
   610
            if (TreeInfo.name(tree) == names._class &&
jjg@4454
   611
                    ((JCFieldAccess) tree).selected.type.isErroneous()) {
jjg@4454
   612
                Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
jjg@4454
   613
                return new Attribute.UnresolvedClass(expectedElementType,
jjg@4454
   614
                        types.createErrorType(n,
jjg@4454
   615
                                syms.unknownSymbol, syms.classType));
jjg@4454
   616
            } else {
jjg@4454
   617
                return new Attribute.Error(result.getOriginalType());
jjg@4454
   618
            }
jjg@4454
   619
        }
jjg@4454
   620
jjg@4454
   621
        // Class literals look like field accesses of a field named class
jjg@4454
   622
        // at the tree level
jjg@4454
   623
        if (TreeInfo.name(tree) != names._class) {
jjg@4454
   624
            log.error(tree.pos(), "annotation.value.must.be.class.literal");
jjg@4454
   625
            return new Attribute.Error(syms.errType);
jjg@4454
   626
        }
jjg@4454
   627
        return new Attribute.Class(types,
jjg@4454
   628
                (((JCFieldAccess) tree).selected).type);
jjg@4454
   629
    }
jjg@4454
   630
jjg@4454
   631
    private Attribute getAnnotationPrimitiveValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   632
        Type result = attr.attribExpr(tree, env, expectedElementType);
jjg@4454
   633
        if (result.isErroneous())
jjg@4454
   634
            return new Attribute.Error(result.getOriginalType());
jjg@4454
   635
        if (result.constValue() == null) {
jjg@4454
   636
            log.error(tree.pos(), "attribute.value.must.be.constant");
jjg@4454
   637
            return new Attribute.Error(expectedElementType);
jjg@4454
   638
        }
jjg@4454
   639
        result = cfolder.coerce(result, expectedElementType);
jjg@4454
   640
        return new Attribute.Constant(expectedElementType, result.constValue());
jjg@4454
   641
    }
jjg@4454
   642
jjg@4454
   643
    private Attribute getAnnotationArrayValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
jjg@4454
   644
        // Special case, implicit array
jjg@4454
   645
        if (!tree.hasTag(NEWARRAY)) {
jjg@4454
   646
            tree = make.at(tree.pos).
mcimadamore@5586
   647
                    NewArray(null, List.nil(), List.of(tree));
jjg@4454
   648
        }
jjg@4454
   649
jjg@4454
   650
        JCNewArray na = (JCNewArray)tree;
jjg@4454
   651
        if (na.elemtype != null) {
jjg@4454
   652
            log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
jjg@4454
   653
        }
jjg@4454
   654
        ListBuffer<Attribute> buf = new ListBuffer<>();
dbalek@5961
   655
        if (na.elems != null) {
dbalek@5961
   656
            for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
dbalek@5961
   657
                buf.append(attributeAnnotationValue(types.elemtype(expectedElementType),
dbalek@5961
   658
                        l.head,
dbalek@5961
   659
                        env));
dbalek@5961
   660
            }
jjg@4454
   661
        }
jjg@4454
   662
        na.type = expectedElementType;
jjg@4454
   663
        return new Attribute.
jjg@4454
   664
                Array(expectedElementType, buf.toArray(new Attribute[buf.length()]));
jjg@4454
   665
    }
jjg@4454
   666
jjg@4454
   667
    /* *********************************
jjg@4454
   668
     * Support for repeating annotations
jjg@4454
   669
     ***********************************/
jjg@4454
   670
jjg@4454
   671
    /**
jfranck@2156
   672
     * This context contains all the information needed to synthesize new
jjg@4454
   673
     * annotations trees for repeating annotations.
jfranck@2156
   674
     */
emc@3932
   675
    private class AnnotationContext<T extends Attribute.Compound> {
jfranck@2156
   676
        public final Env<AttrContext> env;
jjg@2372
   677
        public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
jjg@2372
   678
        public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
jjg@2372
   679
        public final boolean isTypeCompound;
jfranck@2156
   680
emc@3932
   681
        public AnnotationContext(Env<AttrContext> env,
emc@3932
   682
                                 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
emc@3932
   683
                                 Map<T, JCDiagnostic.DiagnosticPosition> pos,
emc@3932
   684
                                 boolean isTypeCompound) {
jjg@2162
   685
            Assert.checkNonNull(env);
jjg@2162
   686
            Assert.checkNonNull(annotated);
jjg@2162
   687
            Assert.checkNonNull(pos);
jfranck@2156
   688
jfranck@2156
   689
            this.env = env;
jfranck@2156
   690
            this.annotated = annotated;
jfranck@2156
   691
            this.pos = pos;
jjg@2372
   692
            this.isTypeCompound = isTypeCompound;
jfranck@2156
   693
        }
emc@3932
   694
    }
emc@3932
   695
jfranck@2156
   696
    /* Process repeated annotations. This method returns the
jfranck@2156
   697
     * synthesized container annotation or null IFF all repeating
jfranck@2156
   698
     * annotation are invalid.  This method reports errors/warnings.
jfranck@2156
   699
     */
jfranck@4203
   700
    private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
alundblad@4477
   701
            AnnotationContext<T> ctx, Symbol on, boolean isTypeParam)
jjg@4454
   702
    {
jjg@2372
   703
        T firstOccurrence = annotations.head;
jfranck@2156
   704
        List<Attribute> repeated = List.nil();
jfranck@2288
   705
        Type origAnnoType = null;
jfranck@2156
   706
        Type arrayOfOrigAnnoType = null;
jfranck@2156
   707
        Type targetContainerType = null;
jfranck@2156
   708
        MethodSymbol containerValueSymbol = null;
jfranck@2156
   709
jjg@4454
   710
        Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1
jfranck@2156
   711
jfranck@2538
   712
        int count = 0;
jjg@4454
   713
        for (List<T> al = annotations; !al.isEmpty(); al = al.tail) {
jfranck@2538
   714
            count++;
jfranck@4203
   715
jfranck@2538
   716
            // There must be more than a single anno in the annotation list
jfranck@2538
   717
            Assert.check(count > 1 || !al.tail.isEmpty());
jfranck@2538
   718
jjg@2372
   719
            T currentAnno = al.head;
jfranck@2156
   720
jfranck@2156
   721
            origAnnoType = currentAnno.type;
jfranck@2156
   722
            if (arrayOfOrigAnnoType == null) {
jfranck@2156
   723
                arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
jjg@2372
   724
            }
jfranck@2156
   725
jfranck@2538
   726
            // Only report errors if this isn't the first occurrence I.E. count > 1
jfranck@2538
   727
            boolean reportError = count > 1;
jfranck@2538
   728
            Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError);
jfranck@2156
   729
            if (currentContainerType == null) {
jfranck@2156
   730
                continue;
jfranck@2156
   731
            }
jfranck@2156
   732
            // Assert that the target Container is == for all repeated
jfranck@2156
   733
            // annos of the same annotation type, the types should
jfranck@2156
   734
            // come from the same Symbol, i.e. be '=='
jfranck@2156
   735
            Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
jfranck@2156
   736
            targetContainerType = currentContainerType;
jfranck@2156
   737
jfranck@2156
   738
            containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));
jfranck@2156
   739
jfranck@2156
   740
            if (containerValueSymbol == null) { // Check of CA type failed
jfranck@2156
   741
                // errors are already reported
jfranck@2156
   742
                continue;
jfranck@2156
   743
            }
jfranck@2156
   744
jfranck@2156
   745
            repeated = repeated.prepend(currentAnno);
jfranck@2156
   746
        }
jfranck@2156
   747
jjg@4454
   748
        if (!repeated.isEmpty() && targetContainerType == null) {
jjg@4454
   749
            log.error(ctx.pos.get(annotations.head), "duplicate.annotation.invalid.repeated", origAnnoType);
jjg@4454
   750
            return null;
jjg@4454
   751
        }
jjg@4454
   752
jfranck@2156
   753
        if (!repeated.isEmpty()) {
jfranck@2156
   754
            repeated = repeated.reverse();
alundblad@4477
   755
            DiagnosticPosition pos = ctx.pos.get(firstOccurrence);
alundblad@4477
   756
            TreeMaker m = make.at(pos);
jfranck@2156
   757
            Pair<MethodSymbol, Attribute> p =
vromero@3810
   758
                    new Pair<MethodSymbol, Attribute>(containerValueSymbol,
jjg@4454
   759
                            new Attribute.Array(arrayOfOrigAnnoType, repeated));
jjg@2372
   760
            if (ctx.isTypeCompound) {
jfranck@4203
   761
                /* TODO: the following code would be cleaner:
jfranck@4203
   762
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
jfranck@4203
   763
                        ((Attribute.TypeCompound)annotations.head).position);
jfranck@4203
   764
                JCTypeAnnotation annoTree = m.TypeAnnotation(at);
jjg@4454
   765
                at = attributeTypeAnnotation(annoTree, targetContainerType, ctx.env);
jfranck@4203
   766
                */
jfranck@4203
   767
                // However, we directly construct the TypeCompound to keep the
jfranck@4203
   768
                // direct relation to the contained TypeCompounds.
jfranck@4203
   769
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
jfranck@4203
   770
                        ((Attribute.TypeCompound)annotations.head).position);
jfranck@4203
   771
alundblad@4477
   772
                JCAnnotation annoTree = m.TypeAnnotation(at);
alundblad@4477
   773
                if (!chk.validateAnnotationDeferErrors(annoTree))
alundblad@4477
   774
                    log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
alundblad@4477
   775
alundblad@4477
   776
                if (!chk.isTypeAnnotation(annoTree, isTypeParam)) {
alundblad@4477
   777
                    log.error(pos, isTypeParam ? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
alundblad@4477
   778
                                               : Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
alundblad@4477
   779
                }
jfranck@4203
   780
jjg@2372
   781
                at.setSynthesized(true);
jfranck@2288
   782
jjg@2372
   783
                @SuppressWarnings("unchecked")
jjg@2372
   784
                T x = (T) at;
jjg@2372
   785
                return x;
jjg@2372
   786
            } else {
jfranck@4203
   787
                Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
jjg@2372
   788
                JCAnnotation annoTree = m.Annotation(c);
jjg@2372
   789
alundblad@4460
   790
                if (!chk.annotationApplicable(annoTree, on)) {
alundblad@4460
   791
                    log.error(annoTree.pos(),
alundblad@4460
   792
                              Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on));
alundblad@4460
   793
                }
jjg@2372
   794
jjg@2372
   795
                if (!chk.validateAnnotationDeferErrors(annoTree))
jjg@2372
   796
                    log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
jjg@2372
   797
jjg@4454
   798
                c = attributeAnnotation(annoTree, targetContainerType, ctx.env);
jjg@2372
   799
                c.setSynthesized(true);
jjg@2372
   800
jjg@2372
   801
                @SuppressWarnings("unchecked")
jjg@2372
   802
                T x = (T) c;
jjg@2372
   803
                return x;
jjg@2372
   804
            }
jfranck@2156
   805
        } else {
jfranck@2156
   806
            return null; // errors should have been reported elsewhere
jfranck@2156
   807
        }
jfranck@2156
   808
    }
jfranck@2156
   809
jjg@4454
   810
    /**
jjg@4454
   811
     * Fetches the actual Type that should be the containing annotation.
jjg@4454
   812
     */
jfranck@2156
   813
    private Type getContainingType(Attribute.Compound currentAnno,
jjg@4454
   814
                                   DiagnosticPosition pos,
jjg@4454
   815
                                   boolean reportError)
jfranck@2156
   816
    {
jfranck@2156
   817
        Type origAnnoType = currentAnno.type;
jfranck@2156
   818
        TypeSymbol origAnnoDecl = origAnnoType.tsym;
jfranck@2156
   819
jjg@2339
   820
        // Fetch the Repeatable annotation from the current
jfranck@2156
   821
        // annotation's declaration, or null if it has none
jjg@4454
   822
        Attribute.Compound ca = origAnnoDecl.getAnnotationTypeMetadata().getRepeatable();
jjg@2339
   823
        if (ca == null) { // has no Repeatable annotation
jfranck@2538
   824
            if (reportError)
jfranck@2538
   825
                log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType);
jfranck@2156
   826
            return null;
jfranck@2156
   827
        }
jfranck@2156
   828
jfranck@2156
   829
        return filterSame(extractContainingType(ca, pos, origAnnoDecl),
jjg@4454
   830
                origAnnoType);
jfranck@2156
   831
    }
jfranck@2156
   832
jfranck@2156
   833
    // returns null if t is same as 's', returns 't' otherwise
jfranck@2156
   834
    private Type filterSame(Type t, Type s) {
jfranck@2156
   835
        if (t == null || s == null) {
jfranck@2156
   836
            return t;
jfranck@2156
   837
        }
jfranck@2156
   838
jfranck@2156
   839
        return types.isSameType(t, s) ? null : t;
jfranck@2156
   840
    }
jfranck@2156
   841
jfranck@2156
   842
    /** Extract the actual Type to be used for a containing annotation. */
jfranck@2156
   843
    private Type extractContainingType(Attribute.Compound ca,
jjg@4454
   844
                                       DiagnosticPosition pos,
jjg@4454
   845
                                       TypeSymbol annoDecl)
jfranck@2156
   846
    {
jjg@2339
   847
        // The next three checks check that the Repeatable annotation
jfranck@2156
   848
        // on the declaration of the annotation type that is repeating is
jfranck@2156
   849
        // valid.
jfranck@2156
   850
jjg@2339
   851
        // Repeatable must have at least one element
jfranck@2156
   852
        if (ca.values.isEmpty()) {
jjg@2339
   853
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   854
            return null;
jfranck@2156
   855
        }
jfranck@2156
   856
        Pair<MethodSymbol,Attribute> p = ca.values.head;
jfranck@2156
   857
        Name name = p.fst.name;
jfranck@2156
   858
        if (name != names.value) { // should contain only one element, named "value"
jjg@2339
   859
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   860
            return null;
jfranck@2156
   861
        }
jfranck@2156
   862
        if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
jjg@2339
   863
            log.error(pos, "invalid.repeatable.annotation", annoDecl);
jfranck@2156
   864
            return null;
jfranck@2156
   865
        }
jfranck@2156
   866
jfranck@2156
   867
        return ((Attribute.Class)p.snd).getValue();
jfranck@2156
   868
    }
jfranck@2156
   869
jfranck@2156
   870
    /* Validate that the suggested targetContainerType Type is a valid
jfranck@2156
   871
     * container type for repeated instances of originalAnnoType
jfranck@2156
   872
     * annotations. Return null and report errors if this is not the
jfranck@2156
   873
     * case, return the MethodSymbol of the value element in
jfranck@2156
   874
     * targetContainerType if it is suitable (this is needed to
jfranck@2156
   875
     * synthesize the container). */
jfranck@2156
   876
    private MethodSymbol validateContainer(Type targetContainerType,
jfranck@2156
   877
                                           Type originalAnnoType,
jfranck@2156
   878
                                           DiagnosticPosition pos) {
jfranck@2156
   879
        MethodSymbol containerValueSymbol = null;
jfranck@2156
   880
        boolean fatalError = false;
jfranck@2156
   881
jfranck@2156
   882
        // Validate that there is a (and only 1) value method
jfranck@2156
   883
        Scope scope = targetContainerType.tsym.members();
jfranck@2156
   884
        int nr_value_elems = 0;
jfranck@2156
   885
        boolean error = false;
jlahoda@4103
   886
        for(Symbol elm : scope.getSymbolsByName(names.value)) {
jfranck@2156
   887
            nr_value_elems++;
jfranck@2156
   888
jfranck@2156
   889
            if (nr_value_elems == 1 &&
jjg@4454
   890
                    elm.kind == MTH) {
jfranck@2156
   891
                containerValueSymbol = (MethodSymbol)elm;
jfranck@2156
   892
            } else {
jfranck@2156
   893
                error = true;
jfranck@2156
   894
            }
jfranck@2156
   895
        }
jfranck@2156
   896
        if (error) {
jfranck@2156
   897
            log.error(pos,
jjg@4454
   898
                    "invalid.repeatable.annotation.multiple.values",
jjg@4454
   899
                    targetContainerType,
jjg@4454
   900
                    nr_value_elems);
jfranck@2156
   901
            return null;
jfranck@2156
   902
        } else if (nr_value_elems == 0) {
jfranck@2156
   903
            log.error(pos,
jjg@4454
   904
                    "invalid.repeatable.annotation.no.value",
jjg@4454
   905
                    targetContainerType);
jfranck@2156
   906
            return null;
jfranck@2156
   907
        }
jfranck@2156
   908
jfranck@2156
   909
        // validate that the 'value' element is a method
jfranck@2156
   910
        // probably "impossible" to fail this
emc@4248
   911
        if (containerValueSymbol.kind != MTH) {
jfranck@2156
   912
            log.error(pos,
jjg@4454
   913
                    "invalid.repeatable.annotation.invalid.value",
jjg@4454
   914
                    targetContainerType);
jfranck@2156
   915
            fatalError = true;
jfranck@2156
   916
        }
jfranck@2156
   917
jfranck@2156
   918
        // validate that the 'value' element has the correct return type
jfranck@2156
   919
        // i.e. array of original anno
jfranck@2156
   920
        Type valueRetType = containerValueSymbol.type.getReturnType();
jfranck@2156
   921
        Type expectedType = types.makeArrayType(originalAnnoType);
jfranck@2156
   922
        if (!(types.isArray(valueRetType) &&
jjg@4454
   923
                types.isSameType(expectedType, valueRetType))) {
jfranck@2156
   924
            log.error(pos,
jjg@4454
   925
                    "invalid.repeatable.annotation.value.return",
jjg@4454
   926
                    targetContainerType,
jjg@4454
   927
                    valueRetType,
jjg@4454
   928
                    expectedType);
jfranck@2156
   929
            fatalError = true;
jfranck@2156
   930
        }
jfranck@2156
   931
jfranck@2156
   932
        return fatalError ? null : containerValueSymbol;
jfranck@2156
   933
    }
emc@3879
   934
jjg@4454
   935
    private <T extends Attribute.Compound> T makeContainerAnnotation(List<T> toBeReplaced,
alundblad@4477
   936
            AnnotationContext<T> ctx, Symbol sym, boolean isTypeParam)
jjg@4454
   937
    {
emc@3932
   938
        // Process repeated annotations
emc@3932
   939
        T validRepeated =
alundblad@4477
   940
                processRepeatedAnnotations(toBeReplaced, ctx, sym, isTypeParam);
emc@3932
   941
emc@3932
   942
        if (validRepeated != null) {
emc@3932
   943
            // Check that the container isn't manually
emc@3932
   944
            // present along with repeated instances of
emc@3932
   945
            // its contained annotation.
emc@3932
   946
            ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
emc@3932
   947
            if (manualContainer != null) {
jjg@4454
   948
                log.error(ctx.pos.get(manualContainer.first()),
jjg@4454
   949
                        "invalid.repeatable.annotation.repeated.and.container.present",
emc@3932
   950
                        manualContainer.first().type.tsym);
emc@3932
   951
            }
emc@3932
   952
        }
emc@3932
   953
emc@3932
   954
        // A null return will delete the Placeholder
emc@3932
   955
        return validRepeated;
emc@3932
   956
    }
emc@3932
   957
jjg@4454
   958
    /********************
jjg@4454
   959
     * Type annotations *
jjg@4454
   960
     ********************/
emc@3879
   961
jjg@4454
   962
    /**
jjg@4454
   963
     * Attribute the list of annotations and enter them onto s.
emc@3879
   964
     */
jjg@4454
   965
    public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env,
alundblad@4477
   966
            Symbol s, DiagnosticPosition deferPos, boolean isTypeParam)
jjg@4454
   967
    {
jfranck@4203
   968
        Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
emc@3882
   969
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
emc@3882
   970
        DiagnosticPosition prevLintPos = null;
emc@3879
   971
emc@3882
   972
        if (deferPos != null) {
emc@3882
   973
            prevLintPos = deferredLintHandler.setPos(deferPos);
emc@3882
   974
        }
emc@3882
   975
        try {
alundblad@4477
   976
            annotateNow(s, annotations, env, true, isTypeParam);
emc@3882
   977
        } finally {
emc@3882
   978
            if (prevLintPos != null)
emc@3882
   979
                deferredLintHandler.setPos(prevLintPos);
emc@3882
   980
            log.useSource(prev);
emc@3879
   981
        }
emc@3879
   982
    }
emc@3879
   983
jjg@4454
   984
    /**
jjg@4454
   985
     * Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
jjg@4454
   986
     */
jjg@4454
   987
    public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym,
jjg@4454
   988
            DiagnosticPosition deferPos)
jjg@4454
   989
    {
emc@3887
   990
        Assert.checkNonNull(sym);
alundblad@4902
   991
        normal(() -> tree.accept(new TypeAnnotate(env, sym, deferPos)));
jjg@4454
   992
    }
jjg@4454
   993
jjg@4454
   994
    /**
jjg@4454
   995
     * Apply the annotations to the particular type.
jjg@4454
   996
     */
jjg@4454
   997
    public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) {
alundblad@4902
   998
        typeAnnotation(() -> {
alundblad@4902
   999
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
alundblad@4902
  1000
            Assert.check(annotations.size() == compounds.size());
alundblad@4902
  1001
            storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
jjg@4454
  1002
        });
jjg@4454
  1003
    }
jjg@4454
  1004
jjg@4454
  1005
    /**
jjg@4454
  1006
     * Apply the annotations to the particular type.
jjg@4454
  1007
     */
jjg@4454
  1008
    public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) {
alundblad@4902
  1009
        typeAnnotation(() -> {
alundblad@4902
  1010
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
alundblad@4902
  1011
            Assert.check(annotations.size() == compounds.size());
jjg@4454
  1012
        });
emc@3879
  1013
    }
emc@3879
  1014
emc@3879
  1015
    /**
jfranck@4203
  1016
     * We need to use a TreeScanner, because it is not enough to visit the top-level
jfranck@4203
  1017
     * annotations. We also need to visit type arguments, etc.
emc@3879
  1018
     */
jfranck@4203
  1019
    private class TypeAnnotate extends TreeScanner {
jfranck@4203
  1020
        private final Env<AttrContext> env;
jfranck@4203
  1021
        private final Symbol sym;
jfranck@4203
  1022
        private DiagnosticPosition deferPos;
emc@3879
  1023
jjg@4454
  1024
        public TypeAnnotate(Env<AttrContext> env, Symbol sym, DiagnosticPosition deferPos) {
jfranck@4203
  1025
jfranck@4203
  1026
            this.env = env;
jfranck@4203
  1027
            this.sym = sym;
jfranck@4203
  1028
            this.deferPos = deferPos;
emc@3879
  1029
        }
emc@3879
  1030
emc@3879
  1031
        @Override
jjg@4454
  1032
        public void visitAnnotatedType(JCAnnotatedType tree) {
alundblad@4477
  1033
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
jjg@4454
  1034
            scan(tree.underlyingType);
emc@3879
  1035
        }
emc@3879
  1036
emc@3879
  1037
        @Override
jjg@4454
  1038
        public void visitTypeParameter(JCTypeParameter tree) {
alundblad@4477
  1039
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, true);
jjg@4454
  1040
            scan(tree.bounds);
emc@3879
  1041
        }
emc@3879
  1042
emc@3879
  1043
        @Override
jjg@4454
  1044
        public void visitNewArray(JCNewArray tree) {
alundblad@4477
  1045
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
jfranck@4203
  1046
            for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
alundblad@4477
  1047
                enterTypeAnnotations(dimAnnos, env, sym, deferPos, false);
jjg@4454
  1048
            scan(tree.elemtype);
jjg@4454
  1049
            scan(tree.elems);
emc@3879
  1050
        }
emc@3879
  1051
emc@3879
  1052
        @Override
jjg@4454
  1053
        public void visitMethodDef(JCMethodDecl tree) {
jfranck@4203
  1054
            scan(tree.mods);
jfranck@4203
  1055
            scan(tree.restype);
jfranck@4203
  1056
            scan(tree.typarams);
jfranck@4203
  1057
            scan(tree.recvparam);
jfranck@4203
  1058
            scan(tree.params);
jfranck@4203
  1059
            scan(tree.thrown);
jfranck@4203
  1060
            scan(tree.defaultValue);
jfranck@4203
  1061
            // Do not annotate the body, just the signature.
emc@3879
  1062
        }
emc@3879
  1063
emc@3879
  1064
        @Override
jjg@4454
  1065
        public void visitVarDef(JCVariableDecl tree) {
jfranck@4203
  1066
            DiagnosticPosition prevPos = deferPos;
jfranck@4203
  1067
            deferPos = tree.pos();
jfranck@4203
  1068
            try {
emc@4248
  1069
                if (sym != null && sym.kind == VAR) {
jfranck@4203
  1070
                    // Don't visit a parameter once when the sym is the method
jfranck@4203
  1071
                    // and once when the sym is the parameter.
jfranck@4203
  1072
                    scan(tree.mods);
jfranck@4203
  1073
                    scan(tree.vartype);
jfranck@4203
  1074
                }
jfranck@4203
  1075
                scan(tree.init);
jfranck@4203
  1076
            } finally {
jfranck@4203
  1077
                deferPos = prevPos;
emc@3879
  1078
            }
emc@3879
  1079
        }
emc@3879
  1080
emc@3879
  1081
        @Override
emc@3879
  1082
        public void visitClassDef(JCClassDecl tree) {
jfranck@4203
  1083
            // We can only hit a classdef if it is declared within
jfranck@4203
  1084
            // a method. Ignore it - the class will be visited
jfranck@4203
  1085
            // separately later.
emc@3879
  1086
        }
emc@3879
  1087
emc@3879
  1088
        @Override
emc@3879
  1089
        public void visitNewClass(JCNewClass tree) {
sadayapalam@4647
  1090
            scan(tree.encl);
sadayapalam@4647
  1091
            scan(tree.typeargs);
sadayapalam@4647
  1092
            scan(tree.clazz);
sadayapalam@4647
  1093
            scan(tree.args);
sadayapalam@4647
  1094
            // the anonymous class instantiation if any will be visited separately.
emc@4248
  1095
        }
dbalek@4731
  1096
dbalek@4731
  1097
        @Override
dbalek@4731
  1098
        public void visitErroneous(JCErroneous tree) {
dbalek@4731
  1099
            scan(tree.errs);
dbalek@4731
  1100
        }
emc@4248
  1101
    }
jjg@4454
  1102
jjg@4454
  1103
    /*********************
jjg@4454
  1104
     * Completer support *
jjg@4454
  1105
     *********************/
jjg@4454
  1106
jjg@4454
  1107
    private AnnotationTypeCompleter theSourceCompleter = new AnnotationTypeCompleter() {
jjg@4454
  1108
        @Override
jjg@4454
  1109
        public void complete(ClassSymbol sym) throws CompletionFailure {
jjg@4454
  1110
            Env<AttrContext> context = typeEnvs.get(sym);
jjg@4454
  1111
            Annotate.this.attributeAnnotationType(context);
jjg@4454
  1112
        }
jjg@4454
  1113
    };
jjg@4454
  1114
jjg@4454
  1115
    /* Last stage completer to enter just enough annotations to have a prototype annotation type.
jjg@4454
  1116
     * This currently means entering @Target and @Repetable.
jjg@4454
  1117
     */
jjg@4454
  1118
    public AnnotationTypeCompleter annotationTypeSourceCompleter() {
jjg@4454
  1119
        return theSourceCompleter;
jjg@4454
  1120
    }
jjg@4454
  1121
jjg@4454
  1122
    private void attributeAnnotationType(Env<AttrContext> env) {
jjg@4454
  1123
        Assert.check(((JCClassDecl)env.tree).sym.isAnnotationType(),
jjg@4454
  1124
                "Trying to annotation type complete a non-annotation type");
jjg@4454
  1125
jjg@4454
  1126
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
jjg@4454
  1127
        try {
jjg@4454
  1128
            JCClassDecl tree = (JCClassDecl)env.tree;
jjg@4454
  1129
            AnnotationTypeVisitor v = new AnnotationTypeVisitor(attr, chk, syms, typeEnvs);
jjg@4454
  1130
            v.scanAnnotationType(tree);
jjg@4454
  1131
            tree.sym.getAnnotationTypeMetadata().setRepeatable(v.repeatable);
jjg@4454
  1132
            tree.sym.getAnnotationTypeMetadata().setTarget(v.target);
jjg@4454
  1133
        } finally {
jjg@4454
  1134
            log.useSource(prev);
jjg@4454
  1135
        }
jjg@4454
  1136
    }
jjg@4454
  1137
jjg@4454
  1138
    public Attribute unfinishedDefaultValue() {
jjg@4454
  1139
        return theUnfinishedDefaultValue;
jjg@4454
  1140
    }
jjg@4454
  1141
jjg@4454
  1142
    public static interface AnnotationTypeCompleter {
jjg@4454
  1143
        void complete(ClassSymbol sym) throws CompletionFailure;
jjg@4454
  1144
    }
jjg@4454
  1145
jjg@4454
  1146
    /** Visitor to determine a prototype annotation type for a class declaring an annotation type.
jjg@4454
  1147
     *
jjg@4454
  1148
     *  <p><b>This is NOT part of any supported API.
jjg@4454
  1149
     *  If you write code that depends on this, you do so at your own risk.
jjg@4454
  1150
     *  This code and its internal interfaces are subject to change or
jjg@4454
  1151
     *  deletion without notice.</b>
jjg@4454
  1152
     */
jjg@4454
  1153
    public class AnnotationTypeVisitor extends TreeScanner {
jjg@4454
  1154
        private Env<AttrContext> env;
jjg@4454
  1155
jjg@4454
  1156
        private final Attr attr;
jjg@4454
  1157
        private final Check check;
jjg@4454
  1158
        private final Symtab tab;
jjg@4454
  1159
        private final TypeEnvs typeEnvs;
jjg@4454
  1160
jjg@4454
  1161
        private Compound target;
jjg@4454
  1162
        private Compound repeatable;
jjg@4454
  1163
jjg@4454
  1164
        public AnnotationTypeVisitor(Attr attr, Check check, Symtab tab, TypeEnvs typeEnvs) {
jjg@4454
  1165
            this.attr = attr;
jjg@4454
  1166
            this.check = check;
jjg@4454
  1167
            this.tab = tab;
jjg@4454
  1168
            this.typeEnvs = typeEnvs;
jjg@4454
  1169
        }
jjg@4454
  1170
jjg@4454
  1171
        public Compound getRepeatable() {
jjg@4454
  1172
            return repeatable;
jjg@4454
  1173
        }
jjg@4454
  1174
jjg@4454
  1175
        public Compound getTarget() {
jjg@4454
  1176
            return target;
jjg@4454
  1177
        }
jjg@4454
  1178
jjg@4454
  1179
        public void scanAnnotationType(JCClassDecl decl) {
jjg@4454
  1180
            visitClassDef(decl);
jjg@4454
  1181
        }
jjg@4454
  1182
jjg@4454
  1183
        @Override
jjg@4454
  1184
        public void visitClassDef(JCClassDecl tree) {
jjg@4454
  1185
            Env<AttrContext> prevEnv = env;
jjg@4454
  1186
            env = typeEnvs.get(tree.sym);
jjg@4454
  1187
            try {
jjg@4454
  1188
                scan(tree.mods); // look for repeatable and target
jjg@4454
  1189
                // don't descend into body
jjg@4454
  1190
            } finally {
jjg@4454
  1191
                env = prevEnv;
jjg@4454
  1192
            }
jjg@4454
  1193
        }
jjg@4454
  1194
jjg@4454
  1195
        @Override
jjg@4454
  1196
        public void visitAnnotation(JCAnnotation tree) {
jjg@4454
  1197
            Type t = tree.annotationType.type;
jjg@4454
  1198
            if (t == null) {
jjg@4454
  1199
                t = attr.attribType(tree.annotationType, env);
jjg@4454
  1200
                tree.annotationType.type = t = check.checkType(tree.annotationType.pos(), t, tab.annotationType);
jjg@4454
  1201
            }
jjg@4454
  1202
jjg@4454
  1203
            if (t == tab.annotationTargetType) {
jjg@4454
  1204
                target = Annotate.this.attributeAnnotation(tree, tab.annotationTargetType, env);
jjg@4454
  1205
            } else if (t == tab.repeatableType) {
jjg@4454
  1206
                repeatable = Annotate.this.attributeAnnotation(tree, tab.repeatableType, env);
emc@3879
  1207
            }
emc@3879
  1208
        }
dbalek@4427
  1209
dbalek@4427
  1210
        @Override
dbalek@4427
  1211
        public void visitErroneous(JCErroneous tree) {
dbalek@4427
  1212
            scan(tree.errs);
dbalek@4427
  1213
        }
emc@3879
  1214
    }
jjg@4454
  1215
jjg@4454
  1216
    /** Represents the semantics of an Annotation Type.
jjg@4454
  1217
     *
jjg@4454
  1218
     *  <p><b>This is NOT part of any supported API.
jjg@4454
  1219
     *  If you write code that depends on this, you do so at your own risk.
jjg@4454
  1220
     *  This code and its internal interfaces are subject to change or
jjg@4454
  1221
     *  deletion without notice.</b>
jjg@4454
  1222
     */
jjg@4454
  1223
    public static class AnnotationTypeMetadata {
jjg@4454
  1224
        final ClassSymbol metaDataFor;
jjg@4454
  1225
        private Compound target;
jjg@4454
  1226
        private Compound repeatable;
jjg@4454
  1227
        private AnnotationTypeCompleter annotationTypeCompleter;
jjg@4454
  1228
jjg@4454
  1229
        public AnnotationTypeMetadata(ClassSymbol metaDataFor, AnnotationTypeCompleter annotationTypeCompleter) {
jjg@4454
  1230
            this.metaDataFor = metaDataFor;
jjg@4454
  1231
            this.annotationTypeCompleter = annotationTypeCompleter;
jjg@4454
  1232
        }
jjg@4454
  1233
jjg@4454
  1234
        private void init() {
jjg@4454
  1235
            // Make sure metaDataFor is member entered
alundblad@4474
  1236
            while (!metaDataFor.isCompleted())
jjg@4454
  1237
                metaDataFor.complete();
jjg@4454
  1238
jjg@4454
  1239
            if (annotationTypeCompleter != null) {
jjg@4454
  1240
                AnnotationTypeCompleter c = annotationTypeCompleter;
jjg@4454
  1241
                annotationTypeCompleter = null;
jjg@4454
  1242
                c.complete(metaDataFor);
jjg@4454
  1243
            }
jjg@4454
  1244
        }
jjg@4454
  1245
jjg@4454
  1246
        public void complete() {
jjg@4454
  1247
            init();
jjg@4454
  1248
        }
jjg@4454
  1249
jjg@4454
  1250
        public Compound getRepeatable() {
jjg@4454
  1251
            init();
jjg@4454
  1252
            return repeatable;
jjg@4454
  1253
        }
jjg@4454
  1254
jjg@4454
  1255
        public void setRepeatable(Compound repeatable) {
jjg@4454
  1256
            Assert.checkNull(this.repeatable);
jjg@4454
  1257
            this.repeatable = repeatable;
jjg@4454
  1258
        }
jjg@4454
  1259
jjg@4454
  1260
        public Compound getTarget() {
jjg@4454
  1261
            init();
jjg@4454
  1262
            return target;
jjg@4454
  1263
        }
jjg@4454
  1264
jjg@4454
  1265
        public void setTarget(Compound target) {
jjg@4454
  1266
            Assert.checkNull(this.target);
jjg@4454
  1267
                this.target = target;
jjg@4454
  1268
        }
jjg@4454
  1269
jjg@4454
  1270
        public Set<MethodSymbol> getAnnotationElements() {
jjg@4454
  1271
            init();
jjg@4454
  1272
            Set<MethodSymbol> members = new LinkedHashSet<>();
jjg@4454
  1273
            WriteableScope s = metaDataFor.members();
jjg@4454
  1274
            Iterable<Symbol> ss = s.getSymbols(NON_RECURSIVE);
jjg@4454
  1275
            for (Symbol sym : ss)
jjg@4454
  1276
                if (sym.kind == MTH &&
jjg@4454
  1277
                        sym.name != sym.name.table.names.clinit &&
jjg@4454
  1278
                        (sym.flags() & SYNTHETIC) == 0)
jjg@4454
  1279
                    members.add((MethodSymbol)sym);
jjg@4454
  1280
            return members;
jjg@4454
  1281
        }
jjg@4454
  1282
jjg@4454
  1283
        public Set<MethodSymbol> getAnnotationElementsWithDefault() {
jjg@4454
  1284
            init();
jjg@4454
  1285
            Set<MethodSymbol> members = getAnnotationElements();
jjg@4454
  1286
            Set<MethodSymbol> res = new LinkedHashSet<>();
jjg@4454
  1287
            for (MethodSymbol m : members)
jjg@4454
  1288
                if (m.defaultValue != null)
jjg@4454
  1289
                    res.add(m);
jjg@4454
  1290
            return res;
jjg@4454
  1291
        }
jjg@4454
  1292
jjg@4454
  1293
        @Override
jjg@4454
  1294
        public String toString() {
jjg@4454
  1295
            return "Annotation type for: " + metaDataFor;
jjg@4454
  1296
        }
jjg@4454
  1297
jjg@4454
  1298
        public boolean isMetadataForAnnotationType() { return true; }
jjg@4454
  1299
jjg@4454
  1300
        public static AnnotationTypeMetadata notAnAnnotationType() {
jjg@4454
  1301
            return NOT_AN_ANNOTATION_TYPE;
jjg@4454
  1302
        }
jjg@4454
  1303
jjg@4454
  1304
        private static final AnnotationTypeMetadata NOT_AN_ANNOTATION_TYPE =
jjg@4454
  1305
                new AnnotationTypeMetadata(null, null) {
jjg@4454
  1306
                    @Override
jjg@4454
  1307
                    public void complete() {
jjg@4454
  1308
                    } // do nothing
jjg@4454
  1309
jjg@4454
  1310
                    @Override
jjg@4454
  1311
                    public String toString() {
jjg@4454
  1312
                        return "Not an annotation type";
jjg@4454
  1313
                    }
jjg@4454
  1314
jjg@4454
  1315
                    @Override
jjg@4454
  1316
                    public Set<MethodSymbol> getAnnotationElements() {
jjg@4454
  1317
                        return new LinkedHashSet<>(0);
jjg@4454
  1318
                    }
jjg@4454
  1319
jjg@4454
  1320
                    @Override
jjg@4454
  1321
                    public Set<MethodSymbol> getAnnotationElementsWithDefault() {
jjg@4454
  1322
                        return new LinkedHashSet<>(0);
jjg@4454
  1323
                    }
jjg@4454
  1324
jjg@4454
  1325
                    @Override
jjg@4454
  1326
                    public boolean isMetadataForAnnotationType() {
jjg@4454
  1327
                        return false;
jjg@4454
  1328
                    }
jjg@4454
  1329
jjg@4454
  1330
                    @Override
jjg@4454
  1331
                    public Compound getTarget() {
jjg@4454
  1332
                        return null;
jjg@4454
  1333
                    }
jjg@4454
  1334
jjg@4454
  1335
                    @Override
jjg@4454
  1336
                    public Compound getRepeatable() {
jjg@4454
  1337
                        return null;
jjg@4454
  1338
                    }
jjg@4454
  1339
                };
jjg@4454
  1340
    }
jlahoda@5675
  1341
jlahoda@5675
  1342
    public void newRound() {
jlahoda@5675
  1343
        blockCount = 1;
jlahoda@5675
  1344
    }
jfranck@2156
  1345
}