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.DescriptorUtilPackage;
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 JetType expectedType = context.getType(expression);
163 return constant.getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType);
164 }
165
166 @NotNull
167 public static JetExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) {
168 ValueParameterDescriptor descriptorWhichDeclaresDefaultValue =
169 getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor);
170 JetParameter psiParameter = getParameterForDescriptor(descriptorWhichDeclaresDefaultValue);
171 JetExpression 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 DescriptorUtilPackage.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 JetExpression 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 JetExpression 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 JetExpression rangeExpression) {
203 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression);
204 }
205
206 @NotNull
207 public static JetType getTypeForExpression(@NotNull BindingContext context,
208 @NotNull JetExpression expression) {
209 return BindingContextUtils.getTypeNotNull(context, expression);
210 }
211
212 @NotNull
213 public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context,
214 @NotNull JetArrayAccessExpression arrayAccessExpression,
215 boolean isGet) {
216 return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression);
217 }
218 }