Avoid getting descriptors for collection literals from built-ins scope

#KT-18845 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2017-07-05 18:08:46 +03:00
parent 1de685949b
commit daa8521729
5 changed files with 45 additions and 37 deletions
@@ -66,6 +66,8 @@ public interface Errors {
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Throwable> EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, Throwable> EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_STDLIB = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR);
@@ -578,6 +578,7 @@ public class DefaultErrorMessages {
MAP.put(EXPERIMENTAL_FEATURE_ERROR, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR)); MAP.put(EXPERIMENTAL_FEATURE_ERROR, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR));
MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE); MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE);
MAP.put(MISSING_STDLIB, "{0}. Ensure you have the standard Kotlin library in dependencies", STRING);
MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE); MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE);
MAP.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here"); MAP.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here");
MAP.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE); MAP.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE);
@@ -21,9 +21,9 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED_FEATURE
import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -39,43 +39,47 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
object CollectionLiteralResolver { class CollectionLiteralResolver(val module: ModuleDescriptor, val callResolver: CallResolver, val languageVersionSettings: LanguageVersionSettings) {
val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf( companion object {
PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"), val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf(
PrimitiveType.CHAR to Name.identifier("charArrayOf"), PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"),
PrimitiveType.INT to Name.identifier("intArrayOf"), PrimitiveType.CHAR to Name.identifier("charArrayOf"),
PrimitiveType.BYTE to Name.identifier("byteArrayOf"), PrimitiveType.INT to Name.identifier("intArrayOf"),
PrimitiveType.SHORT to Name.identifier("shortArrayOf"), PrimitiveType.BYTE to Name.identifier("byteArrayOf"),
PrimitiveType.FLOAT to Name.identifier("floatArrayOf"), PrimitiveType.SHORT to Name.identifier("shortArrayOf"),
PrimitiveType.LONG to Name.identifier("longArrayOf"), PrimitiveType.FLOAT to Name.identifier("floatArrayOf"),
PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf") PrimitiveType.LONG to Name.identifier("longArrayOf"),
) PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf")
)
val ARRAY_OF_FUNCTION = Name.identifier("arrayOf") val ARRAY_OF_FUNCTION = Name.identifier("arrayOf")
}
fun resolveCollectionLiteral(collectionLiteralExpression: KtCollectionLiteralExpression, fun resolveCollectionLiteral(
context: ExpressionTypingContext, collectionLiteralExpression: KtCollectionLiteralExpression,
callResolver: CallResolver, context: ExpressionTypingContext
builtIns: KotlinBuiltIns,
languageVersionSettings: LanguageVersionSettings
): KotlinTypeInfo { ): KotlinTypeInfo {
if (!isInsideAnnotationEntryOrClass(collectionLiteralExpression)) { if (!isInsideAnnotationEntryOrClass(collectionLiteralExpression)) {
context.trace.report(UNSUPPORTED.on(collectionLiteralExpression, "Collection literals outside of annotations")) context.trace.report(UNSUPPORTED.on(collectionLiteralExpression, "Collection literals outside of annotations"))
} }
checkSupportsArrayLiterals(collectionLiteralExpression, context, languageVersionSettings) checkSupportsArrayLiterals(collectionLiteralExpression, context)
return resolveCollectionLiteralSpecialMethod(collectionLiteralExpression, context, callResolver, builtIns) return resolveCollectionLiteralSpecialMethod(collectionLiteralExpression, context)
} }
private fun resolveCollectionLiteralSpecialMethod( private fun resolveCollectionLiteralSpecialMethod(
expression: KtCollectionLiteralExpression, expression: KtCollectionLiteralExpression,
context: ExpressionTypingContext, context: ExpressionTypingContext
callResolver: CallResolver,
builtIns: KotlinBuiltIns
): KotlinTypeInfo { ): KotlinTypeInfo {
val call = CallMaker.makeCallForCollectionLiteral(expression) val call = CallMaker.makeCallForCollectionLiteral(expression)
val functionDescriptor = getFunctionDescriptorForCollectionLiteral(expression, context, builtIns) val callName = getArrayFunctionCallName(context.expectedType)
val functionDescriptor = getFunctionDescriptorForCollectionLiteral(expression, callName)
if (functionDescriptor == null) {
context.trace.report(MISSING_STDLIB.on(
expression, "Collection literal call '$callName()' is unresolved"))
return noTypeInfo(context)
}
val resolutionResults = callResolver.resolveCollectionLiteralCallWithGivenDescriptor(context, expression, call, functionDescriptor) val resolutionResults = callResolver.resolveCollectionLiteralCallWithGivenDescriptor(context, expression, call, functionDescriptor)
@@ -90,17 +94,13 @@ object CollectionLiteralResolver {
private fun getFunctionDescriptorForCollectionLiteral( private fun getFunctionDescriptorForCollectionLiteral(
expression: KtCollectionLiteralExpression, expression: KtCollectionLiteralExpression,
context: ExpressionTypingContext, callName: Name
builtIns: KotlinBuiltIns ): SimpleFunctionDescriptor? {
): SimpleFunctionDescriptor { val memberScopeOfKotlinPackage = module.getPackage(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME).memberScope
val callName = getArrayFunctionCallName(context.expectedType) return memberScopeOfKotlinPackage.getContributedFunctions(callName, KotlinLookupLocation(expression)).singleOrNull()
return builtIns.builtInsPackageScope.getContributedFunctions(callName, KotlinLookupLocation(expression)).single()
} }
private fun checkSupportsArrayLiterals(expression: KtCollectionLiteralExpression, private fun checkSupportsArrayLiterals(expression: KtCollectionLiteralExpression, context: ExpressionTypingContext) {
context: ExpressionTypingContext,
languageVersionSettings: LanguageVersionSettings
) {
if (isInsideAnnotationEntryOrClass(expression) && if (isInsideAnnotationEntryOrClass(expression) &&
!languageVersionSettings.supportsFeature(LanguageFeature.ArrayLiteralsInAnnotations)) { !languageVersionSettings.supportsFeature(LanguageFeature.ArrayLiteralsInAnnotations)) {
context.trace.report(UNSUPPORTED_FEATURE.on(expression, LanguageFeature.ArrayLiteralsInAnnotations to languageVersionSettings)) context.trace.report(UNSUPPORTED_FEATURE.on(expression, LanguageFeature.ArrayLiteralsInAnnotations to languageVersionSettings))
@@ -1423,8 +1423,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public KotlinTypeInfo visitCollectionLiteralExpression( public KotlinTypeInfo visitCollectionLiteralExpression(
@NotNull KtCollectionLiteralExpression expression, ExpressionTypingContext context @NotNull KtCollectionLiteralExpression expression, ExpressionTypingContext context
) { ) {
return CollectionLiteralResolver.INSTANCE.resolveCollectionLiteral( return components.collectionLiteralResolver.resolveCollectionLiteral(expression, context);
expression, context, components.callResolver, components.builtIns, components.languageVersionSettings);
} }
@Override @Override
@@ -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"); * 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.
@@ -62,6 +62,7 @@ public class ExpressionTypingComponents {
/*package*/ LanguageVersionSettings languageVersionSettings; /*package*/ LanguageVersionSettings languageVersionSettings;
/*package*/ Iterable<RttiExpressionChecker> rttiExpressionCheckers; /*package*/ Iterable<RttiExpressionChecker> rttiExpressionCheckers;
/*package*/ WrappedTypeFactory wrappedTypeFactory; /*package*/ WrappedTypeFactory wrappedTypeFactory;
/*package*/ CollectionLiteralResolver collectionLiteralResolver;
@Inject @Inject
public void setGlobalContext(@NotNull GlobalContext globalContext) { public void setGlobalContext(@NotNull GlobalContext globalContext) {
@@ -207,4 +208,9 @@ public class ExpressionTypingComponents {
public void setWrappedTypeFactory(WrappedTypeFactory wrappedTypeFactory) { public void setWrappedTypeFactory(WrappedTypeFactory wrappedTypeFactory) {
this.wrappedTypeFactory = wrappedTypeFactory; this.wrappedTypeFactory = wrappedTypeFactory;
} }
@Inject
public void setCollectionLiteralResolver(CollectionLiteralResolver collectionLiteralResolver) {
this.collectionLiteralResolver = collectionLiteralResolver;
}
} }