001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.codegen; 018 019 import com.intellij.psi.PsiElement; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.jet.codegen.state.JetTypeMapper; 023 import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor; 024 import org.jetbrains.jet.lang.descriptors.*; 025 import org.jetbrains.jet.lang.descriptors.annotations.Annotated; 026 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor; 027 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 028 import org.jetbrains.jet.lang.psi.JetAnnotationEntry; 029 import org.jetbrains.jet.lang.psi.JetClass; 030 import org.jetbrains.jet.lang.psi.JetModifierList; 031 import org.jetbrains.jet.lang.psi.JetModifierListOwner; 032 import org.jetbrains.jet.lang.resolve.BindingContext; 033 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 034 import org.jetbrains.jet.lang.resolve.constants.*; 035 import org.jetbrains.jet.lang.resolve.constants.StringValue; 036 import org.jetbrains.jet.lang.resolve.name.FqName; 037 import org.jetbrains.jet.lang.types.JetType; 038 import org.jetbrains.jet.lang.types.TypeUtils; 039 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 040 import org.jetbrains.org.objectweb.asm.*; 041 042 import java.lang.annotation.Retention; 043 import java.lang.annotation.RetentionPolicy; 044 import java.util.*; 045 046 import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.DELEGATION; 047 import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration; 048 import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getResolvedCall; 049 050 public abstract class AnnotationCodegen { 051 052 public static final class JvmFlagAnnotation { 053 private final FqName fqName; 054 private final int jvmFlag; 055 056 public JvmFlagAnnotation(@NotNull String fqName, int jvmFlag) { 057 this.fqName = new FqName(fqName); 058 this.jvmFlag = jvmFlag; 059 } 060 061 public boolean hasAnnotation(@NotNull Annotated annotated) { 062 return annotated.getAnnotations().findAnnotation(fqName) != null; 063 } 064 065 public int getJvmFlag() { 066 return jvmFlag; 067 } 068 } 069 070 public static final List<JvmFlagAnnotation> FIELD_FLAGS = Arrays.asList( 071 new JvmFlagAnnotation("kotlin.jvm.volatile", Opcodes.ACC_VOLATILE), 072 new JvmFlagAnnotation("kotlin.jvm.transient", Opcodes.ACC_TRANSIENT) 073 ); 074 075 public static final List<JvmFlagAnnotation> METHOD_FLAGS = Arrays.asList( 076 new JvmFlagAnnotation("kotlin.jvm.strictfp", Opcodes.ACC_STRICT), 077 new JvmFlagAnnotation("kotlin.jvm.synchronized", Opcodes.ACC_SYNCHRONIZED) 078 ); 079 080 private static final AnnotationVisitor NO_ANNOTATION_VISITOR = new AnnotationVisitor(Opcodes.ASM5) {}; 081 082 private final JetTypeMapper typeMapper; 083 private final BindingContext bindingContext; 084 085 private AnnotationCodegen(JetTypeMapper mapper) { 086 typeMapper = mapper; 087 bindingContext = typeMapper.getBindingContext(); 088 } 089 090 /** 091 * @param returnType can be null if not applicable (e.g. {@code annotated} is a class) 092 */ 093 public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) { 094 if (annotated == null) { 095 return; 096 } 097 098 if (!(annotated instanceof DeclarationDescriptor)) { 099 return; 100 } 101 102 PsiElement psiElement; 103 if (annotated instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) annotated).getKind() == DELEGATION) { 104 psiElement = null; 105 } 106 else { 107 psiElement = descriptorToDeclaration((DeclarationDescriptor) annotated); 108 } 109 110 JetModifierList modifierList = null; 111 if (annotated instanceof ConstructorDescriptor && psiElement instanceof JetClass) { 112 modifierList = ((JetClass) psiElement).getPrimaryConstructorModifierList(); 113 } 114 else if (psiElement instanceof JetModifierListOwner) { 115 modifierList = ((JetModifierListOwner) psiElement).getModifierList(); 116 } 117 118 Set<String> annotationDescriptorsAlreadyPresent = new HashSet<String>(); 119 120 if (modifierList == null) { 121 if (annotated instanceof CallableMemberDescriptor && 122 JvmCodegenUtil.getDirectMember((CallableMemberDescriptor) annotated) instanceof DeserializedCallableMemberDescriptor) { 123 for (AnnotationDescriptor annotation : annotated.getAnnotations()) { 124 String descriptor = genAnnotation(annotation); 125 if (descriptor != null) { 126 annotationDescriptorsAlreadyPresent.add(descriptor); 127 } 128 } 129 } 130 } 131 else { 132 List<JetAnnotationEntry> annotationEntries = modifierList.getAnnotationEntries(); 133 for (JetAnnotationEntry annotationEntry : annotationEntries) { 134 ResolvedCall<?> resolvedCall = getResolvedCall(annotationEntry, bindingContext); 135 if (resolvedCall == null) continue; // Skipping annotations if they are not resolved. Needed for JetLightClass generation 136 137 AnnotationDescriptor annotationDescriptor = bindingContext.get(BindingContext.ANNOTATION, annotationEntry); 138 if (annotationDescriptor == null) continue; // Skipping annotations if they are not resolved. Needed for JetLightClass generation 139 140 String descriptor = genAnnotation(annotationDescriptor); 141 if (descriptor != null) { 142 annotationDescriptorsAlreadyPresent.add(descriptor); 143 } 144 } 145 } 146 147 generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent); 148 } 149 150 private void generateAdditionalAnnotations( 151 @NotNull Annotated annotated, 152 @Nullable Type returnType, 153 @NotNull Set<String> annotationDescriptorsAlreadyPresent 154 ) { 155 if (annotated instanceof CallableDescriptor) { 156 CallableDescriptor descriptor = (CallableDescriptor) annotated; 157 158 // No need to annotate privates, synthetic accessors and their parameters 159 if (isInvisibleFromTheOutside(descriptor)) return; 160 if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return; 161 162 if (returnType != null && !AsmUtil.isPrimitive(returnType)) { 163 generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent); 164 } 165 } 166 } 167 168 private static boolean isInvisibleFromTheOutside(@Nullable DeclarationDescriptor descriptor) { 169 if (descriptor instanceof CallableMemberDescriptor && JetTypeMapper.isAccessor((CallableMemberDescriptor) descriptor)) return false; 170 if (descriptor instanceof MemberDescriptor) { 171 return AsmUtil.getVisibilityAccessFlag((MemberDescriptor) descriptor) == Opcodes.ACC_PRIVATE; 172 } 173 return false; 174 } 175 176 private void generateNullabilityAnnotation(@Nullable JetType type, @NotNull Set<String> annotationDescriptorsAlreadyPresent) { 177 if (type == null) return; 178 179 if (isBareTypeParameterWithNullableUpperBound(type)) { 180 // This is to account for the case of, say 181 // class Function<R> { fun invoke(): R } 182 // it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null, 183 // so we put no annotations 184 return; 185 } 186 187 boolean isNullableType = TypeUtils.isNullableType(type); 188 189 Class<?> annotationClass = isNullableType ? Nullable.class : NotNull.class; 190 191 String descriptor = Type.getType(annotationClass).getDescriptor(); 192 if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { 193 visitAnnotation(descriptor, false).visitEnd(); 194 } 195 } 196 197 private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull JetType type) { 198 ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor(); 199 return !type.isNullable() && classifier instanceof TypeParameterDescriptor && TypeUtils.hasNullableSuperType(type); 200 } 201 202 public void generateAnnotationDefaultValue(@NotNull CompileTimeConstant value, @NotNull JetType expectedType) { 203 AnnotationVisitor visitor = visitAnnotation(null, false); // Parameters are unimportant 204 genCompileTimeValue(null, value, expectedType, visitor); 205 visitor.visitEnd(); 206 } 207 208 @Nullable 209 private String genAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) { 210 ClassifierDescriptor classifierDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor(); 211 assert classifierDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor; 212 RetentionPolicy rp = getRetentionPolicy(classifierDescriptor); 213 if (rp == RetentionPolicy.SOURCE) { 214 return null; 215 } 216 217 String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); 218 AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME); 219 220 genAnnotationArguments(annotationDescriptor, annotationVisitor); 221 annotationVisitor.visitEnd(); 222 223 return descriptor; 224 } 225 226 private void genAnnotationArguments(AnnotationDescriptor annotationDescriptor, AnnotationVisitor annotationVisitor) { 227 for (Map.Entry<ValueParameterDescriptor, CompileTimeConstant<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) { 228 ValueParameterDescriptor descriptor = entry.getKey(); 229 String name = descriptor.getName().asString(); 230 genCompileTimeValue(name, entry.getValue(), descriptor.getType(), annotationVisitor); 231 } 232 } 233 234 private void genCompileTimeValue( 235 @Nullable final String name, 236 @NotNull CompileTimeConstant<?> value, 237 @NotNull final JetType expectedType, 238 @NotNull final AnnotationVisitor annotationVisitor 239 ) { 240 AnnotationArgumentVisitor argumentVisitor = new AnnotationArgumentVisitor<Void, Void>() { 241 @Override 242 public Void visitLongValue(@NotNull LongValue value, Void data) { 243 return visitSimpleValue(value); 244 } 245 246 @Override 247 public Void visitIntValue(IntValue value, Void data) { 248 return visitSimpleValue(value); 249 } 250 251 @Override 252 public Void visitShortValue(ShortValue value, Void data) { 253 return visitSimpleValue(value); 254 } 255 256 @Override 257 public Void visitByteValue(ByteValue value, Void data) { 258 return visitSimpleValue(value); 259 } 260 261 @Override 262 public Void visitDoubleValue(DoubleValue value, Void data) { 263 return visitSimpleValue(value); 264 } 265 266 @Override 267 public Void visitFloatValue(FloatValue value, Void data) { 268 return visitSimpleValue(value); 269 } 270 271 @Override 272 public Void visitBooleanValue(BooleanValue value, Void data) { 273 return visitSimpleValue(value); 274 } 275 276 @Override 277 public Void visitCharValue(CharValue value, Void data) { 278 return visitSimpleValue(value); 279 } 280 281 @Override 282 public Void visitStringValue(StringValue value, Void data) { 283 return visitSimpleValue(value); 284 } 285 286 @Override 287 public Void visitEnumValue(EnumValue value, Void data) { 288 String propertyName = value.getValue().getName().asString(); 289 annotationVisitor.visitEnum(name, typeMapper.mapType(value.getType(KotlinBuiltIns.getInstance())).getDescriptor(), propertyName); 290 return null; 291 } 292 293 @Override 294 public Void visitArrayValue(ArrayValue value, Void data) { 295 AnnotationVisitor visitor = annotationVisitor.visitArray(name); 296 for (CompileTimeConstant<?> argument : value.getValue()) { 297 genCompileTimeValue(null, argument, value.getType(KotlinBuiltIns.getInstance()), visitor); 298 } 299 visitor.visitEnd(); 300 return null; 301 } 302 303 @Override 304 public Void visitAnnotationValue(AnnotationValue value, Void data) { 305 String internalAnnName = typeMapper.mapType(value.getValue().getType()).getDescriptor(); 306 AnnotationVisitor visitor = annotationVisitor.visitAnnotation(name, internalAnnName); 307 genAnnotationArguments(value.getValue(), visitor); 308 visitor.visitEnd(); 309 return null; 310 } 311 312 @Override 313 public Void visitJavaClassValue(JavaClassValue value, Void data) { 314 annotationVisitor.visit(name, typeMapper.mapType(value.getValue())); 315 return null; 316 } 317 318 @Override 319 public Void visitNumberTypeValue(IntegerValueTypeConstant value, Void data) { 320 Object numberType = value.getValue(expectedType); 321 annotationVisitor.visit(name, numberType); 322 return null; 323 } 324 325 private Void visitSimpleValue(CompileTimeConstant value) { 326 annotationVisitor.visit(name, value.getValue()); 327 return null; 328 } 329 330 @Override 331 public Void visitErrorValue(ErrorValue value, Void data) { 332 return visitUnsupportedValue(value); 333 } 334 335 @Override 336 public Void visitNullValue(NullValue value, Void data) { 337 return visitUnsupportedValue(value); 338 } 339 340 private Void visitUnsupportedValue(CompileTimeConstant value) { 341 throw new IllegalStateException("Don't know how to compile annotation value " + value); 342 } 343 }; 344 345 value.accept(argumentVisitor, null); 346 } 347 348 @NotNull 349 private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) { 350 AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName())); 351 if (retentionAnnotation != null) { 352 Collection<CompileTimeConstant<?>> valueArguments = retentionAnnotation.getAllValueArguments().values(); 353 if (!valueArguments.isEmpty()) { 354 CompileTimeConstant<?> compileTimeConstant = valueArguments.iterator().next(); 355 if (compileTimeConstant instanceof EnumValue) { 356 ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue(); 357 JetType classObjectType = enumEntry.getClassObjectType(); 358 if (classObjectType != null) { 359 if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) { 360 return RetentionPolicy.valueOf(enumEntry.getName().asString()); 361 } 362 } 363 } 364 } 365 } 366 367 return RetentionPolicy.CLASS; 368 } 369 370 @NotNull 371 abstract AnnotationVisitor visitAnnotation(String descr, boolean visible); 372 373 public static AnnotationCodegen forClass(final ClassVisitor cv, JetTypeMapper mapper) { 374 return new AnnotationCodegen(mapper) { 375 @NotNull 376 @Override 377 AnnotationVisitor visitAnnotation(String descr, boolean visible) { 378 return safe(cv.visitAnnotation(descr, visible)); 379 } 380 }; 381 } 382 383 public static AnnotationCodegen forMethod(final MethodVisitor mv, JetTypeMapper mapper) { 384 return new AnnotationCodegen(mapper) { 385 @NotNull 386 @Override 387 AnnotationVisitor visitAnnotation(String descr, boolean visible) { 388 return safe(mv.visitAnnotation(descr, visible)); 389 } 390 }; 391 } 392 393 public static AnnotationCodegen forField(final FieldVisitor fv, JetTypeMapper mapper) { 394 return new AnnotationCodegen(mapper) { 395 @NotNull 396 @Override 397 AnnotationVisitor visitAnnotation(String descr, boolean visible) { 398 return safe(fv.visitAnnotation(descr, visible)); 399 } 400 }; 401 } 402 403 public static AnnotationCodegen forParameter(final int parameter, final MethodVisitor mv, JetTypeMapper mapper) { 404 return new AnnotationCodegen(mapper) { 405 @NotNull 406 @Override 407 AnnotationVisitor visitAnnotation(String descr, boolean visible) { 408 return safe(mv.visitParameterAnnotation(parameter, descr, visible)); 409 } 410 }; 411 } 412 413 public static AnnotationCodegen forAnnotationDefaultValue(final MethodVisitor mv, JetTypeMapper mapper) { 414 return new AnnotationCodegen(mapper) { 415 @NotNull 416 @Override 417 AnnotationVisitor visitAnnotation(String descr, boolean visible) { 418 return safe(mv.visitAnnotationDefault()); 419 } 420 }; 421 } 422 423 @NotNull 424 private static AnnotationVisitor safe(@Nullable AnnotationVisitor av) { 425 return av == null ? NO_ANNOTATION_VISITOR : av; 426 } 427 }