001 /* 002 * Copyright 2010-2015 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.kotlin.js.translate.utils; 018 019 import com.intellij.psi.PsiElement; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.kotlin.descriptors.*; 023 import org.jetbrains.kotlin.psi.*; 024 import org.jetbrains.kotlin.resolve.BindingContext; 025 import org.jetbrains.kotlin.resolve.BindingContextUtils; 026 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 027 import org.jetbrains.kotlin.resolve.DescriptorUtils; 028 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; 029 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 030 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 031 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 032 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; 033 import org.jetbrains.kotlin.types.KotlinType; 034 import org.jetbrains.kotlin.types.TypeUtils; 035 036 import java.util.List; 037 038 import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message; 039 import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET; 040 import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET; 041 042 /** 043 * This class contains some code related to BindingContext use. Intention is not to pollute other classes. 044 * Every call to BindingContext.get() is supposed to be wrapped by this utility class. 045 */ 046 public final class BindingUtils { 047 048 private BindingUtils() { 049 } 050 051 @NotNull 052 static private <E extends PsiElement, D extends DeclarationDescriptor> 053 D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class<D> descriptorClass) { 054 DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression); 055 assert descriptor != null; 056 assert descriptorClass.isInstance(descriptor) 057 : message(expression, expression.toString() + " expected to have of type" + descriptorClass.toString()); 058 //noinspection unchecked 059 return (D) descriptor; 060 } 061 062 @NotNull 063 public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context, 064 @NotNull KtClassOrObject declaration) { 065 return BindingContextUtils.getNotNull(context, BindingContext.CLASS, declaration); 066 } 067 068 @NotNull 069 public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context, 070 @NotNull KtDeclarationWithBody declaration) { 071 return getDescriptorForExpression(context, declaration, FunctionDescriptor.class); 072 } 073 074 @NotNull 075 public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context, 076 @NotNull KtProperty declaration) { 077 return getDescriptorForExpression(context, declaration, PropertyDescriptor.class); 078 } 079 080 @NotNull 081 private static KtParameter getParameterForDescriptor(@NotNull ValueParameterDescriptor descriptor) { 082 PsiElement result = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); 083 assert result instanceof KtParameter : message(descriptor, "ValueParameterDescriptor should have corresponding JetParameter"); 084 return (KtParameter) result; 085 } 086 087 public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull KtClassOrObject classDeclaration) { 088 ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration); 089 List<ClassDescriptor> superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor); 090 return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null); 091 } 092 093 @NotNull 094 public static KotlinType getTypeByReference(@NotNull BindingContext context, 095 @NotNull KtTypeReference typeReference) { 096 return BindingContextUtils.getNotNull(context, BindingContext.TYPE, typeReference); 097 } 098 099 @Nullable 100 public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context, 101 @NotNull KtParameter parameter) { 102 return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 103 } 104 105 @Nullable 106 public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context, 107 @NotNull KtReferenceExpression reference) { 108 if (BindingContextUtils.isExpressionWithValidReference(reference, context)) { 109 return BindingContextUtils.getNotNull(context, BindingContext.REFERENCE_TARGET, reference); 110 } 111 return null; 112 } 113 114 @Nullable 115 private static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context, 116 @NotNull KtReferenceExpression reference) { 117 return context.get(BindingContext.REFERENCE_TARGET, reference); 118 } 119 120 public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull KtExpression expression) { 121 return BindingContextUtils.getNotNull(context, BindingContext.VARIABLE_REASSIGNMENT, expression); 122 } 123 124 @Nullable 125 public static CallableDescriptor getCallableDescriptorForOperationExpression( 126 @NotNull BindingContext context, 127 @NotNull KtOperationExpression expression 128 ) { 129 KtSimpleNameExpression operationReference = expression.getOperationReference(); 130 DeclarationDescriptor descriptorForReferenceExpression = 131 getNullableDescriptorForReferenceExpression(context, operationReference); 132 133 if (descriptorForReferenceExpression == null) return null; 134 135 assert descriptorForReferenceExpression instanceof CallableDescriptor : 136 message(operationReference, "Operation should resolve to callable descriptor"); 137 return (CallableDescriptor) descriptorForReferenceExpression; 138 } 139 140 @NotNull 141 public static DeclarationDescriptor getDescriptorForElement(@NotNull BindingContext context, 142 @NotNull PsiElement element) { 143 return BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element); 144 } 145 146 @Nullable 147 public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression) { 148 CompileTimeConstant<?> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context); 149 if (compileTimeValue != null) { 150 return getCompileTimeValue(context, expression, compileTimeValue); 151 } 152 return null; 153 } 154 155 @Nullable 156 public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression, @NotNull CompileTimeConstant<?> constant) { 157 KotlinType expectedType = context.getType(expression); 158 return constant.getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType); 159 } 160 161 @NotNull 162 public static KtExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) { 163 ValueParameterDescriptor descriptorWhichDeclaresDefaultValue = 164 getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor); 165 KtParameter psiParameter = getParameterForDescriptor(descriptorWhichDeclaresDefaultValue); 166 KtExpression defaultValue = psiParameter.getDefaultValue(); 167 assert defaultValue != null : message(parameterDescriptor, "No default value found in PSI"); 168 return defaultValue; 169 } 170 171 private static ValueParameterDescriptor getOriginalDescriptorWhichDeclaresDefaultValue( 172 @NotNull ValueParameterDescriptor parameterDescriptor 173 ) { 174 ValueParameterDescriptor result = parameterDescriptor; 175 assert DescriptorUtilsKt.hasDefaultValue(result) : message(parameterDescriptor, "Unsupplied parameter must have default value"); 176 // TODO: this seems incorrect, as the default value may come from _not the first_ overridden parameter 177 while (!result.declaresDefaultValue()) { 178 result = result.getOverriddenDescriptors().iterator().next(); 179 } 180 return result; 181 } 182 183 @NotNull 184 public static ResolvedCall<FunctionDescriptor> getIteratorFunction(@NotNull BindingContext context, 185 @NotNull KtExpression rangeExpression) { 186 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, rangeExpression); 187 } 188 189 @NotNull 190 public static ResolvedCall<FunctionDescriptor> getNextFunction(@NotNull BindingContext context, 191 @NotNull KtExpression rangeExpression) { 192 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, rangeExpression); 193 } 194 195 @NotNull 196 public static ResolvedCall<FunctionDescriptor> getHasNextCallable(@NotNull BindingContext context, 197 @NotNull KtExpression rangeExpression) { 198 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression); 199 } 200 201 @NotNull 202 public static KotlinType getTypeForExpression(@NotNull BindingContext context, 203 @NotNull KtExpression expression) { 204 return BindingContextUtils.getTypeNotNull(context, expression); 205 } 206 207 @NotNull 208 public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context, 209 @NotNull KtArrayAccessExpression arrayAccessExpression, 210 boolean isGet) { 211 return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression); 212 } 213 214 215 @Nullable 216 @SuppressWarnings("unchecked") 217 public static ResolvedCall<FunctionDescriptor> getSuperCall(@NotNull BindingContext context, KtClassOrObject classDeclaration) { 218 for (KtSuperTypeListEntry specifier : classDeclaration.getSuperTypeListEntries()) { 219 if (specifier instanceof KtSuperTypeCallEntry) { 220 KtSuperTypeCallEntry superCall = (KtSuperTypeCallEntry) specifier; 221 return (ResolvedCall<FunctionDescriptor>) CallUtilKt.getResolvedCallWithAssert(superCall, context); 222 } 223 } 224 return null; 225 } 226 }