org.jetbrains.kotlin.js.translate.utils.BindingUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.translate.utils;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import java.util.List;
import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET;
/**
* This class contains some code related to BindingContext use. Intention is not to pollute other classes.
* Every call to BindingContext.get() is supposed to be wrapped by this utility class.
*/
public final class BindingUtils {
private BindingUtils() {
}
@SuppressWarnings("unchecked")
@NotNull
private static D getDescriptorForExpression(
@NotNull BindingContext context, @NotNull E expression, Class descriptorClass
) {
DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
assert descriptor != null;
assert descriptorClass.isInstance(descriptor)
: message(expression, expression.toString() + " expected to have of type" + descriptorClass.toString());
return (D) descriptor;
}
@NotNull
public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context,
@NotNull KtPureClassOrObject declaration) {
return SyntheticClassOrObjectDescriptorKt.findClassDescriptor(declaration, context);
}
@NotNull
public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context,
@NotNull KtDeclarationWithBody declaration) {
return getDescriptorForExpression(context, declaration, FunctionDescriptor.class);
}
@NotNull
public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context,
@NotNull KtProperty declaration) {
return getDescriptorForExpression(context, declaration, PropertyDescriptor.class);
}
@NotNull
private static KtParameter getParameterForDescriptor(@NotNull ValueParameterDescriptor descriptor) {
PsiElement result = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
assert result instanceof KtParameter : message(descriptor, "ValueParameterDescriptor should have corresponding KtParameter");
return (KtParameter) result;
}
public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull KtPureClassOrObject classDeclaration) {
ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration);
List superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor);
return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null);
}
@NotNull
public static KotlinType getTypeByReference(@NotNull BindingContext context,
@NotNull KtTypeReference typeReference) {
return BindingContextUtils.getNotNull(context, BindingContext.TYPE, typeReference);
}
@Nullable
public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context,
@NotNull KtParameter parameter) {
return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
}
@Nullable
public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
@NotNull KtReferenceExpression reference) {
if (BindingContextUtils.isExpressionWithValidReference(reference, context)) {
return resolveObjectViaTypeAlias(BindingContextUtils.getNotNull(context, BindingContext.REFERENCE_TARGET, reference));
}
return null;
}
@Nullable
private static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context,
@NotNull KtReferenceExpression reference) {
DeclarationDescriptor descriptor = context.get(BindingContext.REFERENCE_TARGET, reference);
return descriptor != null ? resolveObjectViaTypeAlias(descriptor) : null;
}
@NotNull
private static DeclarationDescriptor resolveObjectViaTypeAlias(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof TypeAliasDescriptor) {
ClassDescriptor classDescriptor = ((TypeAliasDescriptor) descriptor).getClassDescriptor();
assert classDescriptor != null : "Class descriptor must be non-null in resolved typealias: " + descriptor;
if (classDescriptor.getKind() != ClassKind.OBJECT && classDescriptor.getKind() != ClassKind.ENUM_CLASS) {
classDescriptor = classDescriptor.getCompanionObjectDescriptor();
assert classDescriptor != null : "Resolved typealias must have non-null class descriptor: " + descriptor;
}
return classDescriptor;
}
else if (descriptor instanceof FakeCallableDescriptorForTypeAliasObject) {
return ((FakeCallableDescriptorForTypeAliasObject) descriptor).getReferencedObject();
}
else {
return descriptor;
}
}
public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull KtExpression expression) {
Boolean result = context.get(BindingContext.VARIABLE_REASSIGNMENT, expression);
return (result != null) ? result : false;
}
@Nullable
public static CallableDescriptor getCallableDescriptorForOperationExpression(
@NotNull BindingContext context,
@NotNull KtOperationExpression expression
) {
KtSimpleNameExpression operationReference = expression.getOperationReference();
DeclarationDescriptor descriptorForReferenceExpression =
getNullableDescriptorForReferenceExpression(context, operationReference);
if (descriptorForReferenceExpression == null) return null;
assert descriptorForReferenceExpression instanceof CallableDescriptor :
message(operationReference, "Operation should resolve to callable descriptor");
return (CallableDescriptor) descriptorForReferenceExpression;
}
@NotNull
public static DeclarationDescriptor getDescriptorForElement(@NotNull BindingContext context,
@NotNull PsiElement element) {
return BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element);
}
@Nullable
public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression) {
CompileTimeConstant> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context);
if (compileTimeValue != null) {
return getCompileTimeValue(context, expression, compileTimeValue);
}
return null;
}
@Nullable
public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression, @NotNull CompileTimeConstant> constant) {
KotlinType expectedType = context.getType(expression);
return constant.getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType);
}
@NotNull
public static KtExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) {
KtParameter psiParameter = getParameterForDescriptor(parameterDescriptor);
KtExpression defaultValue = psiParameter.getDefaultValue();
assert defaultValue != null : message(parameterDescriptor, "No default value found in PSI");
return defaultValue;
}
@NotNull
public static ResolvedCall getIteratorFunction(@NotNull BindingContext context,
@NotNull KtExpression rangeExpression) {
return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, rangeExpression);
}
@NotNull
public static ResolvedCall getNextFunction(@NotNull BindingContext context,
@NotNull KtExpression rangeExpression) {
return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, rangeExpression);
}
@NotNull
public static ResolvedCall getHasNextCallable(@NotNull BindingContext context,
@NotNull KtExpression rangeExpression) {
return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression);
}
@NotNull
public static KotlinType getTypeForExpression(@NotNull BindingContext context,
@NotNull KtExpression expression) {
return BindingContextUtils.getTypeNotNull(context, expression);
}
@NotNull
public static ResolvedCall getResolvedCallForArrayAccess(@NotNull BindingContext context,
@NotNull KtArrayAccessExpression arrayAccessExpression,
boolean isGet) {
return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression);
}
@Nullable
@SuppressWarnings("unchecked")
public static ResolvedCall getSuperCall(@NotNull BindingContext context, KtPureClassOrObject classDeclaration) {
for (KtSuperTypeListEntry specifier : classDeclaration.getSuperTypeListEntries()) {
if (specifier instanceof KtSuperTypeCallEntry) {
KtSuperTypeCallEntry superCall = (KtSuperTypeCallEntry) specifier;
return (ResolvedCall) CallUtilKt.getResolvedCallWithAssert(superCall, context);
}
}
return null;
}
}