Resolve collection literal expression as special array-like function
This commit is contained in:
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -17,5 +17,14 @@
|
||||
package org.jetbrains.kotlin.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
class KtCollectionLiteralExpression(node: ASTNode) : KtExpressionImpl(node)
|
||||
class KtCollectionLiteralExpression(node: ASTNode) : KtExpressionImpl(node), KtReferenceExpression {
|
||||
override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R {
|
||||
return visitor.visitCollectionLiteralExpression(this, data)
|
||||
}
|
||||
|
||||
fun getInnerExpressions(): List<KtExpression> {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, KtExpression::class.java)
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -242,6 +242,10 @@ public class KtVisitor<R, D> extends PsiElementVisitor {
|
||||
return visitExpression(expression, data);
|
||||
}
|
||||
|
||||
public R visitCollectionLiteralExpression(@NotNull KtCollectionLiteralExpression expression, D data) {
|
||||
return visitExpression(expression, data);
|
||||
}
|
||||
|
||||
public R visitTryExpression(@NotNull KtTryExpression expression, D data) {
|
||||
return visitExpression(expression, data);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -229,6 +229,10 @@ public class KtVisitorVoid extends KtVisitor<Void, Void> {
|
||||
super.visitWhenExpression(expression, null);
|
||||
}
|
||||
|
||||
public void visitCollectionLiteralExpression(@NotNull KtCollectionLiteralExpression expression) {
|
||||
super.visitCollectionLiteralExpression(expression, null);
|
||||
}
|
||||
|
||||
public void visitTryExpression(@NotNull KtTryExpression expression) {
|
||||
super.visitTryExpression(expression, null);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -370,6 +370,10 @@ public class KtVisitorVoidWithParameter<P> extends KtVisitor<Void, P> {
|
||||
super.visitWhenEntry(jetWhenEntry, data);
|
||||
}
|
||||
|
||||
public void visitCollectionLiteralExpressionVoid(@NotNull KtCollectionLiteralExpression expression, P data) {
|
||||
super.visitCollectionLiteralExpression(expression, data);
|
||||
}
|
||||
|
||||
public void visitIsExpressionVoid(@NotNull KtIsExpression expression, P data) {
|
||||
super.visitIsExpression(expression, data);
|
||||
}
|
||||
@@ -705,6 +709,12 @@ public class KtVisitorVoidWithParameter<P> extends KtVisitor<Void, P> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCollectionLiteralExpression(@NotNull KtCollectionLiteralExpression expression, P data) {
|
||||
visitCollectionLiteralExpressionVoid(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Void visitTryExpression(@NotNull KtTryExpression expression, P data) {
|
||||
visitTryExpressionVoid(expression, data);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 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.
|
||||
@@ -149,6 +149,8 @@ public interface BindingContext {
|
||||
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_GET = Slices.createSimpleSlice();
|
||||
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_SET = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<KtCollectionLiteralExpression, ResolvedCall<FunctionDescriptor>> COLLECTION_LITERAL_CALL = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<KtExpression, ExplicitSmartCasts> SMARTCAST = new BasicWritableSlice<KtExpression, ExplicitSmartCasts>(DO_NOTHING);
|
||||
WritableSlice<KtExpression, Boolean> SMARTCAST_NULL = Slices.createSimpleSlice();
|
||||
WritableSlice<KtExpression, ImplicitSmartCasts> IMPLICIT_RECEIVER_SMARTCAST = new BasicWritableSlice<KtExpression, ImplicitSmartCasts>(DO_NOTHING);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 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.
|
||||
|
||||
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -250,6 +250,16 @@ public class CallMaker {
|
||||
return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
|
||||
}
|
||||
|
||||
public static Call makeCallForCollectionLiteral(@NotNull KtCollectionLiteralExpression collectionLiteralExpression) {
|
||||
return makeCallWithExpressions(
|
||||
collectionLiteralExpression,
|
||||
null,
|
||||
null,
|
||||
collectionLiteralExpression,
|
||||
collectionLiteralExpression.getInnerExpressions(),
|
||||
CallType.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ValueArgument makeValueArgument(@NotNull KtExpression expression) {
|
||||
return makeValueArgument(expression, expression);
|
||||
|
||||
+58
-4
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
@@ -75,10 +77,7 @@ import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperK
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -98,6 +97,19 @@ import static org.jetbrains.kotlin.types.expressions.TypeReconstructionUtil.reco
|
||||
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
private static final Map<PrimitiveType, Name> PRIMITIVE_TYPE_TO_ARRAY = new HashMap<PrimitiveType, Name>();
|
||||
static {
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.BOOLEAN, Name.identifier("booleanArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.CHAR, Name.identifier("charArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.INT, Name.identifier("intArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.BYTE, Name.identifier("byteArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.SHORT, Name.identifier("shortArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.FLOAT, Name.identifier("floatArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.LONG, Name.identifier("longArrayOf"));
|
||||
PRIMITIVE_TYPE_TO_ARRAY.put(PrimitiveType.DOUBLE, Name.identifier("doubleArrayOf"));
|
||||
}
|
||||
|
||||
private static final Name ARRAY_OF_FUNCTION = Name.identifier("arrayOf");
|
||||
|
||||
private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE);
|
||||
|
||||
@@ -1501,6 +1513,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return components.dataFlowAnalyzer.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitCollectionLiteralExpression(
|
||||
@NotNull KtCollectionLiteralExpression expression, ExpressionTypingContext context
|
||||
) {
|
||||
return resolveCollectionLiteralSpecialMethod(expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitClass(@NotNull KtClass klass, ExpressionTypingContext context) {
|
||||
// analyze class in illegal position and write descriptor to trace but do not write to any scope
|
||||
@@ -1761,4 +1780,39 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
functionResults.getResultingCall());
|
||||
return resultTypeInfo.replaceType(functionResults.getResultingDescriptor().getReturnType());
|
||||
}
|
||||
|
||||
private KotlinTypeInfo resolveCollectionLiteralSpecialMethod(
|
||||
@NotNull KtCollectionLiteralExpression collectionLiteralExpression,
|
||||
@NotNull ExpressionTypingContext context
|
||||
) {
|
||||
Name collectionLiteralCallName;
|
||||
KotlinType expectedType = context.expectedType;
|
||||
if (NO_EXPECTED_TYPE == expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) {
|
||||
collectionLiteralCallName = ARRAY_OF_FUNCTION;
|
||||
}
|
||||
else {
|
||||
ClassifierDescriptor descriptor = expectedType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor != null) {
|
||||
FqNameUnsafe arrayFqName = DescriptorUtils.getFqName(descriptor);
|
||||
PrimitiveType primitiveType = KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(arrayFqName);
|
||||
|
||||
collectionLiteralCallName = PRIMITIVE_TYPE_TO_ARRAY.get(primitiveType);
|
||||
}
|
||||
else {
|
||||
collectionLiteralCallName = ARRAY_OF_FUNCTION;
|
||||
}
|
||||
}
|
||||
|
||||
Call call = CallMaker.makeCallForCollectionLiteral(collectionLiteralExpression);
|
||||
OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
|
||||
context, call, collectionLiteralExpression, collectionLiteralCallName);
|
||||
|
||||
if (!functionResults.isSuccess() || !functionResults.isSingleResult()) {
|
||||
// TODO: report an error
|
||||
return TypeInfoFactoryKt.noTypeInfo(context);
|
||||
}
|
||||
|
||||
context.trace.record(COLLECTION_LITERAL_CALL, collectionLiteralExpression, functionResults.getResultingCall());
|
||||
return TypeInfoFactoryKt.createTypeInfo(functionResults.getResultingDescriptor().getReturnType(), context);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user