JDK 11 jdk.compiler.jmod - Compiler Tool

JDK 11 jdk.compiler.jmod is the JMOD file for JDK 11 Compiler tool, which can be invoked by the "javac" command.

JDK 11 Compiler tool compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\jdk.compiler.jmod.

JDK 11 Compiler tool compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.

JDK 11 Compiler source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\jdk.compiler.

You can click and view the content of each source code file in the list below.

✍: FYIcenter

com/sun/tools/javac/comp/Annotate.java

/*
 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.tools.javac.comp;

import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.Compound;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Kinds.KindSelector;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;

import javax.tools.JavaFileObject;

import java.util.*;

import static com.sun.tools.javac.code.Flags.SYNTHETIC;
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
import static com.sun.tools.javac.code.Kinds.Kind.PCK;
import static com.sun.tools.javac.code.Kinds.Kind.VAR;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.tree.JCTree.Tag.ANNOTATION;
import static com.sun.tools.javac.tree.JCTree.Tag.ASSIGN;
import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
import static com.sun.tools.javac.tree.JCTree.Tag.NEWARRAY;

import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;


/** Enter annotations onto symbols and types (and trees).
 *
 *  This is also a pseudo stage in the compiler taking care of scheduling when annotations are
 *  entered.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class Annotate {
    protected static final Context.Key<Annotate> annotateKey = new Context.Key<>();

    public static Annotate instance(Context context) {
        Annotate instance = context.get(annotateKey);
        if (instance == null)
            instance = new Annotate(context);
        return instance;
    }

    private final Attr attr;
    private final Check chk;
    private final ConstFold cfolder;
    private final DeferredLintHandler deferredLintHandler;
    private final Enter enter;
    private final Lint lint;
    private final Log log;
    private final Names names;
    private final Resolve resolve;
    private final TreeMaker make;
    private final Symtab syms;
    private final TypeEnvs typeEnvs;
    private final Types types;

    private final Attribute theUnfinishedDefaultValue;
    private final boolean allowRepeatedAnnos;
    private final String sourceName;

    protected Annotate(Context context) {
        context.put(annotateKey, this);

        attr = Attr.instance(context);
        chk = Check.instance(context);
        cfolder = ConstFold.instance(context);
        deferredLintHandler = DeferredLintHandler.instance(context);
        enter = Enter.instance(context);
        log = Log.instance(context);
        lint = Lint.instance(context);
        make = TreeMaker.instance(context);
        names = Names.instance(context);
        resolve = Resolve.instance(context);
        syms = Symtab.instance(context);
        typeEnvs = TypeEnvs.instance(context);
        types = Types.instance(context);

        theUnfinishedDefaultValue =  new Attribute.Error(syms.errType);

        Source source = Source.instance(context);
        allowRepeatedAnnos = Feature.REPEATED_ANNOTATIONS.allowedInSource(source);
        sourceName = source.name;

        blockCount = 1;
    }

    /** Semaphore to delay annotation processing */
    private int blockCount = 0;

    /** Called when annotations processing needs to be postponed. */
    public void blockAnnotations() {
        blockCount++;
    }

    /** Called when annotation processing can be resumed. */
    public void unblockAnnotations() {
        blockCount--;
        if (blockCount == 0)
            flush();
    }

    /** Variant which allows for a delayed flush of annotations.
     * Needed by ClassReader */
    public void unblockAnnotationsNoFlush() {
        blockCount--;
    }

    /** are we blocking annotation processing? */
    public boolean annotationsBlocked() {return blockCount > 0; }

    public void enterDone() {
        unblockAnnotations();
    }

    public List<TypeCompound> fromAnnotations(List<JCAnnotation> annotations) {
        if (annotations.isEmpty()) {
            return List.nil();
        }

        ListBuffer<TypeCompound> buf = new ListBuffer<>();
        for (JCAnnotation anno : annotations) {
            Assert.checkNonNull(anno.attribute);
            buf.append((TypeCompound) anno.attribute);
        }
        return buf.toList();
    }

    /** Annotate (used for everything else) */
    public void normal(Runnable r) {
        q.append(r);
    }

    /** Validate, triggers after 'normal' */
    public void validate(Runnable a) {
        validateQ.append(a);
    }

    /** Flush all annotation queues */
    public void flush() {
        if (annotationsBlocked()) return;
        if (isFlushing()) return;

        startFlushing();
        try {
            while (q.nonEmpty()) {
                q.next().run();
            }
            while (typesQ.nonEmpty()) {
                typesQ.next().run();
            }
            while (afterTypesQ.nonEmpty()) {
                afterTypesQ.next().run();
            }
            while (validateQ.nonEmpty()) {
                validateQ.next().run();
            }
        } finally {
            doneFlushing();
        }
    }

    private ListBuffer<Runnable> q = new ListBuffer<>();
    private ListBuffer<Runnable> validateQ = new ListBuffer<>();

    private int flushCount = 0;
    private boolean isFlushing() { return flushCount > 0; }
    private void startFlushing() { flushCount++; }
    private void doneFlushing() { flushCount--; }

    ListBuffer<Runnable> typesQ = new ListBuffer<>();
    ListBuffer<Runnable> afterTypesQ = new ListBuffer<>();


    public void typeAnnotation(Runnable a) {
        typesQ.append(a);
    }

    public void afterTypes(Runnable a) {
        afterTypesQ.append(a);
    }

    /**
     * Queue annotations for later attribution and entering. This is probably the method you are looking for.
     *
     * @param annotations the list of JCAnnotations to attribute and enter
     * @param localEnv    the enclosing env
     * @param s           ths Symbol on which to enter the annotations
     * @param deferPos    report errors here
     */
    public void annotateLater(List<JCAnnotation> annotations, Env<AttrContext> localEnv,
            Symbol s, DiagnosticPosition deferPos)
    {
        if (annotations.isEmpty()) {
            return;
        }

        s.resetAnnotations(); // mark Annotations as incomplete for now

        normal(() -> {
            // Packages are unusual, in that they are the only type of declaration that can legally appear
            // more than once in a compilation, and in all cases refer to the same underlying symbol.
            // This means they are the only kind of declaration that syntactically may have multiple sets
            // of annotations, each on a different package declaration, even though that is ultimately
            // forbidden by JLS 8 section 7.4.
            // The corollary here is that all of the annotations on a package symbol may have already
            // been handled, meaning that the set of annotations pending completion is now empty.
            Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
            DiagnosticPosition prevLintPos =
                    deferPos != null
                            ? deferredLintHandler.setPos(deferPos)
                            : deferredLintHandler.immediate();
            Lint prevLint = deferPos != null ? null : chk.setLint(lint);
            try {
                if (s.hasAnnotations() && annotations.nonEmpty())
                    log.error(annotations.head.pos, Errors.AlreadyAnnotated(Kinds.kindName(s), s));

                Assert.checkNonNull(s, "Symbol argument to actualEnterAnnotations is null");

                // false is passed as fifth parameter since annotateLater is
                // never called for a type parameter
                annotateNow(s, annotations, localEnv, false, false);
            } finally {
                if (prevLint != null)
                    chk.setLint(prevLint);
                deferredLintHandler.setPos(prevLintPos);
                log.useSource(prev);
            }
        });

        validate(() -> { //validate annotations
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
            try {
                chk.validateAnnotations(annotations, s);
            } finally {
                log.useSource(prev);
            }
        });
    }


    /** Queue processing of an attribute default value. */
    public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv,
            MethodSymbol m, DiagnosticPosition deferPos)
    {
        normal(() -> {
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
            DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos);
            try {
                enterDefaultValue(defaultValue, localEnv, m);
            } finally {
                deferredLintHandler.setPos(prevLintPos);
                log.useSource(prev);
            }
        });

        validate(() -> { //validate annotations
            JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
            try {
                // if default value is an annotation, check it is a well-formed
                // annotation value (e.g. no duplicate values, no missing values, etc.)
                chk.validateAnnotationTree(defaultValue);
            } finally {
                log.useSource(prev);
            }
        });
    }

    /** Enter a default value for an annotation element. */
    private void enterDefaultValue(JCExpression defaultValue,
            Env<AttrContext> localEnv, MethodSymbol m) {
        m.defaultValue = attributeAnnotationValue(m.type.getReturnType(), defaultValue, localEnv);
    }

    /**
     * Gather up annotations into a map from type symbols to lists of Compound attributes,
     * then continue on with repeating annotations processing.
     */
    private <T extends Attribute.Compound> void annotateNow(Symbol toAnnotate,
            List<JCAnnotation> withAnnotations, Env<AttrContext> env, boolean typeAnnotations,
            boolean isTypeParam)
    {
        Map<TypeSymbol, ListBuffer<T>> annotated = new LinkedHashMap<>();
        Map<T, DiagnosticPosition> pos = new HashMap<>();

        for (List<JCAnnotation> al = withAnnotations; !al.isEmpty(); al = al.tail) {
            JCAnnotation a = al.head;

            T c;
            if (typeAnnotations) {
                @SuppressWarnings("unchecked")
                T tmp = (T)attributeTypeAnnotation(a, syms.annotationType, env);
                c = tmp;
            } else {
                @SuppressWarnings("unchecked")
                T tmp = (T)attributeAnnotation(a, syms.annotationType, env);
                c = tmp;
            }

            Assert.checkNonNull(c, "Failed to create annotation");

            if (annotated.containsKey(a.type.tsym)) {
                if (!allowRepeatedAnnos) {
                    log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Feature.REPEATED_ANNOTATIONS.error(sourceName));
                }
                ListBuffer<T> l = annotated.get(a.type.tsym);
                l = l.append(c);
                annotated.put(a.type.tsym, l);
                pos.put(c, a.pos());
            } else {
                annotated.put(a.type.tsym, ListBuffer.of(c));
                pos.put(c, a.pos());
            }

            // Note: @Deprecated has no effect on local variables and parameters
            if (!c.type.isErroneous()
                    && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
                    && types.isSameType(c.type, syms.deprecatedType)) {
                toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
                Attribute fr = c.member(names.forRemoval);
                if (fr instanceof Attribute.Constant) {
                    Attribute.Constant v = (Attribute.Constant) fr;
                    if (v.type == syms.booleanType && ((Integer) v.value) != 0) {
                        toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
                    }
                }
            }
        }

        List<T> buf = List.nil();
        for (ListBuffer<T> lb : annotated.values()) {
            if (lb.size() == 1) {
                buf = buf.prepend(lb.first());
            } else {
                AnnotationContext<T> ctx = new AnnotationContext<>(env, annotated, pos, typeAnnotations);
                T res = makeContainerAnnotation(lb.toList(), ctx, toAnnotate, isTypeParam);
                if (res != null)
                    buf = buf.prepend(res);
            }
        }

        if (typeAnnotations) {
            @SuppressWarnings("unchecked")
            List<TypeCompound> attrs = (List<TypeCompound>)buf.reverse();
            toAnnotate.appendUniqueTypeAttributes(attrs);
        } else {
            @SuppressWarnings("unchecked")
            List<Attribute.Compound> attrs =  (List<Attribute.Compound>)buf.reverse();
            toAnnotate.resetAnnotations();
            toAnnotate.setDeclarationAttributes(attrs);
        }
    }

    /**
     * Attribute and store a semantic representation of the annotation tree {@code tree} into the
     * tree.attribute field.
     *
     * @param tree the tree representing an annotation
     * @param expectedAnnotationType the expected (super)type of the annotation
     * @param env the current env in where the annotation instance is found
     */
    public Attribute.Compound attributeAnnotation(JCAnnotation tree, Type expectedAnnotationType,
                                                  Env<AttrContext> env)
    {
        // The attribute might have been entered if it is Target or Repetable
        // Because TreeCopier does not copy type, redo this if type is null
        if (tree.attribute != null && tree.type != null)
            return tree.attribute;

        List<Pair<MethodSymbol, Attribute>> elems = attributeAnnotationValues(tree, expectedAnnotationType, env);
        Attribute.Compound ac = new Attribute.Compound(tree.type, elems);

        return tree.attribute = ac;
    }

    /** Attribute and store a semantic representation of the type annotation tree {@code tree} into
     * the tree.attribute field.
     *
     * @param a the tree representing an annotation
     * @param expectedAnnotationType the expected (super)type of the annotation
     * @param env the the current env in where the annotation instance is found
     */
    public Attribute.TypeCompound attributeTypeAnnotation(JCAnnotation a, Type expectedAnnotationType,
                                                          Env<AttrContext> env)
    {
        // The attribute might have been entered if it is Target or Repetable
        // Because TreeCopier does not copy type, redo this if type is null
        if (a.attribute == null || a.type == null || !(a.attribute instanceof Attribute.TypeCompound)) {
            // Create a new TypeCompound
            List<Pair<MethodSymbol,Attribute>> elems =
                    attributeAnnotationValues(a, expectedAnnotationType, env);

            Attribute.TypeCompound tc =
                    new Attribute.TypeCompound(a.type, elems, TypeAnnotationPosition.unknown);
            a.attribute = tc;
            return tc;
        } else {
            // Use an existing TypeCompound
            return (Attribute.TypeCompound)a.attribute;
        }
    }

    /**
     *  Attribute annotation elements creating a list of pairs of the Symbol representing that
     *  element and the value of that element as an Attribute. */
    private List<Pair<MethodSymbol, Attribute>> attributeAnnotationValues(JCAnnotation a,
            Type expected, Env<AttrContext> env)
    {
        // The annotation might have had its type attributed (but not
        // checked) by attr.attribAnnotationTypes during MemberEnter,
        // in which case we do not need to do it again.
        Type at = (a.annotationType.type != null ?
                a.annotationType.type : attr.attribType(a.annotationType, env));
        a.type = chk.checkType(a.annotationType.pos(), at, expected);

        boolean isError = a.type.isErroneous();
        if (!a.type.tsym.isAnnotationType() && !isError) {
            log.error(a.annotationType.pos(), Errors.NotAnnotationType(a.type));
            isError = true;
        }

        // List of name=value pairs (or implicit "value=" if size 1)
        List<JCExpression> args = a.args;

        boolean elidedValue = false;
        // special case: elided "value=" assumed
        if (args.length() == 1 && !args.head.hasTag(ASSIGN)) {
            args.head = make.at(args.head.pos).
                    Assign(make.Ident(names.value), args.head);
            elidedValue = true;
        }

        ListBuffer<Pair<MethodSymbol,Attribute>> buf = new ListBuffer<>();
        for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
            Pair<MethodSymbol, Attribute> p = attributeAnnotationNameValuePair(tl.head, a.type, isError, env, elidedValue);
            if (p != null && !p.fst.type.isErroneous())
                buf.append(p);
        }
        return buf.toList();
    }

    // where
    private Pair<MethodSymbol, Attribute> attributeAnnotationNameValuePair(JCExpression nameValuePair,
            Type thisAnnotationType, boolean badAnnotation, Env<AttrContext> env, boolean elidedValue)
    {
        if (!nameValuePair.hasTag(ASSIGN)) {
            log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue);
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
            return null;
        }
        JCAssign assign = (JCAssign)nameValuePair;
        if (!assign.lhs.hasTag(IDENT)) {
            log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue);
            attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
            return null;
        }

        // Resolve element to MethodSym
        JCIdent left = (JCIdent)assign.lhs;
        Symbol method = resolve.resolveQualifiedMethod(elidedValue ? assign.rhs.pos() : left.pos(),
                env, thisAnnotationType,
                left.name, List.nil(), null);
        left.sym = method;
        left.type = method.type;
        if (method.owner != thisAnnotationType.tsym && !badAnnotation)
            log.error(left.pos(), Errors.NoAnnotationMember(left.name, thisAnnotationType));
        Type resultType = method.type.getReturnType();

        // Compute value part
        Attribute value = attributeAnnotationValue(resultType, assign.rhs, env);
        nameValuePair.type = resultType;

        return method.type.isErroneous() ? null : new Pair<>((MethodSymbol)method, value);

    }

    /** Attribute an annotation element value */
    private Attribute attributeAnnotationValue(Type expectedElementType, JCExpression tree,
            Env<AttrContext> env)
    {
        //first, try completing the symbol for the annotation value - if acompletion
        //error is thrown, we should recover gracefully, and display an
        //ordinary resolution diagnostic.
        try {
            expectedElementType.tsym.complete();
        } catch(CompletionFailure e) {
            log.error(tree.pos(), Errors.CantResolve(Kinds.kindName(e.sym), e.sym.getQualifiedName(), null, null));
            expectedElementType = syms.errType;
        }

        if (expectedElementType.hasTag(ARRAY)) {
            return getAnnotationArrayValue(expectedElementType, tree, env);

        }

        //error recovery
        if (tree.hasTag(NEWARRAY)) {
            if (!expectedElementType.isErroneous())
                log.error(tree.pos(), Errors.AnnotationValueNotAllowableType);
            JCNewArray na = (JCNewArray)tree;
            if (na.elemtype != null) {
                log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation);
            }
            for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
                attributeAnnotationValue(syms.errType,
                        l.head,
                        env);
            }
            return new Attribute.Error(syms.errType);
        }

        if (expectedElementType.tsym.isAnnotationType()) {
            if (tree.hasTag(ANNOTATION)) {
                return attributeAnnotation((JCAnnotation)tree, expectedElementType, env);
            } else {
                log.error(tree.pos(), Errors.AnnotationValueMustBeAnnotation);
                expectedElementType = syms.errType;
            }
        }

        //error recovery
        if (tree.hasTag(ANNOTATION)) {
            if (!expectedElementType.isErroneous())
                log.error(tree.pos(), Errors.AnnotationNotValidForType(expectedElementType));
            attributeAnnotation((JCAnnotation)tree, syms.errType, env);
            return new Attribute.Error(((JCAnnotation)tree).annotationType.type);
        }

        MemberEnter.InitTreeVisitor initTreeVisitor = new MemberEnter.InitTreeVisitor() {
            // the methods below are added to allow class literals on top of constant expressions
            @Override
            public void visitTypeIdent(JCPrimitiveTypeTree that) {}

            @Override
            public void visitTypeArray(JCArrayTypeTree that) {}
        };
        tree.accept(initTreeVisitor);
        if (!initTreeVisitor.result) {
            log.error(tree.pos(), Errors.ExpressionNotAllowableAsAnnotationValue);
            return new Attribute.Error(syms.errType);
        }

        if (expectedElementType.isPrimitive() ||
                (types.isSameType(expectedElementType, syms.stringType) && !expectedElementType.hasTag(TypeTag.ERROR))) {
            return getAnnotationPrimitiveValue(expectedElementType, tree, env);
        }

        if (expectedElementType.tsym == syms.classType.tsym) {
            return getAnnotationClassValue(expectedElementType, tree, env);
        }

        if (expectedElementType.hasTag(CLASS) &&
                (expectedElementType.tsym.flags() & Flags.ENUM) != 0) {
            return getAnnotationEnumValue(expectedElementType, tree, env);
        }

        //error recovery:
        if (!expectedElementType.isErroneous())
            log.error(tree.pos(), Errors.AnnotationValueNotAllowableType);
        return new Attribute.Error(attr.attribExpr(tree, env, expectedElementType));
    }

    private Attribute getAnnotationEnumValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
        Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
        Symbol sym = TreeInfo.symbol(tree);
        if (sym == null ||
                TreeInfo.nonstaticSelect(tree) ||
                sym.kind != VAR ||
                (sym.flags() & Flags.ENUM) == 0) {
            log.error(tree.pos(), Errors.EnumAnnotationMustBeEnumConstant);
            return new Attribute.Error(result.getOriginalType());
        }
        VarSymbol enumerator = (VarSymbol) sym;
        return new Attribute.Enum(expectedElementType, enumerator);
    }

    private Attribute getAnnotationClassValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
        Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
        if (result.isErroneous()) {
            // Does it look like an unresolved class literal?
            if (TreeInfo.name(tree) == names._class &&
                    ((JCFieldAccess) tree).selected.type.isErroneous()) {
                Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
                return new Attribute.UnresolvedClass(expectedElementType,
                        types.createErrorType(n,
                                syms.unknownSymbol, syms.classType));
            } else {
                return new Attribute.Error(result.getOriginalType());
            }
        }

        // Class literals look like field accesses of a field named class
        // at the tree level
        if (TreeInfo.name(tree) != names._class) {
            log.error(tree.pos(), Errors.AnnotationValueMustBeClassLiteral);
            return new Attribute.Error(syms.errType);
        }

        return new Attribute.Class(types,
                (((JCFieldAccess) tree).selected).type);
    }

    private Attribute getAnnotationPrimitiveValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
        Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
        if (result.isErroneous())
            return new Attribute.Error(result.getOriginalType());
        if (result.constValue() == null) {
            log.error(tree.pos(), Errors.AttributeValueMustBeConstant);
            return new Attribute.Error(expectedElementType);
        }
        result = cfolder.coerce(result, expectedElementType);
        return new Attribute.Constant(expectedElementType, result.constValue());
    }

    private Attr.ResultInfo annotationValueInfo(Type pt) {
        return attr.unknownExprInfo.dup(pt, new AnnotationValueContext(attr.unknownExprInfo.checkContext));
    }

    class AnnotationValueContext extends Check.NestedCheckContext {
        AnnotationValueContext(CheckContext enclosingContext) {
            super(enclosingContext);
        }

        @Override
        public boolean compatible(Type found, Type req, Warner warn) {
            //handle non-final implicitly-typed vars (will be rejected later on)
            return found.hasTag(TypeTag.NONE) || super.compatible(found, req, warn);
        }
    }

    private Attribute getAnnotationArrayValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
        // Special case, implicit array
        if (!tree.hasTag(NEWARRAY)) {
            tree = make.at(tree.pos).
                    NewArray(null, List.nil(), List.of(tree));
        }

        JCNewArray na = (JCNewArray)tree;
        if (na.elemtype != null) {
            log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation);
        }
        ListBuffer<Attribute> buf = new ListBuffer<>();
        for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
            buf.append(attributeAnnotationValue(types.elemtype(expectedElementType),
                    l.head,
                    env));
        }
        na.type = expectedElementType;
        return new Attribute.
                Array(expectedElementType, buf.toArray(new Attribute[buf.length()]));
    }

    /* *********************************
     * Support for repeating annotations
     ***********************************/

    /**
     * This context contains all the information needed to synthesize new
     * annotations trees for repeating annotations.
     */
    private class AnnotationContext<T extends Attribute.Compound> {
        public final Env<AttrContext> env;
        public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
        public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
        public final boolean isTypeCompound;

        public AnnotationContext(Env<AttrContext> env,
                                 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
                                 Map<T, JCDiagnostic.DiagnosticPosition> pos,
                                 boolean isTypeCompound) {
            Assert.checkNonNull(env);
            Assert.checkNonNull(annotated);
            Assert.checkNonNull(pos);

            this.env = env;
            this.annotated = annotated;
            this.pos = pos;
            this.isTypeCompound = isTypeCompound;
        }
    }

    /* Process repeated annotations. This method returns the
     * synthesized container annotation or null IFF all repeating
     * annotation are invalid.  This method reports errors/warnings.
     */
    private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
            AnnotationContext<T> ctx, Symbol on, boolean isTypeParam)
    {
        T firstOccurrence = annotations.head;
        List<Attribute> repeated = List.nil();
        Type origAnnoType = null;
        Type arrayOfOrigAnnoType = null;
        Type targetContainerType = null;
        MethodSymbol containerValueSymbol = null;

        Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1

        int count = 0;
        for (List<T> al = annotations; !al.isEmpty(); al = al.tail) {
            count++;

            // There must be more than a single anno in the annotation list
            Assert.check(count > 1 || !al.tail.isEmpty());

            T currentAnno = al.head;

            origAnnoType = currentAnno.type;
            if (arrayOfOrigAnnoType == null) {
                arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
            }

            // Only report errors if this isn't the first occurrence I.E. count > 1
            boolean reportError = count > 1;
            Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError);
            if (currentContainerType == null) {
                continue;
            }
            // Assert that the target Container is == for all repeated
            // annos of the same annotation type, the types should
            // come from the same Symbol, i.e. be '=='
            Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
            targetContainerType = currentContainerType;

            containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));

            if (containerValueSymbol == null) { // Check of CA type failed
                // errors are already reported
                continue;
            }

            repeated = repeated.prepend(currentAnno);
        }

        if (!repeated.isEmpty() && targetContainerType == null) {
            log.error(ctx.pos.get(annotations.head), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
            return null;
        }

        if (!repeated.isEmpty()) {
            repeated = repeated.reverse();
            DiagnosticPosition pos = ctx.pos.get(firstOccurrence);
            TreeMaker m = make.at(pos);
            Pair<MethodSymbol, Attribute> p =
                    new Pair<MethodSymbol, Attribute>(containerValueSymbol,
                            new Attribute.Array(arrayOfOrigAnnoType, repeated));
            if (ctx.isTypeCompound) {
                /* TODO: the following code would be cleaner:
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
                        ((Attribute.TypeCompound)annotations.head).position);
                JCTypeAnnotation annoTree = m.TypeAnnotation(at);
                at = attributeTypeAnnotation(annoTree, targetContainerType, ctx.env);
                */
                // However, we directly construct the TypeCompound to keep the
                // direct relation to the contained TypeCompounds.
                Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
                        ((Attribute.TypeCompound)annotations.head).position);

                JCAnnotation annoTree = m.TypeAnnotation(at);
                if (!chk.validateAnnotationDeferErrors(annoTree))
                    log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));

                if (!chk.isTypeAnnotation(annoTree, isTypeParam)) {
                    log.error(pos, isTypeParam ? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
                                               : Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
                }

                at.setSynthesized(true);

                @SuppressWarnings("unchecked")
                T x = (T) at;
                return x;
            } else {
                Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
                JCAnnotation annoTree = m.Annotation(c);

                if (!chk.annotationApplicable(annoTree, on)) {
                    log.error(annoTree.pos(),
                              Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on));
                }

                if (!chk.validateAnnotationDeferErrors(annoTree))
                    log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));

                c = attributeAnnotation(annoTree, targetContainerType, ctx.env);
                c.setSynthesized(true);

                @SuppressWarnings("unchecked")
                T x = (T) c;
                return x;
            }
        } else {
            return null; // errors should have been reported elsewhere
        }
    }

    /**
     * Fetches the actual Type that should be the containing annotation.
     */
    private Type getContainingType(Attribute.Compound currentAnno,
                                   DiagnosticPosition pos,
                                   boolean reportError)
    {
        Type origAnnoType = currentAnno.type;
        TypeSymbol origAnnoDecl = origAnnoType.tsym;

        // Fetch the Repeatable annotation from the current
        // annotation's declaration, or null if it has none
        Attribute.Compound ca = origAnnoDecl.getAnnotationTypeMetadata().getRepeatable();
        if (ca == null) { // has no Repeatable annotation
            if (reportError)
                log.error(pos, Errors.DuplicateAnnotationMissingContainer(origAnnoType));
            return null;
        }

        return filterSame(extractContainingType(ca, pos, origAnnoDecl),
                origAnnoType);
    }

    // returns null if t is same as 's', returns 't' otherwise
    private Type filterSame(Type t, Type s) {
        if (t == null || s == null) {
            return t;
        }

        return types.isSameType(t, s) ? null : t;
    }

    /** Extract the actual Type to be used for a containing annotation. */
    private Type extractContainingType(Attribute.Compound ca,
                                       DiagnosticPosition pos,
                                       TypeSymbol annoDecl)
    {
        // The next three checks check that the Repeatable annotation
        // on the declaration of the annotation type that is repeating is
        // valid.

        // Repeatable must have at least one element
        if (ca.values.isEmpty()) {
            log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
            return null;
        }
        Pair<MethodSymbol,Attribute> p = ca.values.head;
        Name name = p.fst.name;
        if (name != names.value) { // should contain only one element, named "value"
            log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
            return null;
        }
        if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
            log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
            return null;
        }

        return ((Attribute.Class)p.snd).getValue();
    }

    /* Validate that the suggested targetContainerType Type is a valid
     * container type for repeated instances of originalAnnoType
     * annotations. Return null and report errors if this is not the
     * case, return the MethodSymbol of the value element in
     * targetContainerType if it is suitable (this is needed to
     * synthesize the container). */
    private MethodSymbol validateContainer(Type targetContainerType,
                                           Type originalAnnoType,
                                           DiagnosticPosition pos) {
        MethodSymbol containerValueSymbol = null;
        boolean fatalError = false;

        // Validate that there is a (and only 1) value method
        Scope scope = targetContainerType.tsym.members();
        int nr_value_elems = 0;
        boolean error = false;
        for(Symbol elm : scope.getSymbolsByName(names.value)) {
            nr_value_elems++;

            if (nr_value_elems == 1 &&
                    elm.kind == MTH) {
                containerValueSymbol = (MethodSymbol)elm;
            } else {
                error = true;
            }
        }
        if (error) {
            log.error(pos,
                      Errors.InvalidRepeatableAnnotationMultipleValues(targetContainerType,
                                                                       nr_value_elems));
            return null;
        } else if (nr_value_elems == 0) {
            log.error(pos,
                      Errors.InvalidRepeatableAnnotationNoValue(targetContainerType));
            return null;
        }

        // validate that the 'value' element is a method
        // probably "impossible" to fail this
        if (containerValueSymbol.kind != MTH) {
            log.error(pos,
                    Errors.InvalidRepeatableAnnotationInvalidValue(targetContainerType));
            fatalError = true;
        }

        // validate that the 'value' element has the correct return type
        // i.e. array of original anno
        Type valueRetType = containerValueSymbol.type.getReturnType();
        Type expectedType = types.makeArrayType(originalAnnoType);
        if (!(types.isArray(valueRetType) &&
                types.isSameType(expectedType, valueRetType))) {
            log.error(pos,
                      Errors.InvalidRepeatableAnnotationValueReturn(targetContainerType,
                                                                    valueRetType,
                                                                    expectedType));
            fatalError = true;
        }

        return fatalError ? null : containerValueSymbol;
    }

    private <T extends Attribute.Compound> T makeContainerAnnotation(List<T> toBeReplaced,
            AnnotationContext<T> ctx, Symbol sym, boolean isTypeParam)
    {
        // Process repeated annotations
        T validRepeated =
                processRepeatedAnnotations(toBeReplaced, ctx, sym, isTypeParam);

        if (validRepeated != null) {
            // Check that the container isn't manually
            // present along with repeated instances of
            // its contained annotation.
            ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
            if (manualContainer != null) {
                log.error(ctx.pos.get(manualContainer.first()),
                          Errors.InvalidRepeatableAnnotationRepeatedAndContainerPresent(manualContainer.first().type.tsym));
            }
        }

        // A null return will delete the Placeholder
        return validRepeated;
    }

    /********************
     * Type annotations *
     ********************/

    /**
     * Attribute the list of annotations and enter them onto s.
     */
    public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env,
            Symbol s, DiagnosticPosition deferPos, boolean isTypeParam)
    {
        Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
        DiagnosticPosition prevLintPos = null;

        if (deferPos != null) {
            prevLintPos = deferredLintHandler.setPos(deferPos);
        }
        try {
            annotateNow(s, annotations, env, true, isTypeParam);
        } finally {
            if (prevLintPos != null)
                deferredLintHandler.setPos(prevLintPos);
            log.useSource(prev);
        }
    }

    /**
     * Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
     */
    public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym,
            DiagnosticPosition deferPos)
    {
        Assert.checkNonNull(sym);
        normal(() -> tree.accept(new TypeAnnotate(env, sym, deferPos)));
    }

    /**
     * Apply the annotations to the particular type.
     */
    public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) {
        typeAnnotation(() -> {
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
            Assert.check(annotations.size() == compounds.size());
            storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
        });
    }

    /**
     * Apply the annotations to the particular type.
     */
    public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) {
        typeAnnotation(() -> {
            List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
            Assert.check(annotations.size() == compounds.size());
        });
    }

    /**
     * We need to use a TreeScanner, because it is not enough to visit the top-level
     * annotations. We also need to visit type arguments, etc.
     */
    private class TypeAnnotate extends TreeScanner {
        private final Env<AttrContext> env;
        private final Symbol sym;
        private DiagnosticPosition deferPos;

        public TypeAnnotate(Env<AttrContext> env, Symbol sym, DiagnosticPosition deferPos) {

            this.env = env;
            this.sym = sym;
            this.deferPos = deferPos;
        }

        @Override
        public void visitAnnotatedType(JCAnnotatedType tree) {
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
            scan(tree.underlyingType);
        }

        @Override
        public void visitTypeParameter(JCTypeParameter tree) {
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, true);
            scan(tree.bounds);
        }

        @Override
        public void visitNewArray(JCNewArray tree) {
            enterTypeAnnotations(tree.annotations, env, sym, deferPos, false);
            for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
                enterTypeAnnotations(dimAnnos, env, sym, deferPos, false);
            scan(tree.elemtype);
            scan(tree.elems);
        }

        @Override
        public void visitMethodDef(JCMethodDecl tree) {
            scan(tree.mods);
            scan(tree.restype);
            scan(tree.typarams);
            scan(tree.recvparam);
            scan(tree.params);
            scan(tree.thrown);
            scan(tree.defaultValue);
            // Do not annotate the body, just the signature.
        }

        @Override
        public void visitVarDef(JCVariableDecl tree) {
            DiagnosticPosition prevPos = deferPos;
            deferPos = tree.pos();
            try {
                if (sym != null && sym.kind == VAR) {
                    // Don't visit a parameter once when the sym is the method
                    // and once when the sym is the parameter.
                    scan(tree.mods);
                    scan(tree.vartype);
                }
                scan(tree.init);
            } finally {
                deferPos = prevPos;
            }
        }

        @Override
        public void visitClassDef(JCClassDecl tree) {
            // We can only hit a classdef if it is declared within
            // a method. Ignore it - the class will be visited
            // separately later.
        }

        @Override
        public void visitNewClass(JCNewClass tree) {
            scan(tree.encl);
            scan(tree.typeargs);
            scan(tree.clazz);
            scan(tree.args);
            // the anonymous class instantiation if any will be visited separately.
        }
    }

    /*********************
     * Completer support *
     *********************/

    private AnnotationTypeCompleter theSourceCompleter = new AnnotationTypeCompleter() {
        @Override
        public void complete(ClassSymbol sym) throws CompletionFailure {
            Env<AttrContext> context = typeEnvs.get(sym);
            Annotate.this.attributeAnnotationType(context);
        }
    };

    /* Last stage completer to enter just enough annotations to have a prototype annotation type.
     * This currently means entering @Target and @Repetable.
     */
    public AnnotationTypeCompleter annotationTypeSourceCompleter() {
        return theSourceCompleter;
    }

    private void attributeAnnotationType(Env<AttrContext> env) {
        Assert.check(((JCClassDecl)env.tree).sym.isAnnotationType(),
                "Trying to annotation type complete a non-annotation type");

        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
        try {
            JCClassDecl tree = (JCClassDecl)env.tree;
            AnnotationTypeVisitor v = new AnnotationTypeVisitor(attr, chk, syms, typeEnvs);
            v.scanAnnotationType(tree);
            tree.sym.getAnnotationTypeMetadata().setRepeatable(v.repeatable);
            tree.sym.getAnnotationTypeMetadata().setTarget(v.target);
        } finally {
            log.useSource(prev);
        }
    }

    public Attribute unfinishedDefaultValue() {
        return theUnfinishedDefaultValue;
    }

    public static interface AnnotationTypeCompleter {
        void complete(ClassSymbol sym) throws CompletionFailure;
    }

    /** Visitor to determine a prototype annotation type for a class declaring an annotation type.
     *
     *  <p><b>This is NOT part of any supported API.
     *  If you write code that depends on this, you do so at your own risk.
     *  This code and its internal interfaces are subject to change or
     *  deletion without notice.</b>
     */
    public class AnnotationTypeVisitor extends TreeScanner {
        private Env<AttrContext> env;

        private final Attr attr;
        private final Check check;
        private final Symtab tab;
        private final TypeEnvs typeEnvs;

        private Compound target;
        private Compound repeatable;

        public AnnotationTypeVisitor(Attr attr, Check check, Symtab tab, TypeEnvs typeEnvs) {
            this.attr = attr;
            this.check = check;
            this.tab = tab;
            this.typeEnvs = typeEnvs;
        }

        public Compound getRepeatable() {
            return repeatable;
        }

        public Compound getTarget() {
            return target;
        }

        public void scanAnnotationType(JCClassDecl decl) {
            visitClassDef(decl);
        }

        @Override
        public void visitClassDef(JCClassDecl tree) {
            Env<AttrContext> prevEnv = env;
            env = typeEnvs.get(tree.sym);
            try {
                scan(tree.mods); // look for repeatable and target
                // don't descend into body
            } finally {
                env = prevEnv;
            }
        }

        @Override
        public void visitAnnotation(JCAnnotation tree) {
            Type t = tree.annotationType.type;
            if (t == null) {
                t = attr.attribType(tree.annotationType, env);
                tree.annotationType.type = t = check.checkType(tree.annotationType.pos(), t, tab.annotationType);
            }

            if (t == tab.annotationTargetType) {
                target = Annotate.this.attributeAnnotation(tree, tab.annotationTargetType, env);
            } else if (t == tab.repeatableType) {
                repeatable = Annotate.this.attributeAnnotation(tree, tab.repeatableType, env);
            }
        }
    }

    /** Represents the semantics of an Annotation Type.
     *
     *  <p><b>This is NOT part of any supported API.
     *  If you write code that depends on this, you do so at your own risk.
     *  This code and its internal interfaces are subject to change or
     *  deletion without notice.</b>
     */
    public static class AnnotationTypeMetadata {
        final ClassSymbol metaDataFor;
        private Compound target;
        private Compound repeatable;
        private AnnotationTypeCompleter annotationTypeCompleter;

        public AnnotationTypeMetadata(ClassSymbol metaDataFor, AnnotationTypeCompleter annotationTypeCompleter) {
            this.metaDataFor = metaDataFor;
            this.annotationTypeCompleter = annotationTypeCompleter;
        }

        private void init() {
            // Make sure metaDataFor is member entered
            while (!metaDataFor.isCompleted())
                metaDataFor.complete();

            if (annotationTypeCompleter != null) {
                AnnotationTypeCompleter c = annotationTypeCompleter;
                annotationTypeCompleter = null;
                c.complete(metaDataFor);
            }
        }

        public void complete() {
            init();
        }

        public Compound getRepeatable() {
            init();
            return repeatable;
        }

        public void setRepeatable(Compound repeatable) {
            Assert.checkNull(this.repeatable);
            this.repeatable = repeatable;
        }

        public Compound getTarget() {
            init();
            return target;
        }

        public void setTarget(Compound target) {
            Assert.checkNull(this.target);
                this.target = target;
        }

        public Set<MethodSymbol> getAnnotationElements() {
            init();
            Set<MethodSymbol> members = new LinkedHashSet<>();
            WriteableScope s = metaDataFor.members();
            Iterable<Symbol> ss = s.getSymbols(NON_RECURSIVE);
            for (Symbol sym : ss)
                if (sym.kind == MTH &&
                        sym.name != sym.name.table.names.clinit &&
                        (sym.flags() & SYNTHETIC) == 0)
                    members.add((MethodSymbol)sym);
            return members;
        }

        public Set<MethodSymbol> getAnnotationElementsWithDefault() {
            init();
            Set<MethodSymbol> members = getAnnotationElements();
            Set<MethodSymbol> res = new LinkedHashSet<>();
            for (MethodSymbol m : members)
                if (m.defaultValue != null)
                    res.add(m);
            return res;
        }

        @Override
        public String toString() {
            return "Annotation type for: " + metaDataFor;
        }

        public boolean isMetadataForAnnotationType() { return true; }

        public static AnnotationTypeMetadata notAnAnnotationType() {
            return NOT_AN_ANNOTATION_TYPE;
        }

        private static final AnnotationTypeMetadata NOT_AN_ANNOTATION_TYPE =
                new AnnotationTypeMetadata(null, null) {
                    @Override
                    public void complete() {
                    } // do nothing

                    @Override
                    public String toString() {
                        return "Not an annotation type";
                    }

                    @Override
                    public Set<MethodSymbol> getAnnotationElements() {
                        return new LinkedHashSet<>(0);
                    }

                    @Override
                    public Set<MethodSymbol> getAnnotationElementsWithDefault() {
                        return new LinkedHashSet<>(0);
                    }

                    @Override
                    public boolean isMetadataForAnnotationType() {
                        return false;
                    }

                    @Override
                    public Compound getTarget() {
                        return null;
                    }

                    @Override
                    public Compound getRepeatable() {
                        return null;
                    }
                };
    }

    public void newRound() {
        blockCount = 1;
    }
}

com/sun/tools/javac/comp/Annotate.java

 

JDK 11 jdk.crypto.cryptoki.jmod - Crypto KI Module

JDK 11 jdk.charsets.jmod - Charsets Module

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2020-08-13, 20855👍, 0💬