• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.turbine.bytecode;
18 
19 import com.google.common.collect.ImmutableList;
20 import com.google.turbine.bytecode.Attribute.AnnotationDefault;
21 import com.google.turbine.bytecode.Attribute.ConstantValue;
22 import com.google.turbine.bytecode.Attribute.ExceptionsAttribute;
23 import com.google.turbine.bytecode.Attribute.InnerClasses;
24 import com.google.turbine.bytecode.Attribute.MethodParameters;
25 import com.google.turbine.bytecode.Attribute.Signature;
26 import com.google.turbine.bytecode.ClassFile.AnnotationInfo;
27 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo;
28 import java.util.ArrayList;
29 import java.util.List;
30 
31 /** Lower information in {@link ClassFile} structures to attributes. */
32 public final class LowerAttributes {
33 
34   /** Collects the {@link Attribute}s for a {@link ClassFile}. */
classAttributes(ClassFile classfile)35   static List<Attribute> classAttributes(ClassFile classfile) {
36     List<Attribute> attributes = new ArrayList<>();
37     if (!classfile.innerClasses().isEmpty()) {
38       attributes.add(new InnerClasses(classfile.innerClasses()));
39     }
40     addAllAnnotations(attributes, classfile.annotations());
41     addAllTypeAnnotations(attributes, classfile.typeAnnotations());
42     if (classfile.signature() != null) {
43       attributes.add(new Signature(classfile.signature()));
44     }
45     if (classfile.module() != null) {
46       attributes.add(new Attribute.Module(classfile.module()));
47     }
48     if (classfile.nestHost() != null) {
49       attributes.add(new Attribute.NestHost(classfile.nestHost()));
50     }
51     if (!classfile.nestMembers().isEmpty()) {
52       attributes.add(new Attribute.NestMembers(classfile.nestMembers()));
53     }
54     if (classfile.record() != null) {
55       attributes.add(recordAttribute(classfile.record()));
56     }
57     if (!classfile.permits().isEmpty()) {
58       attributes.add(new Attribute.PermittedSubclasses(classfile.permits()));
59     }
60     if (classfile.transitiveJar() != null) {
61       attributes.add(new Attribute.TurbineTransitiveJar(classfile.transitiveJar()));
62     }
63     return attributes;
64   }
65 
recordAttribute(ClassFile.RecordInfo record)66   private static Attribute recordAttribute(ClassFile.RecordInfo record) {
67     ImmutableList.Builder<Attribute.Record.Component> components = ImmutableList.builder();
68     for (ClassFile.RecordInfo.RecordComponentInfo component : record.recordComponents()) {
69       List<Attribute> attributes = new ArrayList<>();
70       if (component.signature() != null) {
71         attributes.add(new Attribute.Signature(component.signature()));
72       }
73       addAllAnnotations(attributes, component.annotations());
74       addAllTypeAnnotations(attributes, component.typeAnnotations());
75       components.add(
76           new Attribute.Record.Component(component.name(), component.descriptor(), attributes));
77     }
78     return new Attribute.Record(components.build());
79   }
80 
81   /** Collects the {@link Attribute}s for a {@link MethodInfo}. */
methodAttributes(ClassFile.MethodInfo method)82   static List<Attribute> methodAttributes(ClassFile.MethodInfo method) {
83     List<Attribute> attributes = new ArrayList<>();
84     addAllAnnotations(attributes, method.annotations());
85     addAllTypeAnnotations(attributes, method.typeAnnotations());
86     if (method.signature() != null) {
87       attributes.add(new Signature(method.signature()));
88     }
89     addParameterAnnotations(attributes, method.parameterAnnotations());
90     if (!method.exceptions().isEmpty()) {
91       attributes.add(new ExceptionsAttribute(method.exceptions()));
92     }
93     if (method.defaultValue() != null) {
94       attributes.add(new AnnotationDefault(method.defaultValue()));
95     }
96     if (!method.parameters().isEmpty()) {
97       attributes.add(new MethodParameters(method.parameters()));
98     }
99     return attributes;
100   }
101 
102   /** Collects the {@link Attribute}s for a {@link FieldInfo}. */
fieldAttributes(ClassFile.FieldInfo field)103   static List<Attribute> fieldAttributes(ClassFile.FieldInfo field) {
104     List<Attribute> attributes = new ArrayList<>();
105     if (field.signature() != null) {
106       attributes.add(new Signature(field.signature()));
107     }
108     if (field.value() != null) {
109       attributes.add(new ConstantValue(field.value()));
110     }
111     addAllAnnotations(attributes, field.annotations());
112     addAllTypeAnnotations(attributes, field.typeAnnotations());
113     return attributes;
114   }
115 
addAllAnnotations(List<Attribute> attributes, List<AnnotationInfo> annotations)116   static void addAllAnnotations(List<Attribute> attributes, List<AnnotationInfo> annotations) {
117     List<AnnotationInfo> visible = new ArrayList<>();
118     List<AnnotationInfo> invisible = new ArrayList<>();
119     for (AnnotationInfo annotation : annotations) {
120       if (annotation.typeName().equals("Ljava/lang/Deprecated;")) {
121         attributes.add(Attribute.DEPRECATED);
122       }
123       (annotation.isRuntimeVisible() ? visible : invisible).add(annotation);
124     }
125     if (!visible.isEmpty()) {
126       attributes.add(new Attribute.RuntimeVisibleAnnotations(visible));
127     }
128     if (!invisible.isEmpty()) {
129       attributes.add(new Attribute.RuntimeInvisibleAnnotations(invisible));
130     }
131   }
132 
addAllTypeAnnotations( List<Attribute> attributes, ImmutableList<TypeAnnotationInfo> annotations)133   private static void addAllTypeAnnotations(
134       List<Attribute> attributes, ImmutableList<TypeAnnotationInfo> annotations) {
135     List<TypeAnnotationInfo> visible = new ArrayList<>();
136     List<TypeAnnotationInfo> invisible = new ArrayList<>();
137     for (TypeAnnotationInfo annotation : annotations) {
138       (annotation.anno().isRuntimeVisible() ? visible : invisible).add(annotation);
139     }
140     if (!visible.isEmpty()) {
141       attributes.add(new Attribute.RuntimeVisibleTypeAnnotations(ImmutableList.copyOf(visible)));
142     }
143     if (!invisible.isEmpty()) {
144       attributes.add(
145           new Attribute.RuntimeInvisibleTypeAnnotations(ImmutableList.copyOf(invisible)));
146     }
147   }
148 
addParameterAnnotations( List<Attribute> attributes, ImmutableList<ImmutableList<AnnotationInfo>> annotations)149   static void addParameterAnnotations(
150       List<Attribute> attributes, ImmutableList<ImmutableList<AnnotationInfo>> annotations) {
151     List<List<AnnotationInfo>> visibles = new ArrayList<>();
152     List<List<AnnotationInfo>> invisibles = new ArrayList<>();
153     boolean hasVisible = false;
154     boolean hasInvisible = false;
155     for (List<AnnotationInfo> parameterAnnotations : annotations) {
156       List<AnnotationInfo> visible = new ArrayList<>();
157       List<AnnotationInfo> invisible = new ArrayList<>();
158       for (AnnotationInfo annotation : parameterAnnotations) {
159         if (annotation.isRuntimeVisible()) {
160           hasVisible = true;
161           visible.add(annotation);
162         } else {
163           hasInvisible = true;
164           invisible.add(annotation);
165         }
166       }
167       visibles.add(visible);
168       invisibles.add(invisible);
169     }
170     // only add the attributes if one of the nested lists is non-empty,
171     // i.e. at least one parameter was annotated
172     if (hasVisible) {
173       attributes.add(new Attribute.RuntimeVisibleParameterAnnotations(visibles));
174     }
175     if (hasInvisible) {
176       attributes.add(new Attribute.RuntimeInvisibleParameterAnnotations(invisibles));
177     }
178   }
179 
LowerAttributes()180   private LowerAttributes() {}
181 }
182