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 }