FIR checker: introduce top-level function checker
This commit is contained in:
committed by
Mikhail Glukhikh
parent
df68f319bc
commit
9341ca3004
+2
-1
@@ -19,7 +19,8 @@ FILE: operatorsOverLiterals.kt
|
|||||||
}
|
}
|
||||||
public final fun R|kotlin/Int|.bar(): R|kotlin/Int| {
|
public final fun R|kotlin/Int|.bar(): R|kotlin/Int| {
|
||||||
}
|
}
|
||||||
public final fun R|kotlin/Int|.baz(): R|kotlin/Int|
|
public final fun R|kotlin/Int|.baz(): R|kotlin/Int| {
|
||||||
|
}
|
||||||
public final fun R|kotlin/Byte|.baz(): R|kotlin/Byte| {
|
public final fun R|kotlin/Byte|.baz(): R|kotlin/Byte| {
|
||||||
}
|
}
|
||||||
public final fun test_3(): R|kotlin/Unit| {
|
public final fun test_3(): R|kotlin/Unit| {
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ fun test_2(n: Int) {
|
|||||||
|
|
||||||
fun Int.bar(): Int {}
|
fun Int.bar(): Int {}
|
||||||
|
|
||||||
fun Int.baz(): Int
|
fun Int.baz(): Int {}
|
||||||
fun Byte.baz(): Byte {}
|
fun Byte.baz(): Byte {}
|
||||||
|
|
||||||
fun test_3() {
|
fun test_3() {
|
||||||
|
|||||||
+2
-1
@@ -111,7 +111,8 @@ FILE: conflictingOverloads.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public final fun mest(): R|kotlin/Unit|
|
public final fun mest(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
public final class mest : R|kotlin/Any| {
|
public final class mest : R|kotlin/Any| {
|
||||||
public constructor(): R|mest| {
|
public constructor(): R|mest| {
|
||||||
super<R|kotlin/Any|>()
|
super<R|kotlin/Any|>()
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ class L {
|
|||||||
fun B.foo() {}
|
fun B.foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mest()
|
fun mest() {}
|
||||||
|
|
||||||
class mest
|
class mest
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ interface B
|
|||||||
class Clazz1 : A, B
|
class Clazz1 : A, B
|
||||||
class Clazz2 : A, B
|
class Clazz2 : A, B
|
||||||
|
|
||||||
fun <K> select(x: K, y: K): K
|
<!NON_MEMBER_FUNCTION_NO_BODY!>fun <K> select(x: K, y: K): K<!>
|
||||||
|
|
||||||
fun test() = select(Clazz1(), Clazz2())
|
fun test() = select(Clazz1(), Clazz2())
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ package a.d
|
|||||||
|
|
||||||
import b.d.*
|
import b.d.*
|
||||||
|
|
||||||
fun foo(arg: Other): Another
|
<!NON_MEMBER_FUNCTION_NO_BODY!>fun foo(arg: Other): Another<!>
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
baz()
|
baz()
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.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.*
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
|
// See old FE's [DeclarationsChecker]
|
||||||
|
object FirTopLevelFunctionChecker : FirFileChecker() {
|
||||||
|
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
for (topLevelDeclaration in declaration.declarations) {
|
||||||
|
if (topLevelDeclaration is FirSimpleFunction) {
|
||||||
|
checkFunction(topLevelDeclaration, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkFunction(function: FirSimpleFunction, reporter: DiagnosticReporter) {
|
||||||
|
val source = function.source ?: return
|
||||||
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
|
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
||||||
|
// So, our source of truth should be the full modifier list retrieved from the source.
|
||||||
|
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||||
|
val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true
|
||||||
|
val isExternal = function.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true
|
||||||
|
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
||||||
|
if (!function.hasBody && !hasAbstractModifier && !isExternal && !isExpect) {
|
||||||
|
reporter.report(FirErrors.NON_MEMBER_FUNCTION_NO_BODY.on(source, function))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -80,6 +80,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||||
@@ -359,6 +360,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
map.put(ABSTRACT_FUNCTION_WITH_BODY, "A function ''{0}'' with body cannot be abstract", DECLARATION_NAME)
|
map.put(ABSTRACT_FUNCTION_WITH_BODY, "A function ''{0}'' with body cannot be abstract", DECLARATION_NAME)
|
||||||
map.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without a body must be abstract", DECLARATION_NAME)
|
map.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without a body must be abstract", DECLARATION_NAME)
|
||||||
map.put(PRIVATE_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be private", DECLARATION_NAME)
|
map.put(PRIVATE_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be private", DECLARATION_NAME)
|
||||||
|
map.put(NON_MEMBER_FUNCTION_NO_BODY, "Function ''{0}'' must have a body", DECLARATION_NAME)
|
||||||
|
|
||||||
map.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name")
|
map.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name")
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ object FirErrors {
|
|||||||
val ABSTRACT_FUNCTION_WITH_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
|
val ABSTRACT_FUNCTION_WITH_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
|
||||||
val NON_ABSTRACT_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val NON_ABSTRACT_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
val PRIVATE_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
val PRIVATE_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
|
val NON_MEMBER_FUNCTION_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
val FUNCTION_DECLARATION_WITH_NO_NAME by error0<FirSourceElement, KtFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val FUNCTION_DECLARATION_WITH_NO_NAME by error0<FirSourceElement, KtFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
|
|||||||
+4
@@ -59,6 +59,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirConstructorAllowedChecker,
|
FirConstructorAllowedChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val fileCheckers: Set<FirFileChecker> = setOf(
|
||||||
|
FirTopLevelFunctionChecker,
|
||||||
|
)
|
||||||
|
|
||||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
|
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
|
||||||
FirCallsEffectAnalyzer,
|
FirCallsEffectAnalyzer,
|
||||||
FirReturnsImpliesAnalyzer,
|
FirReturnsImpliesAnalyzer,
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ package MyPackage
|
|||||||
abstract val e3: Int = 0; get() = a
|
abstract val e3: Int = 0; get() = a
|
||||||
|
|
||||||
//methods
|
//methods
|
||||||
fun f()
|
<!NON_MEMBER_FUNCTION_NO_BODY!>fun f()<!>
|
||||||
fun g() {}
|
fun g() {}
|
||||||
abstract fun h()
|
abstract fun h()
|
||||||
abstract fun j() {}
|
abstract fun j() {}
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ abstract class Abst {
|
|||||||
abstract fun foo(x: Int = <!UNRESOLVED_REFERENCE!>y<!>, y: Int = x)
|
abstract fun foo(x: Int = <!UNRESOLVED_REFERENCE!>y<!>, y: Int = x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extraDiagnostics(x: Int = <!UNRESOLVED_REFERENCE!>y<!>, y: Int)
|
<!NON_MEMBER_FUNCTION_NO_BODY!>fun extraDiagnostics(x: Int = <!UNRESOLVED_REFERENCE!>y<!>, y: Int)<!>
|
||||||
|
|||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
fun bar()
|
|
||||||
+1
@@ -1 +1,2 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
<!NON_MEMBER_FUNCTION_NO_BODY!>fun bar()<!>
|
<!NON_MEMBER_FUNCTION_NO_BODY!>fun bar()<!>
|
||||||
|
|||||||
Vendored
+2
-2
@@ -7,6 +7,6 @@ expect fun foo()
|
|||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|
||||||
actual fun foo()
|
<!NON_MEMBER_FUNCTION_NO_BODY!>actual fun foo()<!>
|
||||||
|
|
||||||
actual fun bar()
|
<!NON_MEMBER_FUNCTION_NO_BODY!>actual fun bar()<!>
|
||||||
|
|||||||
Reference in New Issue
Block a user