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