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);
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// !CHECK_TYPE
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
fun test() {
|
||||
val a = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>[]<!>
|
||||
val b: Array<Int> = []
|
||||
val c = [1, 2]
|
||||
val d: Array<Int> = [1, 2]
|
||||
val e: Array<String> = <!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>[1]<!>
|
||||
|
||||
val f: IntArray = [1, 2]
|
||||
val g = [f]
|
||||
}
|
||||
|
||||
fun check() {
|
||||
[1, 2] checkType { _<Array<Int>>() }
|
||||
[""] checkType { _<Array<String>>() }
|
||||
|
||||
val f: IntArray = [1]
|
||||
[f] checkType { _<Array<IntArray>>() }
|
||||
|
||||
[1, ""] checkType { _<Array<Any>>() }
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun check(): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
fun basicTypes() {
|
||||
val a: IntArray = [1]
|
||||
val b: ByteArray = [1]
|
||||
val c: BooleanArray = [true, false]
|
||||
val d: CharArray = ['a']
|
||||
val e: ShortArray = [1]
|
||||
val f: FloatArray = [1.0f]
|
||||
val g: LongArray = [1]
|
||||
val h: DoubleArray = [1.0]
|
||||
}
|
||||
|
||||
fun basicTypesWithErrors() {
|
||||
val a: IntArray = [<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1.0<!>]
|
||||
val b: ShortArray = [<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1.0<!>]
|
||||
val c: CharArray = [<!TYPE_MISMATCH!>"a"<!>]
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun basicTypes(): kotlin.Unit
|
||||
public fun basicTypesWithErrors(): kotlin.Unit
|
||||
@@ -3332,6 +3332,27 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/collectionLiterals")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CollectionLiterals extends AbstractDiagnosticsTest {
|
||||
public void testAllFilesPresentInCollectionLiterals() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/collectionLiterals"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("basicCollectionLiterals.kt")
|
||||
public void testBasicCollectionLiterals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/basicCollectionLiterals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("collectionLiteralsAsPrimitiveArrays.kt")
|
||||
public void testCollectionLiteralsAsPrimitiveArrays() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/collectionLiteralsAsPrimitiveArrays.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/constructorConsistency")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user