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