8022260: Rename javac.code.Annotations to javac.code.SymbolMetadata

Mon, 09 Sep 2013 09:58:20 +0200

author
jfranck
date
Mon, 09 Sep 2013 09:58:20 +0200
changeset 2014
6cffcd15a17e
parent 2013
2de3750d65a5
child 2015
a4b9a8859e58

8022260: Rename javac.code.Annotations to javac.code.SymbolMetadata
Reviewed-by: jfranck, jjg
Contributed-by: Andreas Lundblad <andreas.lundblad@oracle.com>

src/share/classes/com/sun/tools/javac/code/Annotations.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java file | annotate | diff | comparison | revisions
test/tools/javac/lib/DPrinter.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Annotations.java	Sun Sep 08 11:54:21 2013 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,451 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package com.sun.tools.javac.code;
    1.30 -
    1.31 -import java.util.Map;
    1.32 -
    1.33 -import javax.tools.JavaFileObject;
    1.34 -
    1.35 -import com.sun.tools.javac.comp.Annotate;
    1.36 -import com.sun.tools.javac.comp.AttrContext;
    1.37 -import com.sun.tools.javac.comp.Env;
    1.38 -import com.sun.tools.javac.util.*;
    1.39 -import com.sun.tools.javac.util.Assert;
    1.40 -import com.sun.tools.javac.util.List;
    1.41 -import com.sun.tools.javac.util.Log;
    1.42 -import com.sun.tools.javac.util.Pair;
    1.43 -import static com.sun.tools.javac.code.Kinds.PCK;
    1.44 -
    1.45 -/**
    1.46 - * Container for all annotations (attributes in javac) on a Symbol.
    1.47 - *
    1.48 - * This class is explicitly mutable. Its contents will change when attributes
    1.49 - * are annotated onto the Symbol. However this class depends on the facts that
    1.50 - * List (in javac) is immutable.
    1.51 - *
    1.52 - * An instance of this class can be in one of three states:
    1.53 - *
    1.54 - * NOT_STARTED indicates that the Symbol this instance belongs to has not been
    1.55 - * annotated (yet). Specifically if the declaration is not annotated this
    1.56 - * instance will never move past NOT_STARTED. You can never go back to
    1.57 - * NOT_STARTED.
    1.58 - *
    1.59 - * IN_PROGRESS annotations have been found on the declaration. Will be processed
    1.60 - * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
    1.61 - * of attributes (and this moves out of the IN_PROGRESS state).
    1.62 - *
    1.63 - * "unnamed" this Annotations contains some attributes, possibly the final set.
    1.64 - * While in this state you can only prepend or append to the attributes not set
    1.65 - * it directly. You can also move back to the IN_PROGRESS state using reset().
    1.66 - *
    1.67 - * <p><b>This is NOT part of any supported API. If you write code that depends
    1.68 - * on this, you do so at your own risk. This code and its internal interfaces
    1.69 - * are subject to change or deletion without notice.</b>
    1.70 - */
    1.71 -public class Annotations {
    1.72 -
    1.73 -    private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
    1.74 -    private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
    1.75 -
    1.76 -    /*
    1.77 -     * This field should never be null
    1.78 -     */
    1.79 -    private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
    1.80 -
    1.81 -    /*
    1.82 -     * Type attributes for this symbol.
    1.83 -     * This field should never be null.
    1.84 -     */
    1.85 -    private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil();
    1.86 -
    1.87 -    /*
    1.88 -     * Type attributes of initializers in this class.
    1.89 -     * Unused if the current symbol is not a ClassSymbol.
    1.90 -     */
    1.91 -    private List<Attribute.TypeCompound> init_type_attributes = List.<Attribute.TypeCompound>nil();
    1.92 -
    1.93 -    /*
    1.94 -     * Type attributes of class initializers in this class.
    1.95 -     * Unused if the current symbol is not a ClassSymbol.
    1.96 -     */
    1.97 -    private List<Attribute.TypeCompound> clinit_type_attributes = List.<Attribute.TypeCompound>nil();
    1.98 -
    1.99 -    /*
   1.100 -     * The Symbol this Annotations instance belongs to
   1.101 -     */
   1.102 -    private final Symbol sym;
   1.103 -
   1.104 -    public Annotations(Symbol sym) {
   1.105 -        this.sym = sym;
   1.106 -    }
   1.107 -
   1.108 -    public List<Attribute.Compound> getDeclarationAttributes() {
   1.109 -        return filterDeclSentinels(attributes);
   1.110 -    }
   1.111 -
   1.112 -    public List<Attribute.TypeCompound> getTypeAttributes() {
   1.113 -        return type_attributes;
   1.114 -    }
   1.115 -
   1.116 -    public List<Attribute.TypeCompound> getInitTypeAttributes() {
   1.117 -        return init_type_attributes;
   1.118 -    }
   1.119 -
   1.120 -    public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
   1.121 -        return clinit_type_attributes;
   1.122 -    }
   1.123 -
   1.124 -    public void setDeclarationAttributes(List<Attribute.Compound> a) {
   1.125 -        Assert.check(pendingCompletion() || !isStarted());
   1.126 -        if (a == null) {
   1.127 -            throw new NullPointerException();
   1.128 -        }
   1.129 -        attributes = a;
   1.130 -    }
   1.131 -
   1.132 -    public void setTypeAttributes(List<Attribute.TypeCompound> a) {
   1.133 -        if (a == null) {
   1.134 -            throw new NullPointerException();
   1.135 -        }
   1.136 -        type_attributes = a;
   1.137 -    }
   1.138 -
   1.139 -    public void setInitTypeAttributes(List<Attribute.TypeCompound> a) {
   1.140 -        if (a == null) {
   1.141 -            throw new NullPointerException();
   1.142 -        }
   1.143 -        init_type_attributes = a;
   1.144 -    }
   1.145 -
   1.146 -    public void setClassInitTypeAttributes(List<Attribute.TypeCompound> a) {
   1.147 -        if (a == null) {
   1.148 -            throw new NullPointerException();
   1.149 -        }
   1.150 -        clinit_type_attributes = a;
   1.151 -    }
   1.152 -
   1.153 -    public void setAttributes(Annotations other) {
   1.154 -        if (other == null) {
   1.155 -            throw new NullPointerException();
   1.156 -        }
   1.157 -        setDeclarationAttributes(other.getDeclarationAttributes());
   1.158 -        setTypeAttributes(other.getTypeAttributes());
   1.159 -        setInitTypeAttributes(other.getInitTypeAttributes());
   1.160 -        setClassInitTypeAttributes(other.getClassInitTypeAttributes());
   1.161 -    }
   1.162 -
   1.163 -    public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) {
   1.164 -        Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK));
   1.165 -        this.setDeclarationAttributes(getAttributesForCompletion(ctx));
   1.166 -    }
   1.167 -
   1.168 -    public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.TypeCompound> ctx) {
   1.169 -        this.appendUniqueTypes(getAttributesForCompletion(ctx));
   1.170 -    }
   1.171 -
   1.172 -    private <T extends Attribute.Compound> List<T> getAttributesForCompletion(
   1.173 -            final Annotate.AnnotateRepeatedContext<T> ctx) {
   1.174 -
   1.175 -        Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated;
   1.176 -        boolean atLeastOneRepeated = false;
   1.177 -        List<T> buf = List.<T>nil();
   1.178 -        for (ListBuffer<T> lb : annotated.values()) {
   1.179 -            if (lb.size() == 1) {
   1.180 -                buf = buf.prepend(lb.first());
   1.181 -            } else { // repeated
   1.182 -                // This will break when other subtypes of Attributs.Compound
   1.183 -                // are introduced, because PlaceHolder is a subtype of TypeCompound.
   1.184 -                T res;
   1.185 -                @SuppressWarnings("unchecked")
   1.186 -                T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym);
   1.187 -                res = ph;
   1.188 -                buf = buf.prepend(res);
   1.189 -                atLeastOneRepeated = true;
   1.190 -            }
   1.191 -        }
   1.192 -
   1.193 -        if (atLeastOneRepeated) {
   1.194 -            // The Symbol s is now annotated with a combination of
   1.195 -            // finished non-repeating annotations and placeholders for
   1.196 -            // repeating annotations.
   1.197 -            //
   1.198 -            // We need to do this in two passes because when creating
   1.199 -            // a container for a repeating annotation we must
   1.200 -            // guarantee that the @Repeatable on the
   1.201 -            // contained annotation is fully annotated
   1.202 -            //
   1.203 -            // The way we force this order is to do all repeating
   1.204 -            // annotations in a pass after all non-repeating are
   1.205 -            // finished. This will work because @Repeatable
   1.206 -            // is non-repeating and therefore will be annotated in the
   1.207 -            // fist pass.
   1.208 -
   1.209 -            // Queue a pass that will replace Attribute.Placeholders
   1.210 -            // with Attribute.Compound (made from synthesized containers).
   1.211 -            ctx.annotateRepeated(new Annotate.Annotator() {
   1.212 -                @Override
   1.213 -                public String toString() {
   1.214 -                    return "repeated annotation pass of: " + sym + " in: " + sym.owner;
   1.215 -                }
   1.216 -
   1.217 -                @Override
   1.218 -                public void enterAnnotation() {
   1.219 -                    complete(ctx);
   1.220 -                }
   1.221 -            });
   1.222 -        }
   1.223 -        // Add non-repeating attributes
   1.224 -        return buf.reverse();
   1.225 -    }
   1.226 -
   1.227 -    public Annotations reset() {
   1.228 -        attributes = DECL_IN_PROGRESS;
   1.229 -        return this;
   1.230 -    }
   1.231 -
   1.232 -    public boolean isEmpty() {
   1.233 -        return !isStarted()
   1.234 -                || pendingCompletion()
   1.235 -                || attributes.isEmpty();
   1.236 -    }
   1.237 -
   1.238 -    public boolean isTypesEmpty() {
   1.239 -        return type_attributes.isEmpty();
   1.240 -    }
   1.241 -
   1.242 -    public boolean pendingCompletion() {
   1.243 -        return attributes == DECL_IN_PROGRESS;
   1.244 -    }
   1.245 -
   1.246 -    public Annotations append(List<Attribute.Compound> l) {
   1.247 -        attributes = filterDeclSentinels(attributes);
   1.248 -
   1.249 -        if (l.isEmpty()) {
   1.250 -            ; // no-op
   1.251 -        } else if (attributes.isEmpty()) {
   1.252 -            attributes = l;
   1.253 -        } else {
   1.254 -            attributes = attributes.appendList(l);
   1.255 -        }
   1.256 -        return this;
   1.257 -    }
   1.258 -
   1.259 -    public Annotations appendUniqueTypes(List<Attribute.TypeCompound> l) {
   1.260 -        if (l.isEmpty()) {
   1.261 -            ; // no-op
   1.262 -        } else if (type_attributes.isEmpty()) {
   1.263 -            type_attributes = l;
   1.264 -        } else {
   1.265 -            // TODO: in case we expect a large number of annotations, this
   1.266 -            // might be inefficient.
   1.267 -            for (Attribute.TypeCompound tc : l) {
   1.268 -                if (!type_attributes.contains(tc))
   1.269 -                    type_attributes = type_attributes.append(tc);
   1.270 -            }
   1.271 -        }
   1.272 -        return this;
   1.273 -    }
   1.274 -
   1.275 -    public Annotations appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
   1.276 -        if (l.isEmpty()) {
   1.277 -            ; // no-op
   1.278 -        } else if (init_type_attributes.isEmpty()) {
   1.279 -            init_type_attributes = l;
   1.280 -        } else {
   1.281 -            init_type_attributes = init_type_attributes.appendList(l);
   1.282 -        }
   1.283 -        return this;
   1.284 -    }
   1.285 -
   1.286 -    public Annotations appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
   1.287 -        if (l.isEmpty()) {
   1.288 -            ; // no-op
   1.289 -        } else if (clinit_type_attributes.isEmpty()) {
   1.290 -            clinit_type_attributes = l;
   1.291 -        } else {
   1.292 -            clinit_type_attributes = clinit_type_attributes.appendList(l);
   1.293 -        }
   1.294 -        return this;
   1.295 -    }
   1.296 -
   1.297 -    public Annotations prepend(List<Attribute.Compound> l) {
   1.298 -        attributes = filterDeclSentinels(attributes);
   1.299 -
   1.300 -        if (l.isEmpty()) {
   1.301 -            ; // no-op
   1.302 -        } else if (attributes.isEmpty()) {
   1.303 -            attributes = l;
   1.304 -        } else {
   1.305 -            attributes = attributes.prependList(l);
   1.306 -        }
   1.307 -        return this;
   1.308 -    }
   1.309 -
   1.310 -    private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) {
   1.311 -        return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
   1.312 -                ? List.<Attribute.Compound>nil()
   1.313 -                : a;
   1.314 -    }
   1.315 -
   1.316 -    private boolean isStarted() {
   1.317 -        return attributes != DECL_NOT_STARTED;
   1.318 -    }
   1.319 -
   1.320 -    private List<Attribute.Compound> getPlaceholders() {
   1.321 -        List<Attribute.Compound> res = List.<Attribute.Compound>nil();
   1.322 -        for (Attribute.Compound a : filterDeclSentinels(attributes)) {
   1.323 -            if (a instanceof Placeholder) {
   1.324 -                res = res.prepend(a);
   1.325 -            }
   1.326 -        }
   1.327 -        return res.reverse();
   1.328 -    }
   1.329 -
   1.330 -    private List<Attribute.TypeCompound> getTypePlaceholders() {
   1.331 -        List<Attribute.TypeCompound> res = List.<Attribute.TypeCompound>nil();
   1.332 -        for (Attribute.TypeCompound a : type_attributes) {
   1.333 -            if (a instanceof Placeholder) {
   1.334 -                res = res.prepend(a);
   1.335 -            }
   1.336 -        }
   1.337 -        return res.reverse();
   1.338 -    }
   1.339 -
   1.340 -    /*
   1.341 -     * Replace Placeholders for repeating annotations with their containers
   1.342 -     */
   1.343 -    private <T extends Attribute.Compound> void complete(Annotate.AnnotateRepeatedContext<T> ctx) {
   1.344 -        Log log = ctx.log;
   1.345 -        Env<AttrContext> env = ctx.env;
   1.346 -        JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
   1.347 -        try {
   1.348 -            // TODO: can we reduce duplication in the following branches?
   1.349 -            if (ctx.isTypeCompound) {
   1.350 -                Assert.check(!isTypesEmpty());
   1.351 -
   1.352 -                if (isTypesEmpty()) {
   1.353 -                    return;
   1.354 -                }
   1.355 -
   1.356 -                List<Attribute.TypeCompound> result = List.nil();
   1.357 -                for (Attribute.TypeCompound a : getTypeAttributes()) {
   1.358 -                    if (a instanceof Placeholder) {
   1.359 -                        @SuppressWarnings("unchecked")
   1.360 -                        Placeholder<Attribute.TypeCompound> ph = (Placeholder<Attribute.TypeCompound>) a;
   1.361 -                        Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext());
   1.362 -
   1.363 -                        if (null != replacement) {
   1.364 -                            result = result.prepend(replacement);
   1.365 -                        }
   1.366 -                    } else {
   1.367 -                        result = result.prepend(a);
   1.368 -                    }
   1.369 -                }
   1.370 -
   1.371 -                type_attributes = result.reverse();
   1.372 -
   1.373 -                Assert.check(Annotations.this.getTypePlaceholders().isEmpty());
   1.374 -            } else {
   1.375 -                Assert.check(!pendingCompletion());
   1.376 -
   1.377 -                if (isEmpty()) {
   1.378 -                    return;
   1.379 -                }
   1.380 -
   1.381 -                List<Attribute.Compound> result = List.nil();
   1.382 -                for (Attribute.Compound a : getDeclarationAttributes()) {
   1.383 -                    if (a instanceof Placeholder) {
   1.384 -                        @SuppressWarnings("unchecked")
   1.385 -                        Attribute.Compound replacement = replaceOne((Placeholder<T>) a, ctx);
   1.386 -
   1.387 -                        if (null != replacement) {
   1.388 -                            result = result.prepend(replacement);
   1.389 -                        }
   1.390 -                    } else {
   1.391 -                        result = result.prepend(a);
   1.392 -                    }
   1.393 -                }
   1.394 -
   1.395 -                attributes = result.reverse();
   1.396 -
   1.397 -                Assert.check(Annotations.this.getPlaceholders().isEmpty());
   1.398 -            }
   1.399 -        } finally {
   1.400 -            log.useSource(oldSource);
   1.401 -        }
   1.402 -    }
   1.403 -
   1.404 -    private <T extends Attribute.Compound> T replaceOne(Placeholder<T> placeholder, Annotate.AnnotateRepeatedContext<T> ctx) {
   1.405 -        Log log = ctx.log;
   1.406 -
   1.407 -        // Process repeated annotations
   1.408 -        T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
   1.409 -
   1.410 -        if (validRepeated != null) {
   1.411 -            // Check that the container isn't manually
   1.412 -            // present along with repeated instances of
   1.413 -            // its contained annotation.
   1.414 -            ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
   1.415 -            if (manualContainer != null) {
   1.416 -                log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
   1.417 -                        manualContainer.first().type.tsym);
   1.418 -            }
   1.419 -        }
   1.420 -
   1.421 -        // A null return will delete the Placeholder
   1.422 -        return validRepeated;
   1.423 -    }
   1.424 -
   1.425 -    private static class Placeholder<T extends Attribute.Compound> extends Attribute.TypeCompound {
   1.426 -
   1.427 -        private final Annotate.AnnotateRepeatedContext<T> ctx;
   1.428 -        private final List<T> placeholderFor;
   1.429 -        private final Symbol on;
   1.430 -
   1.431 -        public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) {
   1.432 -            super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(),
   1.433 -                    ctx.isTypeCompound ?
   1.434 -                            ((Attribute.TypeCompound)placeholderFor.head).position :
   1.435 -                                null);
   1.436 -            this.ctx = ctx;
   1.437 -            this.placeholderFor = placeholderFor;
   1.438 -            this.on = on;
   1.439 -        }
   1.440 -
   1.441 -        @Override
   1.442 -        public String toString() {
   1.443 -            return "<placeholder: " + placeholderFor + " on: " + on + ">";
   1.444 -        }
   1.445 -
   1.446 -        public List<T> getPlaceholderFor() {
   1.447 -            return placeholderFor;
   1.448 -        }
   1.449 -
   1.450 -        public Annotate.AnnotateRepeatedContext<T> getRepeatedContext() {
   1.451 -            return ctx;
   1.452 -        }
   1.453 -    }
   1.454 -}
     2.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Sun Sep 08 11:54:21 2013 +0100
     2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 09 09:58:20 2013 +0200
     2.3 @@ -98,9 +98,9 @@
     2.4      // <editor-fold defaultstate="collapsed" desc="annotations">
     2.5  
     2.6      /** The attributes of this symbol are contained in this
     2.7 -     * Annotations. The Annotations instance is NOT immutable.
     2.8 +     * SymbolMetadata. The SymbolMetadata instance is NOT immutable.
     2.9       */
    2.10 -    protected Annotations annotations;
    2.11 +    protected SymbolMetadata annotations;
    2.12  
    2.13      /** An accessor method for the attributes of this symbol.
    2.14       *  Attributes of class symbols should be accessed through the accessor
    2.15 @@ -217,19 +217,19 @@
    2.16      public void setTypeAttributes(List<Attribute.TypeCompound> a) {
    2.17          if (annotations != null || a.nonEmpty()) {
    2.18              if (annotations == null)
    2.19 -                annotations = new Annotations(this);
    2.20 +                annotations = new SymbolMetadata(this);
    2.21              annotations.setTypeAttributes(a);
    2.22          }
    2.23      }
    2.24  
    2.25 -    private Annotations initedAnnos() {
    2.26 +    private SymbolMetadata initedAnnos() {
    2.27          if (annotations == null)
    2.28 -            annotations = new Annotations(this);
    2.29 +            annotations = new SymbolMetadata(this);
    2.30          return annotations;
    2.31      }
    2.32  
    2.33      /** This method is intended for debugging only. */
    2.34 -    public Annotations getAnnotations() {
    2.35 +    public SymbolMetadata getAnnotations() {
    2.36          return annotations;
    2.37      }
    2.38  
    2.39 @@ -852,7 +852,7 @@
    2.40          private void mergeAttributes() {
    2.41              if (annotations == null &&
    2.42                  package_info.annotations != null) {
    2.43 -                annotations = new Annotations(this);
    2.44 +                annotations = new SymbolMetadata(this);
    2.45                  annotations.setAttributes(package_info.annotations);
    2.46              }
    2.47          }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java	Mon Sep 09 09:58:20 2013 +0200
     3.3 @@ -0,0 +1,451 @@
     3.4 +/*
     3.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package com.sun.tools.javac.code;
    3.30 +
    3.31 +import java.util.Map;
    3.32 +
    3.33 +import javax.tools.JavaFileObject;
    3.34 +
    3.35 +import com.sun.tools.javac.comp.Annotate;
    3.36 +import com.sun.tools.javac.comp.AttrContext;
    3.37 +import com.sun.tools.javac.comp.Env;
    3.38 +import com.sun.tools.javac.util.*;
    3.39 +import com.sun.tools.javac.util.Assert;
    3.40 +import com.sun.tools.javac.util.List;
    3.41 +import com.sun.tools.javac.util.Log;
    3.42 +import com.sun.tools.javac.util.Pair;
    3.43 +import static com.sun.tools.javac.code.Kinds.PCK;
    3.44 +
    3.45 +/**
    3.46 + * Container for all annotations (attributes in javac) on a Symbol.
    3.47 + *
    3.48 + * This class is explicitly mutable. Its contents will change when attributes
    3.49 + * are annotated onto the Symbol. However this class depends on the facts that
    3.50 + * List (in javac) is immutable.
    3.51 + *
    3.52 + * An instance of this class can be in one of three states:
    3.53 + *
    3.54 + * NOT_STARTED indicates that the Symbol this instance belongs to has not been
    3.55 + * annotated (yet). Specifically if the declaration is not annotated this
    3.56 + * instance will never move past NOT_STARTED. You can never go back to
    3.57 + * NOT_STARTED.
    3.58 + *
    3.59 + * IN_PROGRESS annotations have been found on the declaration. Will be processed
    3.60 + * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
    3.61 + * of attributes (and this moves out of the IN_PROGRESS state).
    3.62 + *
    3.63 + * "unnamed" this SymbolMetadata contains some attributes, possibly the final set.
    3.64 + * While in this state you can only prepend or append to the attributes not set
    3.65 + * it directly. You can also move back to the IN_PROGRESS state using reset().
    3.66 + *
    3.67 + * <p><b>This is NOT part of any supported API. If you write code that depends
    3.68 + * on this, you do so at your own risk. This code and its internal interfaces
    3.69 + * are subject to change or deletion without notice.</b>
    3.70 + */
    3.71 +public class SymbolMetadata {
    3.72 +
    3.73 +    private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
    3.74 +    private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
    3.75 +
    3.76 +    /*
    3.77 +     * This field should never be null
    3.78 +     */
    3.79 +    private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
    3.80 +
    3.81 +    /*
    3.82 +     * Type attributes for this symbol.
    3.83 +     * This field should never be null.
    3.84 +     */
    3.85 +    private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil();
    3.86 +
    3.87 +    /*
    3.88 +     * Type attributes of initializers in this class.
    3.89 +     * Unused if the current symbol is not a ClassSymbol.
    3.90 +     */
    3.91 +    private List<Attribute.TypeCompound> init_type_attributes = List.<Attribute.TypeCompound>nil();
    3.92 +
    3.93 +    /*
    3.94 +     * Type attributes of class initializers in this class.
    3.95 +     * Unused if the current symbol is not a ClassSymbol.
    3.96 +     */
    3.97 +    private List<Attribute.TypeCompound> clinit_type_attributes = List.<Attribute.TypeCompound>nil();
    3.98 +
    3.99 +    /*
   3.100 +     * The Symbol this SymbolMetadata instance belongs to
   3.101 +     */
   3.102 +    private final Symbol sym;
   3.103 +
   3.104 +    public SymbolMetadata(Symbol sym) {
   3.105 +        this.sym = sym;
   3.106 +    }
   3.107 +
   3.108 +    public List<Attribute.Compound> getDeclarationAttributes() {
   3.109 +        return filterDeclSentinels(attributes);
   3.110 +    }
   3.111 +
   3.112 +    public List<Attribute.TypeCompound> getTypeAttributes() {
   3.113 +        return type_attributes;
   3.114 +    }
   3.115 +
   3.116 +    public List<Attribute.TypeCompound> getInitTypeAttributes() {
   3.117 +        return init_type_attributes;
   3.118 +    }
   3.119 +
   3.120 +    public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
   3.121 +        return clinit_type_attributes;
   3.122 +    }
   3.123 +
   3.124 +    public void setDeclarationAttributes(List<Attribute.Compound> a) {
   3.125 +        Assert.check(pendingCompletion() || !isStarted());
   3.126 +        if (a == null) {
   3.127 +            throw new NullPointerException();
   3.128 +        }
   3.129 +        attributes = a;
   3.130 +    }
   3.131 +
   3.132 +    public void setTypeAttributes(List<Attribute.TypeCompound> a) {
   3.133 +        if (a == null) {
   3.134 +            throw new NullPointerException();
   3.135 +        }
   3.136 +        type_attributes = a;
   3.137 +    }
   3.138 +
   3.139 +    public void setInitTypeAttributes(List<Attribute.TypeCompound> a) {
   3.140 +        if (a == null) {
   3.141 +            throw new NullPointerException();
   3.142 +        }
   3.143 +        init_type_attributes = a;
   3.144 +    }
   3.145 +
   3.146 +    public void setClassInitTypeAttributes(List<Attribute.TypeCompound> a) {
   3.147 +        if (a == null) {
   3.148 +            throw new NullPointerException();
   3.149 +        }
   3.150 +        clinit_type_attributes = a;
   3.151 +    }
   3.152 +
   3.153 +    public void setAttributes(SymbolMetadata other) {
   3.154 +        if (other == null) {
   3.155 +            throw new NullPointerException();
   3.156 +        }
   3.157 +        setDeclarationAttributes(other.getDeclarationAttributes());
   3.158 +        setTypeAttributes(other.getTypeAttributes());
   3.159 +        setInitTypeAttributes(other.getInitTypeAttributes());
   3.160 +        setClassInitTypeAttributes(other.getClassInitTypeAttributes());
   3.161 +    }
   3.162 +
   3.163 +    public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) {
   3.164 +        Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK));
   3.165 +        this.setDeclarationAttributes(getAttributesForCompletion(ctx));
   3.166 +    }
   3.167 +
   3.168 +    public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.TypeCompound> ctx) {
   3.169 +        this.appendUniqueTypes(getAttributesForCompletion(ctx));
   3.170 +    }
   3.171 +
   3.172 +    private <T extends Attribute.Compound> List<T> getAttributesForCompletion(
   3.173 +            final Annotate.AnnotateRepeatedContext<T> ctx) {
   3.174 +
   3.175 +        Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated;
   3.176 +        boolean atLeastOneRepeated = false;
   3.177 +        List<T> buf = List.<T>nil();
   3.178 +        for (ListBuffer<T> lb : annotated.values()) {
   3.179 +            if (lb.size() == 1) {
   3.180 +                buf = buf.prepend(lb.first());
   3.181 +            } else { // repeated
   3.182 +                // This will break when other subtypes of Attributs.Compound
   3.183 +                // are introduced, because PlaceHolder is a subtype of TypeCompound.
   3.184 +                T res;
   3.185 +                @SuppressWarnings("unchecked")
   3.186 +                T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym);
   3.187 +                res = ph;
   3.188 +                buf = buf.prepend(res);
   3.189 +                atLeastOneRepeated = true;
   3.190 +            }
   3.191 +        }
   3.192 +
   3.193 +        if (atLeastOneRepeated) {
   3.194 +            // The Symbol s is now annotated with a combination of
   3.195 +            // finished non-repeating annotations and placeholders for
   3.196 +            // repeating annotations.
   3.197 +            //
   3.198 +            // We need to do this in two passes because when creating
   3.199 +            // a container for a repeating annotation we must
   3.200 +            // guarantee that the @Repeatable on the
   3.201 +            // contained annotation is fully annotated
   3.202 +            //
   3.203 +            // The way we force this order is to do all repeating
   3.204 +            // annotations in a pass after all non-repeating are
   3.205 +            // finished. This will work because @Repeatable
   3.206 +            // is non-repeating and therefore will be annotated in the
   3.207 +            // fist pass.
   3.208 +
   3.209 +            // Queue a pass that will replace Attribute.Placeholders
   3.210 +            // with Attribute.Compound (made from synthesized containers).
   3.211 +            ctx.annotateRepeated(new Annotate.Annotator() {
   3.212 +                @Override
   3.213 +                public String toString() {
   3.214 +                    return "repeated annotation pass of: " + sym + " in: " + sym.owner;
   3.215 +                }
   3.216 +
   3.217 +                @Override
   3.218 +                public void enterAnnotation() {
   3.219 +                    complete(ctx);
   3.220 +                }
   3.221 +            });
   3.222 +        }
   3.223 +        // Add non-repeating attributes
   3.224 +        return buf.reverse();
   3.225 +    }
   3.226 +
   3.227 +    public SymbolMetadata reset() {
   3.228 +        attributes = DECL_IN_PROGRESS;
   3.229 +        return this;
   3.230 +    }
   3.231 +
   3.232 +    public boolean isEmpty() {
   3.233 +        return !isStarted()
   3.234 +                || pendingCompletion()
   3.235 +                || attributes.isEmpty();
   3.236 +    }
   3.237 +
   3.238 +    public boolean isTypesEmpty() {
   3.239 +        return type_attributes.isEmpty();
   3.240 +    }
   3.241 +
   3.242 +    public boolean pendingCompletion() {
   3.243 +        return attributes == DECL_IN_PROGRESS;
   3.244 +    }
   3.245 +
   3.246 +    public SymbolMetadata append(List<Attribute.Compound> l) {
   3.247 +        attributes = filterDeclSentinels(attributes);
   3.248 +
   3.249 +        if (l.isEmpty()) {
   3.250 +            ; // no-op
   3.251 +        } else if (attributes.isEmpty()) {
   3.252 +            attributes = l;
   3.253 +        } else {
   3.254 +            attributes = attributes.appendList(l);
   3.255 +        }
   3.256 +        return this;
   3.257 +    }
   3.258 +
   3.259 +    public SymbolMetadata appendUniqueTypes(List<Attribute.TypeCompound> l) {
   3.260 +        if (l.isEmpty()) {
   3.261 +            ; // no-op
   3.262 +        } else if (type_attributes.isEmpty()) {
   3.263 +            type_attributes = l;
   3.264 +        } else {
   3.265 +            // TODO: in case we expect a large number of annotations, this
   3.266 +            // might be inefficient.
   3.267 +            for (Attribute.TypeCompound tc : l) {
   3.268 +                if (!type_attributes.contains(tc))
   3.269 +                    type_attributes = type_attributes.append(tc);
   3.270 +            }
   3.271 +        }
   3.272 +        return this;
   3.273 +    }
   3.274 +
   3.275 +    public SymbolMetadata appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
   3.276 +        if (l.isEmpty()) {
   3.277 +            ; // no-op
   3.278 +        } else if (init_type_attributes.isEmpty()) {
   3.279 +            init_type_attributes = l;
   3.280 +        } else {
   3.281 +            init_type_attributes = init_type_attributes.appendList(l);
   3.282 +        }
   3.283 +        return this;
   3.284 +    }
   3.285 +
   3.286 +    public SymbolMetadata appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
   3.287 +        if (l.isEmpty()) {
   3.288 +            ; // no-op
   3.289 +        } else if (clinit_type_attributes.isEmpty()) {
   3.290 +            clinit_type_attributes = l;
   3.291 +        } else {
   3.292 +            clinit_type_attributes = clinit_type_attributes.appendList(l);
   3.293 +        }
   3.294 +        return this;
   3.295 +    }
   3.296 +
   3.297 +    public SymbolMetadata prepend(List<Attribute.Compound> l) {
   3.298 +        attributes = filterDeclSentinels(attributes);
   3.299 +
   3.300 +        if (l.isEmpty()) {
   3.301 +            ; // no-op
   3.302 +        } else if (attributes.isEmpty()) {
   3.303 +            attributes = l;
   3.304 +        } else {
   3.305 +            attributes = attributes.prependList(l);
   3.306 +        }
   3.307 +        return this;
   3.308 +    }
   3.309 +
   3.310 +    private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) {
   3.311 +        return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
   3.312 +                ? List.<Attribute.Compound>nil()
   3.313 +                : a;
   3.314 +    }
   3.315 +
   3.316 +    private boolean isStarted() {
   3.317 +        return attributes != DECL_NOT_STARTED;
   3.318 +    }
   3.319 +
   3.320 +    private List<Attribute.Compound> getPlaceholders() {
   3.321 +        List<Attribute.Compound> res = List.<Attribute.Compound>nil();
   3.322 +        for (Attribute.Compound a : filterDeclSentinels(attributes)) {
   3.323 +            if (a instanceof Placeholder) {
   3.324 +                res = res.prepend(a);
   3.325 +            }
   3.326 +        }
   3.327 +        return res.reverse();
   3.328 +    }
   3.329 +
   3.330 +    private List<Attribute.TypeCompound> getTypePlaceholders() {
   3.331 +        List<Attribute.TypeCompound> res = List.<Attribute.TypeCompound>nil();
   3.332 +        for (Attribute.TypeCompound a : type_attributes) {
   3.333 +            if (a instanceof Placeholder) {
   3.334 +                res = res.prepend(a);
   3.335 +            }
   3.336 +        }
   3.337 +        return res.reverse();
   3.338 +    }
   3.339 +
   3.340 +    /*
   3.341 +     * Replace Placeholders for repeating annotations with their containers
   3.342 +     */
   3.343 +    private <T extends Attribute.Compound> void complete(Annotate.AnnotateRepeatedContext<T> ctx) {
   3.344 +        Log log = ctx.log;
   3.345 +        Env<AttrContext> env = ctx.env;
   3.346 +        JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
   3.347 +        try {
   3.348 +            // TODO: can we reduce duplication in the following branches?
   3.349 +            if (ctx.isTypeCompound) {
   3.350 +                Assert.check(!isTypesEmpty());
   3.351 +
   3.352 +                if (isTypesEmpty()) {
   3.353 +                    return;
   3.354 +                }
   3.355 +
   3.356 +                List<Attribute.TypeCompound> result = List.nil();
   3.357 +                for (Attribute.TypeCompound a : getTypeAttributes()) {
   3.358 +                    if (a instanceof Placeholder) {
   3.359 +                        @SuppressWarnings("unchecked")
   3.360 +                        Placeholder<Attribute.TypeCompound> ph = (Placeholder<Attribute.TypeCompound>) a;
   3.361 +                        Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext());
   3.362 +
   3.363 +                        if (null != replacement) {
   3.364 +                            result = result.prepend(replacement);
   3.365 +                        }
   3.366 +                    } else {
   3.367 +                        result = result.prepend(a);
   3.368 +                    }
   3.369 +                }
   3.370 +
   3.371 +                type_attributes = result.reverse();
   3.372 +
   3.373 +                Assert.check(SymbolMetadata.this.getTypePlaceholders().isEmpty());
   3.374 +            } else {
   3.375 +                Assert.check(!pendingCompletion());
   3.376 +
   3.377 +                if (isEmpty()) {
   3.378 +                    return;
   3.379 +                }
   3.380 +
   3.381 +                List<Attribute.Compound> result = List.nil();
   3.382 +                for (Attribute.Compound a : getDeclarationAttributes()) {
   3.383 +                    if (a instanceof Placeholder) {
   3.384 +                        @SuppressWarnings("unchecked")
   3.385 +                        Attribute.Compound replacement = replaceOne((Placeholder<T>) a, ctx);
   3.386 +
   3.387 +                        if (null != replacement) {
   3.388 +                            result = result.prepend(replacement);
   3.389 +                        }
   3.390 +                    } else {
   3.391 +                        result = result.prepend(a);
   3.392 +                    }
   3.393 +                }
   3.394 +
   3.395 +                attributes = result.reverse();
   3.396 +
   3.397 +                Assert.check(SymbolMetadata.this.getPlaceholders().isEmpty());
   3.398 +            }
   3.399 +        } finally {
   3.400 +            log.useSource(oldSource);
   3.401 +        }
   3.402 +    }
   3.403 +
   3.404 +    private <T extends Attribute.Compound> T replaceOne(Placeholder<T> placeholder, Annotate.AnnotateRepeatedContext<T> ctx) {
   3.405 +        Log log = ctx.log;
   3.406 +
   3.407 +        // Process repeated annotations
   3.408 +        T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
   3.409 +
   3.410 +        if (validRepeated != null) {
   3.411 +            // Check that the container isn't manually
   3.412 +            // present along with repeated instances of
   3.413 +            // its contained annotation.
   3.414 +            ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
   3.415 +            if (manualContainer != null) {
   3.416 +                log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
   3.417 +                        manualContainer.first().type.tsym);
   3.418 +            }
   3.419 +        }
   3.420 +
   3.421 +        // A null return will delete the Placeholder
   3.422 +        return validRepeated;
   3.423 +    }
   3.424 +
   3.425 +    private static class Placeholder<T extends Attribute.Compound> extends Attribute.TypeCompound {
   3.426 +
   3.427 +        private final Annotate.AnnotateRepeatedContext<T> ctx;
   3.428 +        private final List<T> placeholderFor;
   3.429 +        private final Symbol on;
   3.430 +
   3.431 +        public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) {
   3.432 +            super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(),
   3.433 +                    ctx.isTypeCompound ?
   3.434 +                            ((Attribute.TypeCompound)placeholderFor.head).position :
   3.435 +                                null);
   3.436 +            this.ctx = ctx;
   3.437 +            this.placeholderFor = placeholderFor;
   3.438 +            this.on = on;
   3.439 +        }
   3.440 +
   3.441 +        @Override
   3.442 +        public String toString() {
   3.443 +            return "<placeholder: " + placeholderFor + " on: " + on + ">";
   3.444 +        }
   3.445 +
   3.446 +        public List<T> getPlaceholderFor() {
   3.447 +            return placeholderFor;
   3.448 +        }
   3.449 +
   3.450 +        public Annotate.AnnotateRepeatedContext<T> getRepeatedContext() {
   3.451 +            return ctx;
   3.452 +        }
   3.453 +    }
   3.454 +}
     4.1 --- a/test/tools/javac/lib/DPrinter.java	Sun Sep 08 11:54:21 2013 +0100
     4.2 +++ b/test/tools/javac/lib/DPrinter.java	Mon Sep 09 09:58:20 2013 +0200
     4.3 @@ -49,7 +49,7 @@
     4.4  import com.sun.source.util.TaskListener;
     4.5  import com.sun.source.util.Trees;
     4.6  import com.sun.tools.javac.api.JavacTrees;
     4.7 -import com.sun.tools.javac.code.Annotations;
     4.8 +import com.sun.tools.javac.code.SymbolMetadata;
     4.9  import com.sun.tools.javac.code.Attribute;
    4.10  import com.sun.tools.javac.code.Flags;
    4.11  import com.sun.tools.javac.code.Kinds;
    4.12 @@ -186,21 +186,21 @@
    4.13          FULL
    4.14      };
    4.15  
    4.16 -    public void printAnnotations(String label, Annotations annotations) {
    4.17 +    public void printAnnotations(String label, SymbolMetadata annotations) {
    4.18          printAnnotations(label, annotations, Details.FULL);
    4.19      }
    4.20  
    4.21 -    protected void printAnnotations(String label, Annotations annotations, Details details) {
    4.22 +    protected void printAnnotations(String label, SymbolMetadata annotations, Details details) {
    4.23          if (annotations == null) {
    4.24              printNull(label);
    4.25          } else {
    4.26              // no SUMMARY format currently available to use
    4.27  
    4.28              // use reflection to get at private fields
    4.29 -            Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED");
    4.30 -            Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS");
    4.31 -            Object attributes = getField(annotations, Annotations.class, "attributes");
    4.32 -            Object type_attributes = getField(annotations, Annotations.class, "type_attributes");
    4.33 +            Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED");
    4.34 +            Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS");
    4.35 +            Object attributes = getField(annotations, SymbolMetadata.class, "attributes");
    4.36 +            Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes");
    4.37  
    4.38              if (!showEmptyItems) {
    4.39                  if (attributes instanceof List && ((List) attributes).isEmpty()

mercurial