FIR: introduce FunInterfaceDeclarationChecker
This commit is contained in:
+5
@@ -179,6 +179,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/ft.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funInterfaceDeclaration.kt")
|
||||
public void testFunInterfaceDeclaration() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionTypeAlias.kt")
|
||||
public void testFunctionTypeAlias() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/functionTypeAlias.kt");
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
FILE: funInterfaceDeclaration.kt
|
||||
public abstract interface Test1 : R|kotlin/Any| {
|
||||
public abstract fun foo(): R|kotlin/Unit|
|
||||
|
||||
public abstract fun boo(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test2 : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface Test3 : R|kotlin/Any| {
|
||||
public abstract val a: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public abstract fun foo(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test4 : R|kotlin/Any| {
|
||||
public abstract fun <T> foo(a: R|T|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test5 : R|kotlin/Any| {
|
||||
public abstract fun foo(a: R|kotlin/Int| = Int(5)): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test6 : R|kotlin/Any| {
|
||||
public abstract suspend fun foo(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test7 : R|kotlin/Any| {
|
||||
public abstract fun foo(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test8 : R|Test7| {
|
||||
public abstract fun boo(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test9 : R|kotlin/Any| {
|
||||
public open fun num(m: R|kotlin/Int|): R|kotlin/Int| {
|
||||
^num R|<local>/m|.R|kotlin/Int.times|(R|<local>/m|)
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface Test10 : R|Test9| {
|
||||
public abstract fun test(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface Test11 : R|kotlin/Any| {
|
||||
public abstract val a: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
public abstract interface Test12 : R|Test11| {
|
||||
public abstract fun test(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Test1{
|
||||
fun foo()
|
||||
fun boo()
|
||||
}
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Test2 {}
|
||||
fun interface Test3 {
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>val<!> a: Int
|
||||
fun foo()
|
||||
}
|
||||
fun interface Test4{
|
||||
fun <<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS!>T<!>> foo(a: T)
|
||||
}
|
||||
fun interface Test5{
|
||||
fun foo(<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE!>a: Int = 5<!>)
|
||||
}
|
||||
fun interface Test6{
|
||||
suspend fun foo()
|
||||
}
|
||||
fun interface Test7{
|
||||
fun foo()
|
||||
}
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Test8: Test7{
|
||||
fun boo()
|
||||
}
|
||||
interface Test9 {
|
||||
fun num(m: Int): Int {
|
||||
return m * m
|
||||
}
|
||||
}
|
||||
fun interface Test10 : Test9 {
|
||||
fun test()
|
||||
}
|
||||
interface Test11 {
|
||||
val a: Int
|
||||
}
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>fun<!> interface Test12 : Test11 {
|
||||
fun test()
|
||||
}
|
||||
@@ -2,11 +2,11 @@ fun interface MyRunnable {
|
||||
fun foo(x: Int): Boolean
|
||||
}
|
||||
|
||||
fun interface WithProperty {
|
||||
val x: Int
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface WithProperty {
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>val<!> x: Int
|
||||
}
|
||||
|
||||
fun interface TwoAbstract : MyRunnable {
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface TwoAbstract : MyRunnable {
|
||||
fun bar()
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -206,6 +206,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/ft.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceDeclaration.kt")
|
||||
public void testFunInterfaceDeclaration() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeAlias.kt")
|
||||
public void testFunctionTypeAlias() throws Exception {
|
||||
|
||||
+6
@@ -206,6 +206,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/ft.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceDeclaration.kt")
|
||||
public void testFunInterfaceDeclaration() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeAlias.kt")
|
||||
public void testFunctionTypeAlias() throws Exception {
|
||||
|
||||
+3
@@ -64,6 +64,9 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
LONG_LITERAL_SUFFIX,
|
||||
REIFIED_MODIFIER,
|
||||
TYPE_PARAMETERS_LIST,
|
||||
FUN_MODIFIER,
|
||||
SUSPEND_MODIFIER,
|
||||
FUN_INTERFACE_ABSTRACT_PROPERTY,
|
||||
|
||||
;
|
||||
|
||||
|
||||
+5
-1
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
@@ -500,6 +499,11 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
|
||||
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
||||
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED)
|
||||
val FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS by error<KtClass>(PositioningStrategy.FUN_MODIFIER)
|
||||
val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error<KtDeclaration>(PositioningStrategy.FUN_INTERFACE_ABSTRACT_PROPERTY)
|
||||
val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error<PsiElement>()
|
||||
val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error<PsiElement>()
|
||||
val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error<KtFunction>(PositioningStrategy.SUSPEND_MODIFIER)
|
||||
}
|
||||
|
||||
val PROPERTIES_AND_ACCESSORS by object : DiagnosticGroup("Properties & accessors") {
|
||||
|
||||
@@ -310,6 +310,11 @@ object FirErrors {
|
||||
|
||||
// Fun interfaces
|
||||
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS by error0<KtClass>(SourceElementPositioningStrategies.FUN_MODIFIER)
|
||||
val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error0<KtDeclaration>(SourceElementPositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY)
|
||||
val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error0<PsiElement>()
|
||||
val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error0<PsiElement>()
|
||||
val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error0<KtFunction>(SourceElementPositioningStrategies.SUSPEND_MODIFIER)
|
||||
|
||||
// Properties & accessors
|
||||
val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error2<KtModifierListOwner, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.getProperties
|
||||
|
||||
object FirFunInterfaceDeclarationChecker : FirRegularClassChecker() {
|
||||
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.isInterface || !declaration.isFun) return
|
||||
|
||||
val scope = declaration.unsubstitutedScope(context)
|
||||
|
||||
var abstractFunction: FirSimpleFunction? = null
|
||||
|
||||
for (name in scope.getCallableNames()) {
|
||||
val functions = scope.getFunctions(name)
|
||||
val properties = scope.getProperties(name)
|
||||
|
||||
for (function in functions) {
|
||||
if (function.fir.isAbstract) {
|
||||
if (abstractFunction == null) {
|
||||
abstractFunction = function.fir
|
||||
} else {
|
||||
reporter.reportOn(declaration.source, FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (property in properties) {
|
||||
val firProperty = property.fir as? FirProperty ?: continue
|
||||
if (firProperty.isAbstract) {
|
||||
val source =
|
||||
if (firProperty.getContainingClass(context) != declaration)
|
||||
declaration.source
|
||||
else
|
||||
firProperty.source
|
||||
|
||||
reporter.reportOn(source, FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (abstractFunction == null) {
|
||||
reporter.reportOn(declaration.source, FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS, context)
|
||||
return
|
||||
}
|
||||
|
||||
when {
|
||||
abstractFunction.typeParameters.isNotEmpty() ->
|
||||
reporter.reportOn(
|
||||
abstractFunction.typeParameters.first().source,
|
||||
FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS,
|
||||
context
|
||||
)
|
||||
|
||||
abstractFunction.isSuspend ->
|
||||
if (!context.session.languageVersionSettings.supportsFeature(LanguageFeature.SuspendFunctionsInFunInterfaces)) {
|
||||
reporter.reportOn(abstractFunction.source, FUN_INTERFACE_WITH_SUSPEND_FUNCTION, context)
|
||||
}
|
||||
}
|
||||
|
||||
abstractFunction.valueParameters.forEach {
|
||||
if (it.defaultValue != null) {
|
||||
reporter.reportOn(it.source, FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -111,8 +111,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE_SUBCLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY
|
||||
@@ -698,6 +703,15 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
"An anonymous function is not allowed to specify default values for its parameters"
|
||||
)
|
||||
map.put(USELESS_VARARG_ON_PARAMETER, "Vararg on this parameter is useless")
|
||||
map.put(
|
||||
FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS,
|
||||
"Fun interface must have exactly one abstract function"
|
||||
)
|
||||
map.put(FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES, "Fun interface can not have abstract properties")
|
||||
map.put(FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS, "Fun interface can not have abstract metod with type parameters")
|
||||
map.put(FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE, "Fun interface abstract method can not have default value")
|
||||
map.put(FUN_INTERFACE_WITH_SUSPEND_FUNCTION, "Fun interface abstract method can not be suspend")
|
||||
|
||||
map.put(MULTIPLE_VARARG_PARAMETERS, "Multiple vararg-parameters are prohibited")
|
||||
map.put(FORBIDDEN_VARARG_PARAMETER_TYPE, "Forbidden vararg parameter type: {0}", RENDER_TYPE)
|
||||
map.put(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION, "A type annotation is required on a value parameter")
|
||||
|
||||
+22
@@ -340,6 +340,12 @@ object LightTreePositioningStrategies {
|
||||
val CONST_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.CONST_KEYWORD))
|
||||
|
||||
val FUN_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.FUN_KEYWORD))
|
||||
|
||||
val SUSPEND_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.SUSPEND_KEYWORD))
|
||||
|
||||
val INLINE_OR_VALUE_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.INLINE_KEYWORD, KtTokens.VALUE_KEYWORD))
|
||||
|
||||
@@ -443,6 +449,22 @@ object LightTreePositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
val FUN_INTERFACE_ABSTRACT_PROPERTY: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
return when (node.tokenType) {
|
||||
KtNodeTypes.CLASS -> FUN_MODIFIER.mark(node, startOffset, endOffset, tree)
|
||||
KtNodeTypes.PROPERTY -> VAL_OR_VAR_NODE.mark(node, startOffset, endOffset, tree)
|
||||
else -> DEFAULT.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val REFERENCE_BY_QUALIFIED: LightTreePositioningStrategy = FindReferencePositioningStrategy(false)
|
||||
val REFERENCED_NAME_BY_QUALIFIED: LightTreePositioningStrategy = FindReferencePositioningStrategy(true)
|
||||
|
||||
|
||||
+16
@@ -18,6 +18,11 @@ object SourceElementPositioningStrategies {
|
||||
PositioningStrategies.VAL_OR_VAR_NODE
|
||||
)
|
||||
|
||||
val FUN_INTERFACE_ABSTRACT_PROPERTY = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY,
|
||||
PositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY
|
||||
)
|
||||
|
||||
val COMPANION_OBJECT = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.COMPANION_OBJECT,
|
||||
PositioningStrategies.COMPANION_OBJECT
|
||||
@@ -103,6 +108,17 @@ object SourceElementPositioningStrategies {
|
||||
PositioningStrategies.INNER_MODIFIER
|
||||
)
|
||||
|
||||
val FUN_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.FUN_MODIFIER,
|
||||
PositioningStrategies.FUN_MODIFIER
|
||||
)
|
||||
|
||||
val SUSPEND_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.SUSPEND_MODIFIER,
|
||||
PositioningStrategies.SUSPEND_MODIFIER
|
||||
)
|
||||
|
||||
|
||||
val OPERATOR = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.OPERATOR,
|
||||
PositioningStrategies.OPERATOR
|
||||
|
||||
+6
-5
@@ -78,11 +78,12 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirDataClassPrimaryConstructorChecker,
|
||||
FirPrimaryConstructorSuperTypeChecker,
|
||||
FirTypeParametersInObjectChecker,
|
||||
FirMemberFunctionsChecker,
|
||||
FirMemberPropertiesChecker,
|
||||
FirNestedClassChecker,
|
||||
FirInlineClassDeclarationChecker,
|
||||
)
|
||||
FirFunInterfaceDeclarationChecker,
|
||||
FirMemberFunctionsChecker,
|
||||
FirMemberPropertiesChecker,
|
||||
FirNestedClassChecker,
|
||||
FirInlineClassDeclarationChecker,
|
||||
)
|
||||
|
||||
override val constructorCheckers: Set<FirConstructorChecker>
|
||||
get() = setOf(
|
||||
|
||||
@@ -370,6 +370,12 @@ object PositioningStrategies {
|
||||
@JvmField
|
||||
val CONST_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.CONST_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val FUN_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.FUN_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val SUSPEND_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.SUSPEND_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val FOR_REDECLARATION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||
override fun mark(element: PsiElement): List<TextRange> {
|
||||
@@ -777,6 +783,17 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val FUN_INTERFACE_ABSTRACT_PROPERTY: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
||||
override fun mark(element: KtDeclaration): List<TextRange> {
|
||||
return when (element) {
|
||||
is KtClass -> FUN_MODIFIER.mark(element)
|
||||
is KtProperty -> markElement(element.valOrVarKeyword)
|
||||
else -> error("Expect interface or property, but was " + element.getElementTextWithContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val REFERENCE_BY_QUALIFIED: PositioningStrategy<PsiElement> = FindReferencePositioningStrategy(false)
|
||||
val REFERENCED_NAME_BY_QUALIFIED: PositioningStrategy<PsiElement> = FindReferencePositioningStrategy(true)
|
||||
|
||||
|
||||
+13
-13
@@ -4,13 +4,13 @@ fun interface Good {
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface Foo1
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Foo1
|
||||
|
||||
fun interface Foo2 {
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Foo2 {
|
||||
|
||||
}
|
||||
|
||||
fun interface Foo3 {
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Foo3 {
|
||||
fun foo()
|
||||
fun bar()
|
||||
}
|
||||
@@ -19,7 +19,7 @@ interface BaseWithSAM {
|
||||
fun base()
|
||||
}
|
||||
|
||||
fun interface Foo4 : BaseWithSAM {
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Foo4 : BaseWithSAM {
|
||||
fun oneMore()
|
||||
}
|
||||
|
||||
@@ -37,17 +37,17 @@ fun interface Foo4WithBaseDefault : BaseWithDefault {
|
||||
|
||||
fun interface GoodWithBase : BaseWithSAM
|
||||
|
||||
fun interface Foo5 {
|
||||
val prop: Int
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface Foo5 {
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>val<!> prop: Int
|
||||
}
|
||||
|
||||
fun interface Foo6 {
|
||||
fun foo()
|
||||
val prop: Int
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>val<!> prop: Int
|
||||
}
|
||||
|
||||
fun interface Foo7 : BaseWithSAM {
|
||||
val prop: Int
|
||||
<!FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES!>val<!> prop: Int
|
||||
}
|
||||
|
||||
fun interface GoodWithPropAndBase : BaseWithSAM {
|
||||
@@ -55,7 +55,7 @@ fun interface GoodWithPropAndBase : BaseWithSAM {
|
||||
}
|
||||
|
||||
fun interface Foo8 {
|
||||
fun <T> invoke(x: T)
|
||||
fun <<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS!>T<!>> invoke(x: T)
|
||||
}
|
||||
|
||||
fun interface GoodGeneric<T> {
|
||||
@@ -63,7 +63,7 @@ fun interface GoodGeneric<T> {
|
||||
}
|
||||
|
||||
interface BaseWithGeneric {
|
||||
fun <T> invoke(x: T)
|
||||
fun <<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS!>T<!>> invoke(x: T)
|
||||
}
|
||||
|
||||
fun interface Foo9 : BaseWithGeneric
|
||||
@@ -75,7 +75,7 @@ fun interface GoodSuspend {
|
||||
}
|
||||
|
||||
class WithNestedFun<K> {
|
||||
fun interface NestedSimple
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface NestedSimple
|
||||
|
||||
fun interface GoodFun {
|
||||
fun invoke()
|
||||
@@ -93,11 +93,11 @@ fun <T> local() {
|
||||
}
|
||||
|
||||
fun interface WithDefaultValue {
|
||||
fun invoke(s: String = "")
|
||||
fun invoke(<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE!>s: String = ""<!>)
|
||||
}
|
||||
|
||||
interface BaseWithDefaultValue {
|
||||
fun invoke(s: String = "")
|
||||
fun invoke(<!FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE!>s: String = ""<!>)
|
||||
}
|
||||
|
||||
fun interface DeriveDefault : BaseWithDefaultValue
|
||||
|
||||
Vendored
+2
-2
@@ -1,4 +1,4 @@
|
||||
fun interface IsolatedFunFace {
|
||||
<!FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS!>fun<!> interface IsolatedFunFace {
|
||||
}
|
||||
|
||||
typealias FunAlias = IsolatedFunFace
|
||||
@@ -9,4 +9,4 @@ fun callIsolatedFunFace() {
|
||||
referIsolatedFunFace(<!UNRESOLVED_REFERENCE!>IsolatedFunFace<!> {})
|
||||
referIsolatedFunFace(<!UNRESOLVED_REFERENCE!>FunAlias<!> {})
|
||||
referIsolatedFunFace(<!ARGUMENT_TYPE_MISMATCH!>{}<!>)
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -1413,6 +1413,36 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS) { firDiagnostic ->
|
||||
FunInterfaceWrongCountOfAbstractMembersImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES) { firDiagnostic ->
|
||||
FunInterfaceCannotHaveAbstractPropertiesImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS) { firDiagnostic ->
|
||||
FunInterfaceAbstractMethodWithTypeParametersImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE) { firDiagnostic ->
|
||||
FunInterfaceAbstractMethodWithDefaultValueImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION) { firDiagnostic ->
|
||||
FunInterfaceWithSuspendFunctionImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS) { firDiagnostic ->
|
||||
AbstractPropertyInNonAbstractClassImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a as FirDeclaration),
|
||||
|
||||
+20
@@ -998,6 +998,26 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceWrongCountOfAbstractMembers : KtFirDiagnostic<KtClass>() {
|
||||
override val diagnosticClass get() = FunInterfaceWrongCountOfAbstractMembers::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceCannotHaveAbstractProperties : KtFirDiagnostic<KtDeclaration>() {
|
||||
override val diagnosticClass get() = FunInterfaceCannotHaveAbstractProperties::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceAbstractMethodWithTypeParameters : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = FunInterfaceAbstractMethodWithTypeParameters::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceAbstractMethodWithDefaultValue : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = FunInterfaceAbstractMethodWithDefaultValue::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceWithSuspendFunction : KtFirDiagnostic<KtFunction>() {
|
||||
override val diagnosticClass get() = FunInterfaceWithSuspendFunction::class
|
||||
}
|
||||
|
||||
abstract class AbstractPropertyInNonAbstractClass : KtFirDiagnostic<KtModifierListOwner>() {
|
||||
override val diagnosticClass get() = AbstractPropertyInNonAbstractClass::class
|
||||
abstract val property: KtSymbol
|
||||
|
||||
+35
@@ -1608,6 +1608,41 @@ internal class FunInterfaceConstructorReferenceImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceWrongCountOfAbstractMembersImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FunInterfaceWrongCountOfAbstractMembers(), KtAbstractFirDiagnostic<KtClass> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceCannotHaveAbstractPropertiesImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FunInterfaceCannotHaveAbstractProperties(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceAbstractMethodWithTypeParametersImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FunInterfaceAbstractMethodWithTypeParameters(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceAbstractMethodWithDefaultValueImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FunInterfaceAbstractMethodWithDefaultValue(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceWithSuspendFunctionImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FunInterfaceWithSuspendFunction(), KtAbstractFirDiagnostic<KtFunction> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AbstractPropertyInNonAbstractClassImpl(
|
||||
override val property: KtSymbol,
|
||||
override val containingClass: KtSymbol,
|
||||
|
||||
Reference in New Issue
Block a user