Prototype of collection literals using 'Type.of(...)'
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
index 02b28f8..631c856 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
@@ -531,6 +531,19 @@
token,
)
}
+ add(FirErrors.COLLECTION_LITERAL_UNKNOWN_TYPE) { firDiagnostic ->
+ CollectionLiteralUnknownTypeImpl(
+ firDiagnostic as KtPsiDiagnostic,
+ token,
+ )
+ }
+ add(FirErrors.COLLECTION_LITERAL_NO_BUILDER) { firDiagnostic ->
+ CollectionLiteralNoBuilderImpl(
+ firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
+ firDiagnostic as KtPsiDiagnostic,
+ token,
+ )
+ }
add(FirErrors.SUPER_IS_NOT_AN_EXPRESSION) { firDiagnostic ->
SuperIsNotAnExpressionImpl(
firDiagnostic as KtPsiDiagnostic,
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
index 57e91d7..63c137a 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
@@ -418,6 +418,15 @@
val suggestedFunction: String
}
+ interface CollectionLiteralUnknownType : KtFirDiagnostic<PsiElement> {
+ override val diagnosticClass get() = CollectionLiteralUnknownType::class
+ }
+
+ interface CollectionLiteralNoBuilder : KtFirDiagnostic<PsiElement> {
+ override val diagnosticClass get() = CollectionLiteralNoBuilder::class
+ val type: KtType
+ }
+
interface SuperIsNotAnExpression : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = SuperIsNotAnExpression::class
}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
index 8d6403b..b9d74d6 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
@@ -485,6 +485,17 @@
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.DeprecatedBinaryMod
+internal class CollectionLiteralUnknownTypeImpl(
+ firDiagnostic: KtPsiDiagnostic,
+ token: KtLifetimeToken,
+) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.CollectionLiteralUnknownType
+
+internal class CollectionLiteralNoBuilderImpl(
+ override val type: KtType,
+ firDiagnostic: KtPsiDiagnostic,
+ token: KtLifetimeToken,
+) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.CollectionLiteralNoBuilder
+
internal class SuperIsNotAnExpressionImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
index f556b3f0..293f2aa 100644
--- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
+++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
@@ -224,6 +224,10 @@
parameter<FirBasedSymbol<*>>("forbiddenFunction")
parameter<String>("suggestedFunction")
}
+ val COLLECTION_LITERAL_UNKNOWN_TYPE by error<PsiElement>()
+ val COLLECTION_LITERAL_NO_BUILDER by error<PsiElement> {
+ parameter<ConeKotlinType>("type")
+ }
}
val SUPER by object : DiagnosticGroup("Super") {
diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
index cdeaf2d..15e6658 100644
--- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
+++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
@@ -202,6 +202,8 @@
val AMBIGUOUS_ALTERED_ASSIGN: KtDiagnosticFactory1<List<String?>> by error1<PsiElement, List<String?>>()
val FORBIDDEN_BINARY_MOD: KtDiagnosticFactory2<FirBasedSymbol<*>, String> by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER)
val DEPRECATED_BINARY_MOD: KtDiagnosticFactory2<FirBasedSymbol<*>, String> by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER)
+ val COLLECTION_LITERAL_UNKNOWN_TYPE: KtDiagnosticFactory0 by error0<PsiElement>()
+ val COLLECTION_LITERAL_NO_BUILDER: KtDiagnosticFactory1<ConeKotlinType> by error1<PsiElement, ConeKotlinType>()
// Super
val SUPER_IS_NOT_AN_EXPRESSION: KtDiagnosticFactory0 by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt
index 5959330..f87d032 100644
--- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt
+++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt
@@ -68,6 +68,8 @@
"AMBIGUOUS_ALTERED_ASSIGN",
"FORBIDDEN_BINARY_MOD",
"DEPRECATED_BINARY_MOD",
+ "COLLECTION_LITERAL_UNKNOWN_TYPE",
+ "COLLECTION_LITERAL_NO_BUILDER",
"SUPER_IS_NOT_AN_EXPRESSION",
"SUPER_NOT_AVAILABLE",
"ABSTRACT_SUPER_CALL",
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt
index 3d9c85f..327d29e 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt
@@ -176,7 +176,7 @@
override val arrayLiteralCheckers: Set<FirArrayLiteralChecker>
get() = setOf(
- FirUnsupportedArrayLiteralChecker
+ // FirUnsupportedArrayLiteralChecker // collection literals
)
override val inaccessibleReceiverCheckers: Set<FirInaccessibleReceiverChecker>
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
index d840b0e..186b575 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
@@ -134,6 +134,8 @@
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_INHERITS_JAVA_SEALED_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_LITERAL_LHS_NOT_A_CLASS
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COLLECTION_LITERAL_NO_BUILDER
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COLLECTION_LITERAL_UNKNOWN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_MISSING
@@ -872,6 +874,8 @@
)
map.put(DEPRECATED_BINARY_MOD, "Convention for ''{0}'' is prohibited. Use ''{1}''.", SYMBOL, STRING)
map.put(FORBIDDEN_BINARY_MOD, "Deprecated convention for ''{0}''. Use ''{1}''.", SYMBOL, STRING)
+ map.put(COLLECTION_LITERAL_UNKNOWN_TYPE, "Unresolved type for collection literal")
+ map.put(COLLECTION_LITERAL_NO_BUILDER, "No available collection builder for ''{0}''.", RENDER_TYPE)
map.put(ILLEGAL_SELECTOR, "The expression cannot be a selector (cannot occur after a dot).")
map.put(NO_RECEIVER_ALLOWED, "No receiver can be passed to this function or property.")
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
index 2ddeb0b..e65d62c 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
@@ -188,6 +188,8 @@
is ConeAmbiguousFunctionTypeKinds -> FirErrors.AMBIGUOUS_FUNCTION_TYPE_KIND.createOn(source, kinds)
is ConeUnsupportedClassLiteralsWithEmptyLhs -> FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS.createOn(source)
is ConeMissingConstructorKeyword -> FirErrors.MISSING_CONSTRUCTOR_KEYWORD.createOn(source)
+ is ConeUnknownCollectionLiteralTypeDiagnostic -> FirErrors.COLLECTION_LITERAL_UNKNOWN_TYPE.createOn(source)
+ is ConeMissingCollectionLiteralBuilderDiagnostic -> FirErrors.COLLECTION_LITERAL_NO_BUILDER.createOn(source, type)
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
index 54d1f57..b61bd89 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
@@ -34,6 +34,7 @@
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirStubReference
import org.jetbrains.kotlin.fir.references.isError
+import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
@@ -42,13 +43,14 @@
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
+import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
+import org.jetbrains.kotlin.fir.scopes.getFunctions
+import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.SyntheticCallableId
-import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
-import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
-import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
-import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
+import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
+import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -67,7 +69,6 @@
private val whenSelectFunction: FirSimpleFunction = generateSyntheticSelectFunction(SyntheticCallableId.WHEN)
private val trySelectFunction: FirSimpleFunction = generateSyntheticSelectFunction(SyntheticCallableId.TRY)
- private val idFunction: FirSimpleFunction = generateSyntheticSelectFunction(SyntheticCallableId.ID)
private val checkNotNullFunction: FirSimpleFunction = generateSyntheticCheckNotNullFunction()
private val elvisFunction: FirSimpleFunction = generateSyntheticElvisFunction()
private val arrayOfSymbolCache: FirCache<Name, FirNamedFunctionSymbol?, Nothing?> = session.firCachesFactory.createCache(::getArrayOfSymbol)
@@ -172,52 +173,81 @@
return elvisExpression.transformCalleeReference(UpdateReference, reference)
}
- fun generateSyntheticIdCall(arrayLiteral: FirExpression, context: ResolutionContext, resolutionMode: ResolutionMode): FirFunctionCall {
- val argumentList = buildArgumentList {
- arguments += arrayLiteral
- }
- return buildFunctionCall {
- this.argumentList = argumentList
- calleeReference = generateCalleeReferenceWithCandidate(
- arrayLiteral,
- idFunction,
- argumentList,
- SyntheticCallableId.ID.callableName,
- context = context,
- resolutionMode = resolutionMode,
- )
- }
- }
-
fun generateSyntheticArrayOfCall(
arrayLiteral: FirArrayLiteral,
expectedTypeRef: FirTypeRef,
context: ResolutionContext,
resolutionMode: ResolutionMode,
- ): FirFunctionCall {
+ ): FirFunctionCall? {
val argumentList = arrayLiteral.argumentList
- val arrayOfSymbol = calculateArrayOfSymbol(expectedTypeRef)
- return buildFunctionCall {
- this.argumentList = argumentList
- calleeReference = arrayOfSymbol?.let {
- generateCalleeReferenceWithCandidate(
+ if (@OptIn(UnexpandedTypeCheck::class) expectedTypeRef.isArrayType) {
+ val arrayOfSymbol = calculateArrayOfSymbol(expectedTypeRef)
+ return buildFunctionCall {
+ this.argumentList = argumentList
+ calleeReference = arrayOfSymbol?.let {
+ generateCalleeReferenceWithCandidate(
+ arrayLiteral,
+ it.fir,
+ argumentList,
+ ArrayFqNames.ARRAY_OF_FUNCTION,
+ callKind = CallKind.Function,
+ context = context,
+ resolutionMode,
+ )
+ } ?: buildErrorNamedReference {
+ diagnostic = ConeUnresolvedNameError(ArrayFqNames.ARRAY_OF_FUNCTION)
+ }
+ source = arrayLiteral.source
+ }.also {
+ if (arrayOfSymbol == null) {
+ it.resultType = components.typeFromCallee(it).type
+ }
+ }
+ } else {
+ val type = expectedTypeRef.coneType.fullyExpandedType(session)
+ val klass = type.toSymbol(session)?.fir as? FirRegularClass ?: return null
+ val scope = klass.companionObjectSymbol?.unsubstitutedScope(
+ session,
+ components.scopeSession,
+ false,
+ FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE
+ ) ?: klass.scopeProvider.getStaticMemberScopeForCallables(
+ klass,
+ session,
+ components.scopeSession
+ ) ?: return null
+ val ofFunction = scope.getFunctions(Name.identifier("of")).singleOrNull {
+ it.fir.valueParameters.size == 1 && it.fir.valueParameters.first().isVararg
+ } ?: return null
+ return buildFunctionCall {
+ this.argumentList = argumentList
+ calleeReference = generateCalleeReferenceWithCandidate(
arrayLiteral,
- it.fir,
+ ofFunction.fir,
argumentList,
- ArrayFqNames.ARRAY_OF_FUNCTION,
+ ofFunction.name,
callKind = CallKind.Function,
context = context,
- resolutionMode,
+ resolutionMode
)
- } ?: buildErrorNamedReference {
- diagnostic = ConeUnresolvedNameError(ArrayFqNames.ARRAY_OF_FUNCTION)
- }
- source = arrayLiteral.source
- }.also {
- if (arrayOfSymbol == null) {
- it.resultType = components.typeFromCallee(it).type
+ type.typeArguments.forEach {
+ when (it.kind) {
+ ProjectionKind.STAR -> typeArguments.add(buildStarProjection())
+ else -> typeArguments.add(buildTypeProjectionWithVariance {
+ typeRef = it.type!!.toFirResolvedTypeRef()
+ variance = when (it.kind) {
+ ProjectionKind.IN -> Variance.IN_VARIANCE
+ ProjectionKind.OUT -> Variance.OUT_VARIANCE
+ ProjectionKind.INVARIANT -> Variance.INVARIANT
+ else -> throw IllegalStateException()
+ }
+ })
+ }
+ }
+ source = arrayLiteral.source
}
}
+
}
private fun calculateArrayOfSymbol(expectedTypeRef: FirTypeRef): FirNamedFunctionSymbol? {
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
index 4c49bda..72cbc60 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
@@ -1659,19 +1659,21 @@
resolutionContext,
data,
)
- callCompleter.completeCall(call, data)
- arrayOfCallTransformer.transformFunctionCall(call, session)
+ if (call != null) {
+ callCompleter.completeCall(call, data)
+ arrayOfCallTransformer.transformFunctionCall(call, session)
+ } else {
+ buildErrorExpression {
+ source = arrayLiteral.source
+ diagnostic = ConeMissingCollectionLiteralBuilderDiagnostic(data.expectedTypeRef.type)
+ }
+ }
}
else -> {
- // Other unsupported usage.
- val syntheticIdCall = components.syntheticCallGenerator.generateSyntheticIdCall(
- arrayLiteral,
- resolutionContext,
- data,
- )
- arrayLiteral.transformChildren(transformer, ResolutionMode.ContextDependent)
- callCompleter.completeCall(syntheticIdCall, data)
- arrayLiteral
+ buildErrorExpression {
+ source = arrayLiteral.source
+ diagnostic = ConeUnknownCollectionLiteralTypeDiagnostic()
+ }
}
}
}
diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
index ae564b4..be86658 100644
--- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
+++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
@@ -24,6 +24,7 @@
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirQualifierPart
import org.jetbrains.kotlin.fir.types.FirTypeRef
+import org.jetbrains.kotlin.fir.types.renderReadable
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -358,6 +359,14 @@
override val reason: String get() = "Unknown return lambda parameter type"
}
+class ConeUnknownCollectionLiteralTypeDiagnostic : ConeDiagnostic {
+ override val reason: String get() = "Unknown collection type"
+}
+
+class ConeMissingCollectionLiteralBuilderDiagnostic(val type: ConeKotlinType) : ConeDiagnostic {
+ override val reason: String get() = "No collection builder for ${type.renderReadable()}"
+}
+
private fun describeSymbol(symbol: FirBasedSymbol<*>): String {
return when (symbol) {
is FirClassLikeSymbol<*> -> symbol.classId.asString()