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