[FIR JS] Fix NOT_YET_SUPPORTED_IN_INLINE

This commit is contained in:
Nikolay Lunyak
2022-01-25 13:00:00 +03:00
committed by teamcity
parent ac1fb07102
commit a474acd927
10 changed files with 196 additions and 58 deletions
@@ -5,6 +5,20 @@
package org.jetbrains.kotlin.fir.analysis.js.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker
import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlineDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlinePropertyChecker
object JsDeclarationCheckers : DeclarationCheckers()
object JsDeclarationCheckers : DeclarationCheckers() {
override val functionCheckers: Set<FirFunctionChecker>
get() = setOf(
FirJsInlineDeclarationChecker,
)
override val propertyCheckers: Set<FirPropertyChecker>
get() = setOf(
FirJsInlinePropertyChecker,
)
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.js.checkers.declaration
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
object FirJsInlineDeclarationChecker : FirInlineDeclarationChecker()
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.js.checkers.declaration
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlinePropertyChecker
object FirJsInlinePropertyChecker : FirInlinePropertyChecker() {
override val inlineDeclarationChecker get() = FirJsInlineDeclarationChecker
}
@@ -35,13 +35,15 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirVolatileAnnotationChecker,
FirJvmFieldApplicabilityChecker,
FirJvmSyntheticApplicabilityChecker
FirJvmSyntheticApplicabilityChecker,
FirJvmInlinePropertyChecker,
)
override val functionCheckers: Set<FirFunctionChecker>
get() = setOf(
FirSynchronizedAnnotationChecker,
FirOverloadsChecker,
FirJvmInlineDeclarationChecker,
)
override val typeParameterCheckers: Set<FirTypeParameterChecker>
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
object FirJvmInlineDeclarationChecker : FirInlineDeclarationChecker() {
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isInline) {
checkParametersInNotInline(declaration, context, reporter)
return
}
// local inline functions are prohibited
if (declaration.isLocalMember) {
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context)
return
}
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
val effectiveVisibility = declaration.effectiveVisibility
withSuppressedDiagnostics(declaration, context) { ctx ->
checkInlineFunctionBody(declaration, effectiveVisibility, ctx, reporter)
checkCallableDeclaration(declaration, ctx, reporter)
}
}
override val inlineVisitor get() = ::InlineVisitor
class InlineVisitor(
inlineFunction: FirFunction,
inlineFunEffectiveVisibility: EffectiveVisibility,
inalienableParameters: List<FirValueParameterSymbol>,
session: FirSession,
reporter: DiagnosticReporter
) : BasicInlineVisitor(
inlineFunction,
inlineFunEffectiveVisibility,
inalienableParameters,
session,
reporter
) {
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) {
reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data)
} else {
super.visitRegularClass(regularClass, data)
}
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) {
if (data.containingDeclarations.lastOrNull() === inlineFunction) {
reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data)
} else {
super.visitSimpleFunction(simpleFunction, data)
}
}
}
override fun checkSuspendFunctionalParameterWithDefaultValue(
param: FirValueParameter,
context: CheckerContext,
reporter: DiagnosticReporter,
) {
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Suspend functional parameters with default values",
context
)
}
override fun checkFunctionalParametersWithInheritedDefaultValues(
function: FirSimpleFunction,
context: CheckerContext,
reporter: DiagnosticReporter,
overriddenSymbols: List<FirCallableSymbol<out FirCallableDeclaration>>,
) {
val paramsWithDefaults = overriddenSymbols.flatMap {
if (it !is FirFunctionSymbol<*>) return@flatMap emptyList<Int>()
it.valueParameterSymbols.mapIndexedNotNull { idx, param ->
idx.takeIf { param.hasDefaultValue }
}
}.toSet()
function.valueParameters.forEachIndexed { idx, param ->
if (param.defaultValue == null && paramsWithDefaults.contains(idx)) {
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Functional parameters with inherited default values",
context
)
}
}
}
}
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlinePropertyChecker
object FirJvmInlinePropertyChecker : FirInlinePropertyChecker() {
override val inlineDeclarationChecker get() = FirJvmInlineDeclarationChecker
}
@@ -43,7 +43,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirContractChecker,
FirFunctionParameterChecker,
FirInlineDeclarationChecker,
FirFunctionReturnChecker,
)
@@ -67,7 +66,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirInitializerTypeMismatchChecker,
FirDelegatedPropertyChecker,
FirPropertyFieldTypeChecker,
FirInlinePropertyChecker,
FirPropertyFromParameterChecker,
FirLocalVariableTypeParametersSyntaxChecker,
FirDelegateUsesExtensionPropertyTypeParameterChecker,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -42,17 +42,13 @@ import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.util.OperatorNameConventions
object FirInlineDeclarationChecker : FirFunctionChecker() {
abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isInline) {
checkParametersInNotInline(declaration, context, reporter)
return
}
// local inline functions are prohibited
if (declaration.isLocalMember) {
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context)
return
}
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
val effectiveVisibility = declaration.effectiveVisibility
@@ -62,7 +58,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
}
}
private fun checkInlineFunctionBody(
protected fun checkInlineFunctionBody(
function: FirFunction,
effectiveVisibility: EffectiveVisibility,
context: CheckerContext,
@@ -75,7 +71,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
!type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType }
}.map { it.symbol }
val visitor = Visitor(
val visitor = inlineVisitor(
function,
effectiveVisibility,
inalienableParameters,
@@ -87,7 +83,9 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
}
}
private class Visitor(
open val inlineVisitor get() = ::BasicInlineVisitor
open class BasicInlineVisitor(
val inlineFunction: FirFunction,
val inlineFunEffectiveVisibility: EffectiveVisibility,
val inalienableParameters: List<FirValueParameterSymbol>,
@@ -125,22 +123,6 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
checkQualifiedAccess(variableAssignment, setterSymbol, data)
}
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) {
reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data)
} else {
super.visitRegularClass(regularClass, data)
}
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) {
if (data.containingDeclarations.lastOrNull() === inlineFunction) {
reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data)
} else {
super.visitSimpleFunction(simpleFunction, data)
}
}
private fun checkReceiversOfQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
targetSymbol: FirBasedSymbol<*>?,
@@ -354,6 +336,21 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
}
}
protected open fun checkSuspendFunctionalParameterWithDefaultValue(
param: FirValueParameter,
context: CheckerContext,
reporter: DiagnosticReporter,
) {
}
protected open fun checkFunctionalParametersWithInheritedDefaultValues(
function: FirSimpleFunction,
context: CheckerContext,
reporter: DiagnosticReporter,
overriddenSymbols: List<FirCallableSymbol<out FirCallableDeclaration>>,
) {
}
private fun checkParameters(
function: FirSimpleFunction,
overriddenSymbols: List<FirCallableSymbol<out FirCallableDeclaration>>,
@@ -373,12 +370,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
if (param.isNoinline) continue
if (function.isSuspend && defaultValue != null && isSuspendFunctionalType) {
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Suspend functional parameters with default values",
context
)
checkSuspendFunctionalParameterWithDefaultValue(param, context, reporter)
}
if (isSuspendFunctionalType && !param.isCrossinline) {
@@ -419,25 +411,10 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
}
//check for inherited default values
val paramsWithDefaults = overriddenSymbols.flatMap {
if (it !is FirFunctionSymbol<*>) return@flatMap emptyList<Int>()
it.valueParameterSymbols.mapIndexedNotNull { idx, param ->
idx.takeIf { param.hasDefaultValue }
}
}.toSet()
function.valueParameters.forEachIndexed { idx, param ->
if (param.defaultValue == null && paramsWithDefaults.contains(idx)) {
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Functional parameters with inherited default values",
context
)
}
}
checkFunctionalParametersWithInheritedDefaultValues(function, context, reporter, overriddenSymbols)
}
private fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
protected fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
for (param in function.valueParameters) {
if (param.isNoinline || param.isCrossinline) {
reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context)
@@ -493,7 +470,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
expression is FirAnonymousFunctionExpression ||
(expression is FirConstExpression<*> && expression.value == null) //this will be reported separately
internal fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration is FirPropertyAccessor) return
val overriddenSymbols = declaration.getOverriddenSymbols(context)
if (declaration is FirSimpleFunction) {
@@ -13,12 +13,13 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isInline
object FirInlinePropertyChecker : FirPropertyChecker() {
abstract class FirInlinePropertyChecker : FirPropertyChecker() {
abstract val inlineDeclarationChecker: FirInlineDeclarationChecker
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.getter?.isInline != true && declaration.setter?.isInline != true) return
FirInlineDeclarationChecker.checkCallableDeclaration(declaration, context, reporter)
inlineDeclarationChecker.checkCallableDeclaration(declaration, context, reporter)
if (declaration.hasBackingField || declaration.delegate != null) {
reporter.reportOn(declaration.source, FirErrors.INLINE_PROPERTY_WITH_BACKING_FIELD, context)
@@ -85,7 +85,7 @@ internal val FirDeclaration.isEnumEntryInitializer: Boolean
}
// contract: returns(true) implies (this is FirMemberDeclaration<*>)
internal val FirDeclaration.isLocalMember: Boolean
val FirDeclaration.isLocalMember: Boolean
get() = symbol.isLocalMember
internal val FirBasedSymbol<*>.isLocalMember: Boolean