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.lang.resolve; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.jet.lang.descriptors.*; 021 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 022 import org.jetbrains.jet.lang.psi.JetParameter; 023 import org.jetbrains.jet.lang.psi.JetTypeReference; 024 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 025 import org.jetbrains.jet.lang.types.JetType; 026 import org.jetbrains.jet.lang.types.TypeProjection; 027 import org.jetbrains.jet.lang.types.TypeUtils; 028 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 029 030 import java.util.List; 031 032 import static org.jetbrains.jet.lang.diagnostics.Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER; 033 import static org.jetbrains.jet.lang.diagnostics.Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER; 034 import static org.jetbrains.jet.lang.resolve.BindingContext.VALUE_PARAMETER; 035 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 036 037 public class AnnotationUtils { 038 039 public static void checkConstructorParametersType(@NotNull List<JetParameter> parameters, @NotNull BindingTrace trace) { 040 for (JetParameter parameter : parameters) { 041 VariableDescriptor parameterDescriptor = trace.getBindingContext().get(VALUE_PARAMETER, parameter); 042 if (parameterDescriptor == null) continue; 043 JetType parameterType = parameterDescriptor.getType(); 044 JetTypeReference typeReference = parameter.getTypeReference(); 045 if (typeReference != null) { 046 if (parameterType.isNullable()) { 047 trace.report(NULLABLE_TYPE_OF_ANNOTATION_MEMBER.on(typeReference)); 048 } 049 else if (!isAcceptableTypeForAnnotationParameter(parameterType)) { 050 trace.report(INVALID_TYPE_OF_ANNOTATION_MEMBER.on(typeReference)); 051 } 052 } 053 } 054 } 055 056 private static boolean isAcceptableTypeForAnnotationParameter(@NotNull JetType parameterType) { 057 ClassDescriptor typeDescriptor = TypeUtils.getClassDescriptor(parameterType); 058 if (typeDescriptor == null) { 059 return false; 060 } 061 062 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 063 if (isEnumClass(typeDescriptor) || 064 isAnnotationClass(typeDescriptor) || 065 isJavaLangClass(typeDescriptor) || 066 builtIns.isPrimitiveArray(parameterType) || 067 builtIns.isPrimitiveType(parameterType) || 068 builtIns.getStringType().equals(parameterType)) { 069 return true; 070 } 071 072 if (builtIns.isArray(parameterType)) { 073 List<TypeProjection> arguments = parameterType.getArguments(); 074 if (arguments.size() == 1) { 075 JetType arrayType = arguments.get(0).getType(); 076 if (arrayType.isNullable()) { 077 return false; 078 } 079 ClassDescriptor arrayTypeDescriptor = TypeUtils.getClassDescriptor(arrayType); 080 if (arrayTypeDescriptor != null) { 081 return isEnumClass(arrayTypeDescriptor) || 082 isAnnotationClass(arrayTypeDescriptor) || 083 isJavaLangClass(arrayTypeDescriptor) || 084 builtIns.getStringType().equals(arrayType); 085 } 086 } 087 } 088 return false; 089 } 090 091 public static boolean isArrayMethodCall(@NotNull ResolvedCall resolvedCall) { 092 List<AnnotationDescriptor> annotations = resolvedCall.getResultingDescriptor().getOriginal().getAnnotations(); 093 if (annotations != null) { 094 for (AnnotationDescriptor annotation : annotations) { 095 //noinspection ConstantConditions 096 if ("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().asString())) { 097 return "kotlin.arrays.array".equals(annotation.getAllValueArguments().values().iterator().next().getValue()); 098 } 099 } 100 } 101 return false; 102 } 103 104 public static boolean isJavaClassMethodCall(@NotNull ResolvedCall resolvedCall) { 105 List<AnnotationDescriptor> annotations = resolvedCall.getResultingDescriptor().getOriginal().getAnnotations(); 106 if (annotations != null) { 107 for (AnnotationDescriptor annotation : annotations) { 108 //noinspection ConstantConditions 109 if ("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().asString())) { 110 return "kotlin.javaClass.function".equals(annotation.getAllValueArguments().values().iterator().next().getValue()); 111 } 112 } 113 } 114 return false; 115 } 116 117 public static boolean isPropertyAcceptableAsAnnotationParameter(@NotNull PropertyDescriptor descriptor) { 118 if (descriptor.isVar()) { 119 return false; 120 } 121 if (isClassObject(descriptor.getContainingDeclaration()) || isTopLevelDeclaration(descriptor)) { 122 JetType type = descriptor.getType(); 123 return KotlinBuiltIns.getInstance().isPrimitiveType(type) || KotlinBuiltIns.getInstance().getStringType().equals(type); 124 } 125 return false; 126 } 127 128 private static boolean isJavaLangClass(ClassDescriptor descriptor) { 129 return "java.lang.Class".equals(DescriptorUtils.getFQName(descriptor).asString()); 130 } 131 132 private AnnotationUtils() { 133 } 134 }