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