src/share/classes/com/sun/tools/javac/code/Annotations.java

Tue, 09 Oct 2012 19:10:00 -0700

author
jjg
date
Tue, 09 Oct 2012 19:10:00 -0700
changeset 1357
c75be5bc5283
parent 1313
873ddd9f4900
child 1445
376d6c1b49e5
permissions
-rw-r--r--

8000663: clean up langtools imports
Reviewed-by: darcy

jfranck@1313 1 /*
jfranck@1313 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
jfranck@1313 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jfranck@1313 4 *
jfranck@1313 5 * This code is free software; you can redistribute it and/or modify it
jfranck@1313 6 * under the terms of the GNU General Public License version 2 only, as
jfranck@1313 7 * published by the Free Software Foundation. Oracle designates this
jfranck@1313 8 * particular file as subject to the "Classpath" exception as provided
jfranck@1313 9 * by Oracle in the LICENSE file that accompanied this code.
jfranck@1313 10 *
jfranck@1313 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jfranck@1313 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jfranck@1313 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jfranck@1313 14 * version 2 for more details (a copy is included in the LICENSE file that
jfranck@1313 15 * accompanied this code).
jfranck@1313 16 *
jfranck@1313 17 * You should have received a copy of the GNU General Public License version
jfranck@1313 18 * 2 along with this work; if not, write to the Free Software Foundation,
jfranck@1313 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jfranck@1313 20 *
jfranck@1313 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jfranck@1313 22 * or visit www.oracle.com if you need additional information or have any
jfranck@1313 23 * questions.
jfranck@1313 24 */
jfranck@1313 25
jfranck@1313 26 package com.sun.tools.javac.code;
jfranck@1313 27
jfranck@1313 28 import java.util.Map;
jjg@1357 29
jfranck@1313 30 import javax.tools.JavaFileObject;
jfranck@1313 31
jfranck@1313 32 import com.sun.tools.javac.comp.Annotate;
jfranck@1313 33 import com.sun.tools.javac.comp.AttrContext;
jfranck@1313 34 import com.sun.tools.javac.comp.Env;
jjg@1357 35 import com.sun.tools.javac.util.*;
jfranck@1313 36 import com.sun.tools.javac.util.Assert;
jfranck@1313 37 import com.sun.tools.javac.util.List;
jfranck@1313 38 import com.sun.tools.javac.util.Log;
jfranck@1313 39 import com.sun.tools.javac.util.Pair;
jfranck@1313 40 import static com.sun.tools.javac.code.Kinds.PCK;
jfranck@1313 41
jfranck@1313 42 /**
jfranck@1313 43 * Container for all annotations (attributes in javac) on a Symbol.
jfranck@1313 44 *
jfranck@1313 45 * This class is explicitly mutable. Its contents will change when attributes
jfranck@1313 46 * are annotated onto the Symbol. However this class depends on the facts that
jfranck@1313 47 * List (in javac) is immutable.
jfranck@1313 48 *
jfranck@1313 49 * An instance of this class can be in one of three states:
jfranck@1313 50 *
jfranck@1313 51 * NOT_STARTED indicates that the Symbol this instance belongs to have not been
jfranck@1313 52 * annotated (yet). Specifically if the declaration is not annotated this
jfranck@1313 53 * instance will never move past NOT_STARTED. You can never go back to
jfranck@1313 54 * NOT_STARTED.
jfranck@1313 55 *
jfranck@1313 56 * IN_PROGRESS annotations have been found on the declaration. Will be processed
jfranck@1313 57 * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
jfranck@1313 58 * of attributes (and this moves out of the IN_PROGRESS state).
jfranck@1313 59 *
jfranck@1313 60 * "unnamed" this Annotations contains some attributes, possibly the final set.
jfranck@1313 61 * While in this state you can only prepend or append to the attributes not set
jfranck@1313 62 * it directly. You can also move back to the IN_PROGRESS sate using reset().
jfranck@1313 63 *
jfranck@1313 64 * <p><b>This is NOT part of any supported API. If you write code that depends
jfranck@1313 65 * on this, you do so at your own risk. This code and its internal interfaces
jfranck@1313 66 * are subject to change or deletion without notice.</b>
jfranck@1313 67 */
jfranck@1313 68 public class Annotations {
jfranck@1313 69
jfranck@1313 70 private static final List<Attribute.Compound> NOT_STARTED = List.of(null);
jfranck@1313 71 private static final List<Attribute.Compound> IN_PROGRESS = List.of(null);
jfranck@1313 72 /*
jfranck@1313 73 * This field should never be null
jfranck@1313 74 */
jfranck@1313 75 private List<Attribute.Compound> attributes = NOT_STARTED;
jfranck@1313 76 /*
jfranck@1313 77 * The Symbol this Annotatios belong to
jfranck@1313 78 */
jfranck@1313 79 private final Symbol s;
jfranck@1313 80
jfranck@1313 81 public Annotations(Symbol s) {
jfranck@1313 82 this.s = s;
jfranck@1313 83 }
jfranck@1313 84
jfranck@1313 85 public List<Attribute.Compound> getAttributes() {
jfranck@1313 86 return filterSentinels(attributes);
jfranck@1313 87 }
jfranck@1313 88
jfranck@1313 89 public void setAttributes(List<Attribute.Compound> a) {
jfranck@1313 90 Assert.check(pendingCompletion() || !isStarted());
jfranck@1313 91 if (a == null) {
jfranck@1313 92 throw new NullPointerException();
jfranck@1313 93 }
jfranck@1313 94 attributes = a;
jfranck@1313 95 }
jfranck@1313 96
jfranck@1313 97 public void setAttributes(Annotations other) {
jfranck@1313 98 if (other == null) {
jfranck@1313 99 throw new NullPointerException();
jfranck@1313 100 }
jfranck@1313 101 setAttributes(other.getAttributes());
jfranck@1313 102 }
jfranck@1313 103
jfranck@1313 104 public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
jfranck@1313 105 Assert.check(pendingCompletion() || (!isStarted() && s.kind == PCK));
jfranck@1313 106
jfranck@1313 107 Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated = ctx.annotated;
jfranck@1313 108 boolean atLeastOneRepeated = false;
jfranck@1313 109 List<Attribute.Compound> buf = List.<Attribute.Compound>nil();
jfranck@1313 110 for (ListBuffer<Attribute.Compound> lb : annotated.values()) {
jfranck@1313 111 if (lb.size() == 1) {
jfranck@1313 112 buf = buf.prepend(lb.first());
jfranck@1313 113 } else { // repeated
jfranck@1313 114 buf = buf.prepend(new Placeholder(lb.toList(), s));
jfranck@1313 115 atLeastOneRepeated = true;
jfranck@1313 116 }
jfranck@1313 117 }
jfranck@1313 118
jfranck@1313 119 // Add non-repeating attributes
jfranck@1313 120 setAttributes(buf.reverse());
jfranck@1313 121
jfranck@1313 122 if (atLeastOneRepeated) {
jfranck@1313 123 // The Symbol s is now annotated with a combination of
jfranck@1313 124 // finished non-repeating annotations and placeholders for
jfranck@1313 125 // repeating annotations.
jfranck@1313 126 //
jfranck@1313 127 // We need to do this in two passes because when creating
jfranck@1313 128 // a container for a repeating annotation we must
jfranck@1313 129 // guarantee that the @ContainedBy on the
jfranck@1313 130 // contained annotation is fully annotated
jfranck@1313 131 //
jfranck@1313 132 // The way we force this order is to do all repeating
jfranck@1313 133 // annotations in a pass after all non-repeating are
jfranck@1313 134 // finished. This will work because @ContainedBy
jfranck@1313 135 // is non-repeating and therefore will be annotated in the
jfranck@1313 136 // fist pass.
jfranck@1313 137
jfranck@1313 138 // Queue a pass that will replace Attribute.Placeholders
jfranck@1313 139 // with Attribute.Compound (made from synthesized containers).
jfranck@1313 140 ctx.annotateRepeated(new Annotate.Annotator() {
jfranck@1313 141
jfranck@1313 142 @Override
jfranck@1313 143 public String toString() {
jfranck@1313 144 return "repeated annotation pass of: " + s + " in: " + s.owner;
jfranck@1313 145 }
jfranck@1313 146
jfranck@1313 147 @Override
jfranck@1313 148 public void enterAnnotation() {
jfranck@1313 149 complete(ctx);
jfranck@1313 150 }
jfranck@1313 151 });
jfranck@1313 152 }
jfranck@1313 153 }
jfranck@1313 154
jfranck@1313 155 public Annotations reset() {
jfranck@1313 156 attributes = IN_PROGRESS;
jfranck@1313 157 return this;
jfranck@1313 158 }
jfranck@1313 159
jfranck@1313 160 public boolean isEmpty() {
jfranck@1313 161 return !isStarted()
jfranck@1313 162 || pendingCompletion()
jfranck@1313 163 || attributes.isEmpty();
jfranck@1313 164 }
jfranck@1313 165
jfranck@1313 166 public boolean pendingCompletion() {
jfranck@1313 167 return attributes == IN_PROGRESS;
jfranck@1313 168 }
jfranck@1313 169
jfranck@1313 170 public Annotations append(List<Attribute.Compound> l) {
jfranck@1313 171 attributes = filterSentinels(attributes);
jfranck@1313 172
jfranck@1313 173 if (l.isEmpty()) {
jfranck@1313 174 ; // no-op
jfranck@1313 175 } else if (attributes.isEmpty()) {
jfranck@1313 176 attributes = l;
jfranck@1313 177 } else {
jfranck@1313 178 attributes = attributes.appendList(l);
jfranck@1313 179 }
jfranck@1313 180 return this;
jfranck@1313 181 }
jfranck@1313 182
jfranck@1313 183 public Annotations prepend(List<Attribute.Compound> l) {
jfranck@1313 184 attributes = filterSentinels(attributes);
jfranck@1313 185
jfranck@1313 186 if (l.isEmpty()) {
jfranck@1313 187 ; // no-op
jfranck@1313 188 } else if (attributes.isEmpty()) {
jfranck@1313 189 attributes = l;
jfranck@1313 190 } else {
jfranck@1313 191 attributes = attributes.prependList(l);
jfranck@1313 192 }
jfranck@1313 193 return this;
jfranck@1313 194 }
jfranck@1313 195
jfranck@1313 196 private List<Attribute.Compound> filterSentinels(List<Attribute.Compound> a) {
jfranck@1313 197 return (a == IN_PROGRESS || a == NOT_STARTED)
jfranck@1313 198 ? List.<Attribute.Compound>nil()
jfranck@1313 199 : a;
jfranck@1313 200 }
jfranck@1313 201
jfranck@1313 202 private boolean isStarted() {
jfranck@1313 203 return attributes != NOT_STARTED;
jfranck@1313 204 }
jfranck@1313 205
jfranck@1313 206 private List<Attribute.Compound> getPlaceholders() {
jfranck@1313 207 List<Attribute.Compound> res = List.<Attribute.Compound>nil();
jfranck@1313 208 for (Attribute.Compound a : filterSentinels(attributes)) {
jfranck@1313 209 if (a instanceof Placeholder) {
jfranck@1313 210 res = res.prepend(a);
jfranck@1313 211 }
jfranck@1313 212 }
jfranck@1313 213 return res.reverse();
jfranck@1313 214 }
jfranck@1313 215
jfranck@1313 216 /*
jfranck@1313 217 * Replace Placeholders for repeating annotations with their containers
jfranck@1313 218 */
jfranck@1313 219 private void complete(Annotate.AnnotateRepeatedContext ctx) {
jfranck@1313 220 Assert.check(!pendingCompletion());
jfranck@1313 221 Log log = ctx.log;
jfranck@1313 222 Env<AttrContext> env = ctx.env;
jfranck@1313 223 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
jfranck@1313 224 try {
jfranck@1313 225
jfranck@1313 226 if (isEmpty()) {
jfranck@1313 227 return;
jfranck@1313 228 }
jfranck@1313 229
jfranck@1313 230 List<Attribute.Compound> result = List.nil();
jfranck@1313 231 for (Attribute.Compound a : getAttributes()) {
jfranck@1313 232 if (a instanceof Placeholder) {
jfranck@1313 233 Attribute.Compound replacement = replaceOne((Placeholder) a, ctx);
jfranck@1313 234
jfranck@1313 235 if (null != replacement) {
jfranck@1313 236 result = result.prepend(replacement);
jfranck@1313 237 }
jfranck@1313 238 } else {
jfranck@1313 239 result = result.prepend(a);
jfranck@1313 240 }
jfranck@1313 241 }
jfranck@1313 242
jfranck@1313 243 attributes = result.reverse();
jfranck@1313 244
jfranck@1313 245 Assert.check(Annotations.this.getPlaceholders().isEmpty());
jfranck@1313 246 } finally {
jfranck@1313 247 log.useSource(oldSource);
jfranck@1313 248 }
jfranck@1313 249 }
jfranck@1313 250
jfranck@1313 251 private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) {
jfranck@1313 252 Log log = ctx.log;
jfranck@1313 253
jfranck@1313 254 // Process repeated annotations
jfranck@1313 255 Attribute.Compound validRepeated =
jfranck@1313 256 ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor());
jfranck@1313 257
jfranck@1313 258 if (validRepeated != null) {
jfranck@1313 259 // Check that the container isn't manually
jfranck@1313 260 // present along with repeated instances of
jfranck@1313 261 // its contained annotation.
jfranck@1313 262 ListBuffer<Attribute.Compound> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
jfranck@1313 263 if (manualContainer != null) {
jfranck@1313 264 log.error(ctx.pos.get(manualContainer.first()), "invalid.containedby.annotation.repeated.and.container.present",
jfranck@1313 265 manualContainer.first().type.tsym);
jfranck@1313 266 }
jfranck@1313 267 }
jfranck@1313 268
jfranck@1313 269 // A null return will delete the Placeholder
jfranck@1313 270 return validRepeated;
jfranck@1313 271
jfranck@1313 272 }
jfranck@1313 273
jfranck@1313 274 private static class Placeholder extends Attribute.Compound {
jfranck@1313 275
jfranck@1313 276 private List<Attribute.Compound> placeholderFor;
jfranck@1313 277 private Symbol on;
jfranck@1313 278
jfranck@1313 279 public Placeholder(List<Attribute.Compound> placeholderFor, Symbol on) {
jfranck@1313 280 super(Type.noType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil());
jfranck@1313 281 this.placeholderFor = placeholderFor;
jfranck@1313 282 this.on = on;
jfranck@1313 283 }
jfranck@1313 284
jfranck@1313 285 @Override
jfranck@1313 286 public String toString() {
jfranck@1313 287 return "<placeholder: " + placeholderFor + " on: " + on + ">";
jfranck@1313 288 }
jfranck@1313 289
jfranck@1313 290 public List<Attribute.Compound> getPlaceholderFor() {
jfranck@1313 291 return placeholderFor;
jfranck@1313 292 }
jfranck@1313 293 }
jfranck@1313 294 }

mercurial