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.resolve.constants.evaluate.ConstantExpressionEvaluator;
032 import org.jetbrains.kotlin.types.JetType;
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 JetClassOrObject declaration) {
064 return BindingContextUtils.getNotNull(context, BindingContext.CLASS, declaration);
065 }
066
067 @NotNull
068 public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context,
069 @NotNull JetDeclarationWithBody declaration) {
070 return getDescriptorForExpression(context, declaration, FunctionDescriptor.class);
071 }
072
073 @NotNull
074 public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context,
075 @NotNull JetProperty declaration) {
076 return getDescriptorForExpression(context, declaration, PropertyDescriptor.class);
077 }
078
079 @NotNull
080 private static JetParameter getParameterForDescriptor(@NotNull ValueParameterDescriptor descriptor) {
081 PsiElement result = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
082 assert result instanceof JetParameter : message(descriptor, "ValueParameterDescriptor should have corresponding JetParameter");
083 return (JetParameter) result;
084 }
085
086 public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClassOrObject 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 JetType getTypeByReference(@NotNull BindingContext context,
094 @NotNull JetTypeReference typeReference) {
095 return BindingContextUtils.getNotNull(context, BindingContext.TYPE, typeReference);
096 }
097
098 @NotNull
099 public static ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context,
100 @NotNull JetTypeReference typeReference) {
101 return DescriptorUtils.getClassDescriptorForType(getTypeByReference(context, typeReference));
102 }
103
104 @Nullable
105 public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context,
106 @NotNull JetParameter parameter) {
107 return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
108 }
109
110 @Nullable
111 public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
112 @NotNull JetReferenceExpression 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 JetReferenceExpression reference) {
122 return context.get(BindingContext.REFERENCE_TARGET, reference);
123 }
124
125 public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression 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 JetOperationExpression expression
133 ) {
134 JetSimpleNameExpression 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 JetExpression 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 JetExpression expression, @NotNull CompileTimeConstant<?> constant) {
162 if (constant != null) {
163 if (constant instanceof IntegerValueTypeConstant) {
164 JetType expectedType = context.getType(expression);
165 return ((IntegerValueTypeConstant) constant).getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType);
166 }
167 return constant.getValue();
168 }
169 return null;
170 }
171
172 @NotNull
173 public static JetExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) {
174 ValueParameterDescriptor descriptorWhichDeclaresDefaultValue =
175 getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor);
176 JetParameter psiParameter = getParameterForDescriptor(descriptorWhichDeclaresDefaultValue);
177 JetExpression defaultValue = psiParameter.getDefaultValue();
178 assert defaultValue != null : message(parameterDescriptor, "No default value found in PSI");
179 return defaultValue;
180 }
181
182 private static ValueParameterDescriptor getOriginalDescriptorWhichDeclaresDefaultValue(
183 @NotNull ValueParameterDescriptor parameterDescriptor
184 ) {
185 ValueParameterDescriptor result = parameterDescriptor;
186 assert result.hasDefaultValue() : message(parameterDescriptor, "Unsupplied parameter must have default value");
187 while (!result.declaresDefaultValue()) {
188 result = result.getOverriddenDescriptors().iterator().next();
189 }
190 return result;
191 }
192
193 @NotNull
194 public static ResolvedCall<FunctionDescriptor> getIteratorFunction(@NotNull BindingContext context,
195 @NotNull JetExpression rangeExpression) {
196 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, rangeExpression);
197 }
198
199 @NotNull
200 public static ResolvedCall<FunctionDescriptor> getNextFunction(@NotNull BindingContext context,
201 @NotNull JetExpression rangeExpression) {
202 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, rangeExpression);
203 }
204
205 @NotNull
206 public static ResolvedCall<FunctionDescriptor> getHasNextCallable(@NotNull BindingContext context,
207 @NotNull JetExpression rangeExpression) {
208 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression);
209 }
210
211 @NotNull
212 public static JetType getTypeForExpression(@NotNull BindingContext context,
213 @NotNull JetExpression expression) {
214 return BindingContextUtils.getTypeNotNull(context, expression);
215 }
216
217 @NotNull
218 public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context,
219 @NotNull JetArrayAccessExpression arrayAccessExpression,
220 boolean isGet) {
221 return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression);
222 }
223 }