LowerAttributes.java revision 3088f83b806b82d866d119e344da274105f42821
1/*
2 * Copyright 2016 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.turbine.bytecode;
18
19import com.google.common.collect.ImmutableList;
20import com.google.turbine.bytecode.Attribute.AnnotationDefault;
21import com.google.turbine.bytecode.Attribute.ConstantValue;
22import com.google.turbine.bytecode.Attribute.ExceptionsAttribute;
23import com.google.turbine.bytecode.Attribute.InnerClasses;
24import com.google.turbine.bytecode.Attribute.Signature;
25import com.google.turbine.bytecode.ClassFile.AnnotationInfo;
26import java.util.ArrayList;
27import java.util.List;
28
29/** Lower information in {@link ClassFile} structures to attributes. */
30public class LowerAttributes {
31
32  /** Collects the {@link Attribute}s for a {@link ClassFile}. */
33  static List<Attribute> classAttributes(ClassFile classfile) {
34    List<Attribute> attributes = new ArrayList<>();
35    if (!classfile.innerClasses().isEmpty()) {
36      attributes.add(new InnerClasses(classfile.innerClasses()));
37    }
38    addAllAnnotations(attributes, classfile.annotations());
39    if (classfile.signature() != null) {
40      attributes.add(new Signature(classfile.signature()));
41    }
42    return attributes;
43  }
44
45  /** Collects the {@link Attribute}s for a {@link MethodInfo}. */
46  static List<Attribute> methodAttributes(ClassFile.MethodInfo method) {
47    List<Attribute> attributes = new ArrayList<>();
48    addAllAnnotations(attributes, method.annotations());
49    if (method.signature() != null) {
50      attributes.add(new Signature(method.signature()));
51    }
52    addParameterAnnotations(attributes, method.parameterAnnotations());
53    if (!method.exceptions().isEmpty()) {
54      attributes.add(new ExceptionsAttribute(method.exceptions()));
55    }
56    if (method.defaultValue() != null) {
57      attributes.add(new AnnotationDefault(method.defaultValue()));
58    }
59    return attributes;
60  }
61
62  /** Collects the {@link Attribute}s for a {@link FieldInfo}. */
63  static List<Attribute> fieldAttributes(ClassFile.FieldInfo field) {
64    List<Attribute> attributes = new ArrayList<>();
65    if (field.signature() != null) {
66      attributes.add(new Signature(field.signature()));
67    }
68    if (field.value() != null) {
69      attributes.add(new ConstantValue(field.value()));
70    }
71    addAllAnnotations(attributes, field.annotations());
72    return attributes;
73  }
74
75  static void addAllAnnotations(List<Attribute> attributes, List<AnnotationInfo> annotations) {
76    List<AnnotationInfo> visible = new ArrayList<>();
77    List<AnnotationInfo> invisible = new ArrayList<>();
78    for (AnnotationInfo annotation : annotations) {
79      if (annotation.typeName().equals("Ljava/lang/Deprecated;")) {
80        attributes.add(Attribute.DEPRECATED);
81      }
82      (annotation.isRuntimeVisible() ? visible : invisible).add(annotation);
83    }
84    if (!visible.isEmpty()) {
85      attributes.add(new Attribute.RuntimeVisibleAnnotations(visible));
86    }
87    if (!invisible.isEmpty()) {
88      attributes.add(new Attribute.RuntimeInvisibleAnnotations(invisible));
89    }
90  }
91
92  static void addParameterAnnotations(
93      List<Attribute> attributes, ImmutableList<ImmutableList<AnnotationInfo>> annotations) {
94    List<List<AnnotationInfo>> visibles = new ArrayList<>();
95    List<List<AnnotationInfo>> invisibles = new ArrayList<>();
96    boolean hasVisible = false;
97    boolean hasInvisible = false;
98    for (List<AnnotationInfo> parameterAnnotations : annotations) {
99      List<AnnotationInfo> visible = new ArrayList<>();
100      List<AnnotationInfo> invisible = new ArrayList<>();
101      for (AnnotationInfo annotation : parameterAnnotations) {
102        if (annotation.isRuntimeVisible()) {
103          hasVisible = true;
104          visible.add(annotation);
105        } else {
106          hasInvisible = true;
107          invisible.add(annotation);
108        }
109      }
110      visibles.add(visible);
111      invisibles.add(invisible);
112    }
113    // only add the attributes if one of the nested lists is non-empty,
114    // i.e. at least one parameter was annotated
115    if (hasVisible) {
116      attributes.add(new Attribute.RuntimeVisibleParameterAnnotations(visibles));
117    }
118    if (hasInvisible) {
119      attributes.add(new Attribute.RuntimeInvisibleParameterAnnotations(invisibles));
120    }
121  }
122}
123