RangeCodegenUtil: convert to Kotlin + cleanup
This commit is contained in:
@@ -2874,8 +2874,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
assert deparenthesized != null : "For with empty range expression";
|
assert deparenthesized != null : "For with empty range expression";
|
||||||
boolean isInverted = operationReference.getReferencedNameElementType() == KtTokens.NOT_IN;
|
boolean isInverted = operationReference.getReferencedNameElementType() == KtTokens.NOT_IN;
|
||||||
return StackValue.operation(Type.BOOLEAN_TYPE, v -> {
|
return StackValue.operation(Type.BOOLEAN_TYPE, v -> {
|
||||||
if (RangeCodegenUtil.isPrimitiveRangeSpecializationOfType(leftValue.type, deparenthesized, bindingContext) ||
|
if (RangeCodegenUtilKt.isPrimitiveRangeSpecializationOfType(leftValue.type, deparenthesized, bindingContext) ||
|
||||||
RangeCodegenUtil.isPrimitiveRangeToExtension(operationReference, bindingContext)) {
|
RangeCodegenUtilKt.isPrimitiveRangeToExtension(operationReference, bindingContext)) {
|
||||||
generateInPrimitiveRange(leftValue, (KtBinaryExpression) deparenthesized, isInverted);
|
generateInPrimitiveRange(leftValue, (KtBinaryExpression) deparenthesized, isInverted);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,228 +14,160 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen;
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
import java.util.Arrays;
|
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||||
import java.util.List;
|
supportedRangeTypes().associateBy {
|
||||||
|
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME;
|
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
|
|
||||||
|
|
||||||
public class RangeCodegenUtil {
|
|
||||||
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
|
|
||||||
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static List<PrimitiveType> supportedRangeTypes() {
|
|
||||||
return Arrays.asList(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
|
|
||||||
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
|
|
||||||
for (PrimitiveType primitiveType : supportedRangeTypes()) {
|
|
||||||
FqName rangeClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
|
|
||||||
FqName progressionClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
|
|
||||||
rangeBuilder.put(rangeClassFqName, primitiveType);
|
|
||||||
progressionBuilder.put(progressionClassFqName, primitiveType);
|
|
||||||
}
|
}
|
||||||
RANGE_TO_ELEMENT_TYPE = rangeBuilder.build();
|
|
||||||
PROGRESSION_TO_ELEMENT_TYPE = progressionBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private RangeCodegenUtil() {}
|
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||||
|
supportedRangeTypes().associateBy {
|
||||||
|
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isRange(KotlinType rangeType) {
|
fun supportedRangeTypes() =
|
||||||
return !rangeType.isMarkedNullable() && getPrimitiveRangeElementType(rangeType) != null;
|
listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isProgression(KotlinType rangeType) {
|
fun isRange(rangeType: KotlinType) =
|
||||||
return !rangeType.isMarkedNullable() && getPrimitiveProgressionElementType(rangeType) != null;
|
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
fun isProgression(rangeType: KotlinType) =
|
||||||
private static PrimitiveType getPrimitiveRangeElementType(KotlinType rangeType) {
|
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
|
||||||
return getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
private fun getPrimitiveRangeElementType(rangeType: KotlinType) =
|
||||||
private static PrimitiveType getPrimitiveProgressionElementType(KotlinType rangeType) {
|
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
|
||||||
return getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
|
||||||
private static PrimitiveType getPrimitiveRangeOrProgressionElementType(
|
getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE)
|
||||||
@NotNull KotlinType rangeOrProgression,
|
|
||||||
@NotNull ImmutableMap<FqName, PrimitiveType> map
|
|
||||||
) {
|
|
||||||
ClassifierDescriptor declarationDescriptor = rangeOrProgression.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (declarationDescriptor == null) return null;
|
|
||||||
FqNameUnsafe fqName = DescriptorUtils.getFqName(declarationDescriptor);
|
|
||||||
if (!fqName.isSafe()) return null;
|
|
||||||
return map.get(fqName.toSafe());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
private fun getPrimitiveRangeOrProgressionElementType(
|
||||||
public static PrimitiveType getPrimitiveRangeOrProgressionElementType(@NotNull FqName rangeOrProgressionName) {
|
rangeOrProgression: KotlinType,
|
||||||
PrimitiveType result = RANGE_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
|
map: Map<FqName, PrimitiveType>
|
||||||
return result != null ? result : PROGRESSION_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
|
): PrimitiveType? {
|
||||||
}
|
val declarationDescriptor = rangeOrProgression.constructor.declarationDescriptor ?: return null
|
||||||
|
val fqName = DescriptorUtils.getFqName(declarationDescriptor).takeIf { it.isSafe } ?: return null
|
||||||
|
return map[fqName.toSafe()]
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isRangeOrProgression(@NotNull FqName className) {
|
fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
|
||||||
return getPrimitiveRangeOrProgressionElementType(className) != null;
|
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
|
||||||
}
|
PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
|
||||||
|
|
||||||
public static boolean isPrimitiveNumberRangeTo(CallableDescriptor rangeTo) {
|
fun isRangeOrProgression(className: FqName) =
|
||||||
if (!"rangeTo".equals(rangeTo.getName().asString())) return false;
|
getPrimitiveRangeOrProgressionElementType(className) != null
|
||||||
|
|
||||||
if (!isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) return false;
|
fun isPrimitiveNumberRangeTo(rangeTo: CallableDescriptor) =
|
||||||
|
"rangeTo" == rangeTo.name.asString() &&
|
||||||
|
isPrimitiveNumberClassDescriptor(rangeTo.containingDeclaration)
|
||||||
|
|
||||||
return true;
|
private fun isPrimitiveRangeToExtension(descriptor: CallableDescriptor): Boolean {
|
||||||
}
|
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
|
||||||
|
|
||||||
private static boolean isPrimitiveRangeToExtension(@NotNull CallableDescriptor descriptor) {
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false;
|
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.type)
|
||||||
|
}
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
fun isPrimitiveNumberDownTo(descriptor: CallableDescriptor): Boolean {
|
||||||
if (extensionReceiver == null) return false;
|
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false
|
||||||
|
|
||||||
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.getType());
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
}
|
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||||
|
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isPrimitiveNumberDownTo(@NotNull CallableDescriptor descriptor) {
|
fun isPrimitiveNumberUntil(descriptor: CallableDescriptor): Boolean {
|
||||||
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false;
|
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
if (extensionReceiver == null) return false;
|
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||||
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
|
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||||
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
|
}
|
||||||
|
|
||||||
return true;
|
fun isArrayOrPrimitiveArrayIndices(descriptor: CallableDescriptor): Boolean {
|
||||||
}
|
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||||
|
|
||||||
public static boolean isPrimitiveNumberUntil(@NotNull CallableDescriptor descriptor) {
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false;
|
val extensionReceiverType = extensionReceiver.type
|
||||||
|
return KotlinBuiltIns.isArray(extensionReceiverType) || KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)
|
||||||
|
}
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
fun isCollectionIndices(descriptor: CallableDescriptor): Boolean {
|
||||||
if (extensionReceiver == null) return false;
|
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||||
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
|
|
||||||
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
|
|
||||||
|
|
||||||
return true;
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
}
|
val extensionReceiverType = extensionReceiver.type
|
||||||
|
return KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isArrayOrPrimitiveArrayIndices(@NotNull CallableDescriptor descriptor) {
|
fun isCharSequenceIndices(descriptor: CallableDescriptor): Boolean {
|
||||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
|
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||||
if (extensionReceiver == null) return false;
|
val extensionReceiverType = extensionReceiver.type
|
||||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
return KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)
|
||||||
if (!KotlinBuiltIns.isArray(extensionReceiverType) && !KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)) return false;
|
}
|
||||||
|
|
||||||
return true;
|
fun isPrimitiveRangeToExtension(operationReference: KtSimpleNameExpression, bindingContext: BindingContext): Boolean {
|
||||||
}
|
val resolvedCall = operationReference.getResolvedCallWithAssert(bindingContext)
|
||||||
|
val receiver = resolvedCall.dispatchReceiver as? ExpressionReceiver ?: return false
|
||||||
public static boolean isCollectionIndices(@NotNull CallableDescriptor descriptor) {
|
|
||||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
|
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
|
||||||
if (extensionReceiver == null) return false;
|
|
||||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
|
||||||
if (!KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isCharSequenceIndices(@NotNull CallableDescriptor descriptor) {
|
|
||||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false;
|
|
||||||
|
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
|
||||||
if (extensionReceiver == null) return false;
|
|
||||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
|
||||||
if (!KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPrimitiveRangeToExtension(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
|
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
|
|
||||||
.getResolvedCallWithAssert(operationReference, bindingContext);
|
|
||||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Range is optimizable if
|
|
||||||
* 'in' receiver is expression 'rangeTo' from stdlib package
|
|
||||||
* and its argument has same primitive type as generic range parameter.
|
|
||||||
* For non-matching primitive types (e.g. int in double range)
|
|
||||||
* dispatch receiver will be null, because extension method will be called.
|
|
||||||
*/
|
|
||||||
if (!(receiver instanceof ExpressionReceiver)) return false;
|
|
||||||
ExpressionReceiver e = (ExpressionReceiver) receiver;
|
|
||||||
|
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedReceiver =
|
|
||||||
CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
|
|
||||||
if (resolvedReceiver == null) return false;
|
|
||||||
|
|
||||||
return isPrimitiveRangeToExtension(resolvedReceiver.getResultingDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks whether for expression 'x in a..b' a..b is primitive integral range
|
* Range is optimizable if
|
||||||
* with same type as x.
|
* receiver is a call for 'rangeTo' from stdlib package
|
||||||
|
* and its argument has same primitive type as generic range parameter.
|
||||||
|
* For non-matching primitive types (e.g. int in double range)
|
||||||
|
* dispatch receiver will be null, because extension method will be called.
|
||||||
*/
|
*/
|
||||||
public static boolean isPrimitiveRangeSpecializationOfType(
|
|
||||||
@NotNull Type argumentType,
|
|
||||||
@NotNull KtExpression rangeExpression,
|
|
||||||
@NotNull BindingContext bindingContext
|
|
||||||
) {
|
|
||||||
if (rangeExpression instanceof KtBinaryExpression &&
|
|
||||||
((KtBinaryExpression) rangeExpression).getOperationReference().getReferencedNameElementType() == KtTokens.RANGE) {
|
|
||||||
KotlinType kotlinType = bindingContext.getType(rangeExpression);
|
|
||||||
assert kotlinType != null;
|
|
||||||
DeclarationDescriptor descriptor = kotlinType.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (descriptor != null) {
|
|
||||||
FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
|
|
||||||
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.longRange)) {
|
|
||||||
return argumentType == Type.LONG_TYPE;
|
|
||||||
}
|
|
||||||
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.charRange) || fqName.equals(KotlinBuiltIns.FQ_NAMES.intRange)) {
|
|
||||||
return AsmUtil.isIntPrimitive(argumentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
val resolvedReceiver = receiver.expression.getResolvedCall(bindingContext) ?: return false
|
||||||
}
|
return isPrimitiveRangeToExtension(resolvedReceiver.resultingDescriptor)
|
||||||
|
}
|
||||||
private static boolean isTopLevelInPackage(@NotNull CallableDescriptor descriptor, @NotNull String name, @NotNull String packageName) {
|
|
||||||
if (!name.equals(descriptor.getName().asString())) return false;
|
/*
|
||||||
|
* Checks whether for expression 'x in a..b' a..b is primitive integral range
|
||||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
* with same type as x.
|
||||||
if (!(containingDeclaration instanceof PackageFragmentDescriptor)) return false;
|
*/
|
||||||
String packageFqName = ((PackageFragmentDescriptor) containingDeclaration).getFqName().asString();
|
fun isPrimitiveRangeSpecializationOfType(
|
||||||
if (!packageName.equals(packageFqName)) return false;
|
argumentType: Type,
|
||||||
|
rangeExpression: KtExpression,
|
||||||
return true;
|
bindingContext: BindingContext
|
||||||
}
|
): Boolean {
|
||||||
|
if (rangeExpression is KtBinaryExpression && rangeExpression.operationReference.getReferencedNameElementType() === KtTokens.RANGE) {
|
||||||
|
val kotlinType = bindingContext.getType(rangeExpression)!!
|
||||||
|
val descriptor = kotlinType.constructor.declarationDescriptor ?: return false
|
||||||
|
val fqName = DescriptorUtils.getFqName(descriptor)
|
||||||
|
return (fqName == KotlinBuiltIns.FQ_NAMES.longRange && argumentType === Type.LONG_TYPE) ||
|
||||||
|
(fqName == KotlinBuiltIns.FQ_NAMES.charRange || fqName == KotlinBuiltIns.FQ_NAMES.intRange) && AsmUtil.isIntPrimitive(argumentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTopLevelInPackage(descriptor: CallableDescriptor, name: String, packageName: String): Boolean {
|
||||||
|
if (name != descriptor.name.asString()) return false
|
||||||
|
|
||||||
|
val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||||
|
val packageFqName = containingDeclaration.fqName.asString()
|
||||||
|
return packageName == packageFqName
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.codegen.RangeCodegenUtil
|
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||||
|
import org.jetbrains.kotlin.codegen.isRangeOrProgression
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -213,7 +213,7 @@ fun AbstractInsnNode.isIteratorMethodCallOfProgression(values: List<BasicValue>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isProgressionClass(type: Type) =
|
fun isProgressionClass(type: Type) =
|
||||||
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(type.internalName))
|
isRangeOrProgression(buildFqNameByInternal(type.internalName))
|
||||||
|
|
||||||
fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List<BasicValue>) =
|
fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List<BasicValue>) =
|
||||||
isAreEqualIntrinsic() && areSameTypedBoxedValues(values)
|
isAreEqualIntrinsic() && areSameTypedBoxedValues(values)
|
||||||
|
|||||||
+4
-4
@@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableMap;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||||
import org.jetbrains.kotlin.codegen.RangeCodegenUtil;
|
import org.jetbrains.kotlin.codegen.RangeCodegenUtilKt;
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IteratorNext;
|
import org.jetbrains.kotlin.codegen.intrinsics.IteratorNext;
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
|
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
@@ -32,7 +32,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
|
|||||||
private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
|
private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
|
||||||
static {
|
static {
|
||||||
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder();
|
||||||
for (PrimitiveType primitiveType : RangeCodegenUtil.supportedRangeTypes()) {
|
for (PrimitiveType primitiveType : RangeCodegenUtilKt.supportedRangeTypes()) {
|
||||||
builder.put(primitiveType.getTypeName().asString(), Type.getType(JvmPrimitiveType.get(primitiveType).getDesc()));
|
builder.put(primitiveType.getTypeName().asString(), Type.getType(JvmPrimitiveType.get(primitiveType).getDesc()));
|
||||||
}
|
}
|
||||||
VALUES_TYPENAME_TO_TYPE = builder.build();
|
VALUES_TYPENAME_TO_TYPE = builder.build();
|
||||||
@@ -41,7 +41,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
|
|||||||
private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
|
private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
|
||||||
static {
|
static {
|
||||||
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder();
|
||||||
for (PrimitiveType elementType : RangeCodegenUtil.supportedRangeTypes()) {
|
for (PrimitiveType elementType : RangeCodegenUtilKt.supportedRangeTypes()) {
|
||||||
builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
|
builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
|
||||||
}
|
}
|
||||||
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build();
|
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build();
|
||||||
@@ -67,7 +67,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public static ProgressionIteratorBasicValue byProgressionClassType(@NotNull Type progressionClassType) {
|
public static ProgressionIteratorBasicValue byProgressionClassType(@NotNull Type progressionClassType) {
|
||||||
FqName classFqName = new FqName(progressionClassType.getClassName());
|
FqName classFqName = new FqName(progressionClassType.getClassName());
|
||||||
PrimitiveType elementType = RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(classFqName);
|
PrimitiveType elementType = RangeCodegenUtilKt.getPrimitiveRangeOrProgressionElementType(classFqName);
|
||||||
return ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE.get(elementType);
|
return ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE.get(elementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.codegen.range
|
package org.jetbrains.kotlin.codegen.range
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.RangeCodegenUtil
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -42,9 +41,9 @@ fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpressio
|
|||||||
return when {
|
return when {
|
||||||
asmRangeType.sort == Type.ARRAY ->
|
asmRangeType.sort == Type.ARRAY ->
|
||||||
ArrayRangeValue()
|
ArrayRangeValue()
|
||||||
RangeCodegenUtil.isRange(rangeType) ->
|
isRange(rangeType) ->
|
||||||
PrimitiveRangeRangeValue()
|
PrimitiveRangeRangeValue()
|
||||||
RangeCodegenUtil.isProgression(rangeType) ->
|
isProgression(rangeType) ->
|
||||||
PrimitiveProgressionRangeValue()
|
PrimitiveProgressionRangeValue()
|
||||||
isSubtypeOfCharSequence(rangeType, state.module.builtIns) ->
|
isSubtypeOfCharSequence(rangeType, state.module.builtIns) ->
|
||||||
CharSequenceRangeValue()
|
CharSequenceRangeValue()
|
||||||
@@ -84,17 +83,17 @@ private fun createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out Calla
|
|||||||
val rangeCallee = rangeCall.resultingDescriptor
|
val rangeCallee = rangeCall.resultingDescriptor
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
RangeCodegenUtil.isPrimitiveNumberRangeTo(rangeCallee) ->
|
isPrimitiveNumberRangeTo(rangeCallee) ->
|
||||||
PrimitiveNumberRangeToRangeValue(rangeCall)
|
PrimitiveNumberRangeToRangeValue(rangeCall)
|
||||||
RangeCodegenUtil.isPrimitiveNumberDownTo(rangeCallee) ->
|
isPrimitiveNumberDownTo(rangeCallee) ->
|
||||||
DownToProgressionRangeValue(rangeCall)
|
DownToProgressionRangeValue(rangeCall)
|
||||||
RangeCodegenUtil.isPrimitiveNumberUntil(rangeCallee) ->
|
isPrimitiveNumberUntil(rangeCallee) ->
|
||||||
PrimitiveNumberUntilRangeValue(rangeCall)
|
PrimitiveNumberUntilRangeValue(rangeCall)
|
||||||
RangeCodegenUtil.isArrayOrPrimitiveArrayIndices(rangeCallee) ->
|
isArrayOrPrimitiveArrayIndices(rangeCallee) ->
|
||||||
ArrayIndicesRangeValue(rangeCall)
|
ArrayIndicesRangeValue(rangeCall)
|
||||||
RangeCodegenUtil.isCollectionIndices(rangeCallee) ->
|
isCollectionIndices(rangeCallee) ->
|
||||||
CollectionIndicesRangeValue(rangeCall)
|
CollectionIndicesRangeValue(rangeCall)
|
||||||
RangeCodegenUtil.isCharSequenceIndices(rangeCallee) ->
|
isCharSequenceIndices(rangeCallee) ->
|
||||||
CharSequenceIndicesRangeValue(rangeCall)
|
CharSequenceIndicesRangeValue(rangeCall)
|
||||||
else ->
|
else ->
|
||||||
null
|
null
|
||||||
|
|||||||
Reference in New Issue
Block a user