[FIR] Extension point for function calls

This extension point allows changing the return type of call
 from a declared type to its subtype.
With an idea that such a plugin needs the ability to
control available (extension) properties for this type.
A set of properties should be decided based on the resolved function,
provided arguments, types, and resolved lambdas.
It is not a goal to enable plugins to affect resolution in any way.
Types are not intended to have any structured capabilities

In other words.
The goal was to come up with a way to enable a limited form
of an "extensible records" mechanism through plugins.
- It should give enough value for a practical use.
(more info in the ticket).
- It should have minimal effect on the compilation process
This appears to be an extension point that solves this problem.

^KT-65859 Fixed
This commit is contained in:
Nikita Klimenko
2024-02-09 21:10:56 +02:00
committed by Space Team
parent 4d04546652
commit c49edfef04
14 changed files with 225 additions and 6 deletions
@@ -210,6 +210,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val INNER_CLASS_CONSTRUCTOR_NO_RECEIVER by error<PsiElement> {
parameter<FirRegularClassSymbol>("classSymbol")
}
val PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL by error<PsiElement> {
parameter<List<String>>("names")
}
val RESOLUTION_TO_CLASSIFIER by error<PsiElement> {
parameter<FirRegularClassSymbol>("classSymbol")
}
@@ -200,6 +200,7 @@ object FirErrors {
val INTERFACE_AS_FUNCTION: KtDiagnosticFactory1<FirRegularClassSymbol> by error1<PsiElement, FirRegularClassSymbol>()
val EXPECT_CLASS_AS_FUNCTION: KtDiagnosticFactory1<FirRegularClassSymbol> by error1<PsiElement, FirRegularClassSymbol>()
val INNER_CLASS_CONSTRUCTOR_NO_RECEIVER: KtDiagnosticFactory1<FirRegularClassSymbol> by error1<PsiElement, FirRegularClassSymbol>()
val PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL: KtDiagnosticFactory1<List<String>> by error1<PsiElement, List<String>>()
val RESOLUTION_TO_CLASSIFIER: KtDiagnosticFactory1<FirRegularClassSymbol> by error1<PsiElement, FirRegularClassSymbol>()
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)
@@ -64,6 +64,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
"INTERFACE_AS_FUNCTION",
"EXPECT_CLASS_AS_FUNCTION",
"INNER_CLASS_CONSTRUCTOR_NO_RECEIVER",
"PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL",
"RESOLUTION_TO_CLASSIFIER",
"AMBIGUOUS_ALTERED_ASSIGN",
"FORBIDDEN_BINARY_MOD",
@@ -510,6 +510,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_CANNOT_BE_IMPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_OR_CLASSIFIER_REDECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PLATFORM_CLASS_MAPPED_TO_KOTLIN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.POTENTIALLY_NON_REPORTED_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRE_RELEASE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
@@ -882,6 +883,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
"Multiple extensions attempted to alter this assignment at the same time. Extensions: {0}",
COLLECTION(NULLABLE_STRING)
)
map.put(
PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL,
"Multiple extensions attempted to modify this function call. Extensions: {0}",
COLLECTION(NULLABLE_STRING)
)
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)
@@ -397,6 +397,8 @@ private fun mapInapplicableCandidateError(
// Reported later
is TypeParameterAsExpression -> null
is AmbiguousInterceptedSymbol -> FirErrors.PLUGIN_AMBIGUOUS_INTERCEPTED_SYMBOL.createOn(source, rootCause.pluginNames)
else -> genericDiagnostic
}
}.distinct()