FIR checker: add diagnostic EXPECTED_DECLARATION_WITH_BODY

This commit is contained in:
Jinseong Jeon
2021-01-19 15:41:33 -08:00
committed by Mikhail Glukhikh
parent 9341ca3004
commit f9378a3ab7
9 changed files with 33 additions and 12 deletions
@@ -5,10 +5,24 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.hasBody
import org.jetbrains.kotlin.fir.declarations.isExpect
// Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*.
internal fun isInsideExpectClass(containingDeclaration: FirRegularClass, context: CheckerContext): Boolean =
containingDeclaration.isExpect || context.containingDeclarations.asReversed().any { it is FirRegularClass && it.isExpect }
internal fun checkExpectFunction(function: FirSimpleFunction, reporter: DiagnosticReporter) {
val source = function.source ?: return
if (source.kind is FirFakeSourceElementKind) return
if (function.hasBody) {
reporter.report(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY)
}
}
@@ -60,6 +60,11 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
reporter.report(FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(source, function))
}
}
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
if (isExpect) {
checkExpectFunction(function, reporter)
}
}
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
@@ -35,5 +34,9 @@ object FirTopLevelFunctionChecker : FirFileChecker() {
if (!function.hasBody && !hasAbstractModifier && !isExternal && !isExpect) {
reporter.report(FirErrors.NON_MEMBER_FUNCTION_NO_BODY.on(source, function))
}
if (isExpect) {
checkExpectFunction(function, reporter)
}
}
}
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_E
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DECLARATION_WITH_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_FUNCTION_RETURN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PARAMETER_TYPE
@@ -394,6 +395,9 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, "Private setters are not allowed for abstract properties")
map.put(PRIVATE_SETTER_FOR_OPEN_PROPERTY, "Private setters are not allowed for open properties")
// Multi-platform projects
map.put(EXPECTED_DECLARATION_WITH_BODY, "Expected declaration must not have a body")
// Destructuring declaration
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
map.put(
@@ -180,6 +180,9 @@ object FirErrors {
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error0<FirSourceElement, PsiElement>()
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error0<FirSourceElement, PsiElement>()
// Multi-platform projects
val EXPECTED_DECLARATION_WITH_BODY by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// Destructuring declaration
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, KtDestructuringDeclaration>()
val COMPONENT_FUNCTION_MISSING by error2<FirSourceElement, PsiElement, Name, FirTypeRef>()
@@ -5,7 +5,7 @@
expect interface My {
open fun bar()
open fun bas() {}
<!EXPECTED_DECLARATION_WITH_BODY!>open fun bas()<!> {}
<!REDUNDANT_MODIFIER!>open<!> abstract fun bat(): Int
fun foo()
@@ -21,7 +21,7 @@ expect class Foo(
get() = "no"
set(value) {}
fun functionWithBody(x: Int): Int {
<!EXPECTED_DECLARATION_WITH_BODY!>fun functionWithBody(x: Int): Int<!> {
return x + 1
}
}
@@ -1,9 +0,0 @@
// !LANGUAGE: +MultiPlatformProjects
// MODULE: m1-common
// FILE: common.kt
<!CONFLICTING_OVERLOADS!>expect fun foo()<!>
<!CONFLICTING_OVERLOADS!>expect fun foo()<!> {}
expect fun bar() {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +MultiPlatformProjects
// MODULE: m1-common
// FILE: common.kt