001 /*
002 * Copyright 2010-2013 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.k2js.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.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.psi.*;
024 import org.jetbrains.jet.lang.resolve.BindingContext;
025 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
026 import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
027 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
028 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
029 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
030 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
031 import org.jetbrains.jet.lang.types.JetType;
032 import org.jetbrains.jet.lang.types.TypeUtils;
033
034 import java.util.List;
035
036 import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET;
037 import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET;
038 import static org.jetbrains.k2js.translate.utils.ErrorReportingUtils.message;
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 public static JetFunction getFunctionForDescriptor(@NotNull SimpleFunctionDescriptor descriptor) {
080 PsiElement result = DescriptorToSourceUtils.callableDescriptorToDeclaration(descriptor);
081 assert result instanceof JetFunction : message(descriptor, "SimpleFunctionDescriptor should have declaration of type JetFunction");
082 return (JetFunction) result;
083 }
084
085 @NotNull
086 private static JetParameter getParameterForDescriptor(@NotNull ValueParameterDescriptor descriptor) {
087 PsiElement result = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
088 assert result instanceof JetParameter : message(descriptor, "ValueParameterDescriptor should have corresponding JetParameter");
089 return (JetParameter) result;
090 }
091
092 public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClassOrObject classDeclaration) {
093 ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration);
094 List<ClassDescriptor> superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor);
095 return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null);
096 }
097
098 @NotNull
099 public static JetType getTypeByReference(@NotNull BindingContext context,
100 @NotNull JetTypeReference typeReference) {
101 return BindingContextUtils.getNotNull(context, BindingContext.TYPE, typeReference);
102 }
103
104 @NotNull
105 public static ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context,
106 @NotNull JetTypeReference typeReference) {
107 return DescriptorUtils.getClassDescriptorForType(getTypeByReference(context, typeReference));
108 }
109
110 @Nullable
111 public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context,
112 @NotNull JetParameter parameter) {
113 return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
114 }
115
116 @Nullable
117 public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
118 @NotNull JetReferenceExpression reference) {
119 if (BindingContextUtils.isExpressionWithValidReference(reference, context)) {
120 return BindingContextUtils.getNotNull(context, BindingContext.REFERENCE_TARGET, reference);
121 }
122 return null;
123 }
124
125 @Nullable
126 public static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context,
127 @NotNull JetReferenceExpression reference) {
128 return context.get(BindingContext.REFERENCE_TARGET, reference);
129 }
130
131 public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression expression) {
132 return BindingContextUtils.getNotNull(context, BindingContext.VARIABLE_REASSIGNMENT, expression);
133 }
134
135 @Nullable
136 public static CallableDescriptor getCallableDescriptorForOperationExpression(
137 @NotNull BindingContext context,
138 @NotNull JetOperationExpression expression
139 ) {
140 JetSimpleNameExpression operationReference = expression.getOperationReference();
141 DeclarationDescriptor descriptorForReferenceExpression =
142 getNullableDescriptorForReferenceExpression(context, operationReference);
143
144 if (descriptorForReferenceExpression == null) return null;
145
146 assert descriptorForReferenceExpression instanceof CallableDescriptor :
147 message(operationReference, "Operation should resolve to callable descriptor");
148 return (CallableDescriptor) descriptorForReferenceExpression;
149 }
150
151 @NotNull
152 public static DeclarationDescriptor getDescriptorForElement(@NotNull BindingContext context,
153 @NotNull PsiElement element) {
154 return BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element);
155 }
156
157 @Nullable
158 public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull JetExpression expression) {
159 CompileTimeConstant<?> compileTimeValue = context.get(BindingContext.COMPILE_TIME_VALUE, expression);
160 if (compileTimeValue != null) {
161 return getCompileTimeValue(context, expression, compileTimeValue);
162 }
163 return null;
164 }
165
166 @Nullable
167 public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull JetExpression expression, @NotNull CompileTimeConstant<?> constant) {
168 if (constant != null) {
169 if (constant instanceof IntegerValueTypeConstant) {
170 JetType expectedType = context.get(BindingContext.EXPRESSION_TYPE, expression);
171 return ((IntegerValueTypeConstant) constant).getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType);
172 }
173 return constant.getValue();
174 }
175 return null;
176 }
177
178 @NotNull
179 public static JetExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) {
180 ValueParameterDescriptor descriptorWhichDeclaresDefaultValue =
181 getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor);
182 JetParameter psiParameter = getParameterForDescriptor(descriptorWhichDeclaresDefaultValue);
183 JetExpression defaultValue = psiParameter.getDefaultValue();
184 assert defaultValue != null : message(parameterDescriptor, "No default value found in PSI");
185 return defaultValue;
186 }
187
188 private static ValueParameterDescriptor getOriginalDescriptorWhichDeclaresDefaultValue(
189 @NotNull ValueParameterDescriptor parameterDescriptor
190 ) {
191 ValueParameterDescriptor result = parameterDescriptor;
192 assert result.hasDefaultValue() : message(parameterDescriptor, "Unsupplied parameter must have default value");
193 while (!result.declaresDefaultValue()) {
194 result = result.getOverriddenDescriptors().iterator().next();
195 }
196 return result;
197 }
198
199 @NotNull
200 public static ResolvedCall<FunctionDescriptor> getIteratorFunction(@NotNull BindingContext context,
201 @NotNull JetExpression rangeExpression) {
202 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, rangeExpression);
203 }
204
205 @NotNull
206 public static ResolvedCall<FunctionDescriptor> getNextFunction(@NotNull BindingContext context,
207 @NotNull JetExpression rangeExpression) {
208 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, rangeExpression);
209 }
210
211 @NotNull
212 public static ResolvedCall<FunctionDescriptor> getHasNextCallable(@NotNull BindingContext context,
213 @NotNull JetExpression rangeExpression) {
214 return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression);
215 }
216
217 @NotNull
218 public static JetType getTypeForExpression(@NotNull BindingContext context,
219 @NotNull JetExpression expression) {
220 return BindingContextUtils.getNotNull(context, BindingContext.EXPRESSION_TYPE, expression);
221 }
222
223 @NotNull
224 public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context,
225 @NotNull JetArrayAccessExpression arrayAccessExpression,
226 boolean isGet) {
227 return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression);
228 }
229
230 public static ConstructorDescriptor getConstructor(@NotNull BindingContext bindingContext,
231 @NotNull JetClassOrObject declaration) {
232 ConstructorDescriptor primaryConstructor = getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor();
233 assert primaryConstructor != null : message(declaration, "Traits do not have initialize methods");
234 return primaryConstructor;
235 }
236
237 @Nullable
238 public static SimpleFunctionDescriptor getNullableDescriptorForFunction(@NotNull BindingContext bindingContext,
239 @NotNull JetNamedFunction function) {
240 return bindingContext.get(BindingContext.FUNCTION, function);
241 }
242 }