[FIR] allow primary constructors in interfaces to support invalid code
KTIJ-23504
This commit is contained in:
+6
@@ -718,6 +718,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("superTypeCallEntryResolveToCallInfo.kt")
|
||||||
|
public void testSuperTypeCallEntryResolveToCallInfo() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/superTypeCallEntryResolveToCallInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
||||||
public void testUnresolvableOperator_elvis_1() throws Exception {
|
public void testUnresolvableOperator_elvis_1() throws Exception {
|
||||||
|
|||||||
+6
@@ -718,6 +718,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("superTypeCallEntryResolveToCallInfo.kt")
|
||||||
|
public void testSuperTypeCallEntryResolveToCallInfo() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/superTypeCallEntryResolveToCallInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
||||||
public void testUnresolvableOperator_elvis_1() throws Exception {
|
public void testUnresolvableOperator_elvis_1() throws Exception {
|
||||||
|
|||||||
+6
@@ -718,6 +718,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/smartCastImplicitExtensionReceiver.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("superTypeCallEntryResolveToCallInfo.kt")
|
||||||
|
public void testSuperTypeCallEntryResolveToCallInfo() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/superTypeCallEntryResolveToCallInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
@TestMetadata("unresolvableOperator_elvis_1.kt")
|
||||||
public void testUnresolvableOperator_elvis_1() throws Exception {
|
public void testUnresolvableOperator_elvis_1() throws Exception {
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
interface SimpleClass() : <expr>java.lang.Object()</expr>, I {
|
||||||
|
fun foo() : String = "610" + toString()
|
||||||
|
|
||||||
|
override fun toString() : String { return foo() }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I {}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = java.lang.Object
|
||||||
|
symbol = <constructor>(): java.lang.Object
|
||||||
|
valueParameters = []
|
||||||
|
callableIdIfNonLocal = null
|
||||||
|
typeArgumentsMapping = {}
|
||||||
|
argumentMapping = {}
|
||||||
+14
@@ -1,7 +1,21 @@
|
|||||||
FILE: constructorInInterface.kt
|
FILE: constructorInInterface.kt
|
||||||
public abstract interface A : R|kotlin/Any| {
|
public abstract interface A : R|kotlin/Any| {
|
||||||
|
public constructor(s: R|kotlin/String|): R|A| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open val s: R|kotlin/String| = R|<local>/s|
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
|
||||||
}
|
}
|
||||||
public abstract interface B : R|kotlin/Any| {
|
public abstract interface B : R|kotlin/Any| {
|
||||||
|
public constructor(s: R|kotlin/String|): R|B| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open val s: R|kotlin/String| = R|<local>/s|
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
|
||||||
}
|
}
|
||||||
public abstract interface C : R|kotlin/Any| {
|
public abstract interface C : R|kotlin/Any| {
|
||||||
public constructor(s: R|kotlin/String|): R|C| {
|
public constructor(s: R|kotlin/String|): R|C| {
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>A(val s: String)<!>
|
interface A<!CONSTRUCTOR_IN_INTERFACE!>(val s: String)<!>
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>B constructor(val s: String)<!>
|
interface B <!CONSTRUCTOR_IN_INTERFACE!>constructor(val s: String)<!>
|
||||||
|
|
||||||
interface C {
|
interface C {
|
||||||
<!CONSTRUCTOR_IN_INTERFACE!>constructor(s: String)<!> {}
|
<!CONSTRUCTOR_IN_INTERFACE!>constructor(s: String)<!> {}
|
||||||
|
|||||||
+4
@@ -12,6 +12,10 @@ FILE: typeAliasWithTypeArguments.kt
|
|||||||
|
|
||||||
}
|
}
|
||||||
public abstract interface Inv<K, T> : R|kotlin/Any| {
|
public abstract interface Inv<K, T> : R|kotlin/Any| {
|
||||||
|
public constructor<K, T>(): R|Inv<K, T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
public abstract fun k(): R|K|
|
public abstract fun k(): R|K|
|
||||||
|
|
||||||
public abstract fun t(): R|T|
|
public abstract fun t(): R|T|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface C {
|
|||||||
fun baz()
|
fun baz()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>Inv<K, T>()<!> {
|
interface Inv<K, T><!CONSTRUCTOR_IN_INTERFACE!>()<!> {
|
||||||
fun k(): K
|
fun k(): K
|
||||||
fun t(): T
|
fun t(): T
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -98,7 +98,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirAnnotationClassDeclarationChecker,
|
FirAnnotationClassDeclarationChecker,
|
||||||
FirOptInAnnotationClassChecker,
|
FirOptInAnnotationClassChecker,
|
||||||
FirCommonConstructorDelegationIssuesChecker,
|
FirCommonConstructorDelegationIssuesChecker,
|
||||||
FirConstructorInInterfaceChecker,
|
|
||||||
FirDelegationSuperCallInEnumConstructorChecker,
|
FirDelegationSuperCallInEnumConstructorChecker,
|
||||||
FirDelegationInInterfaceSyntaxChecker,
|
FirDelegationInInterfaceSyntaxChecker,
|
||||||
FirEnumClassSimpleChecker,
|
FirEnumClassSimpleChecker,
|
||||||
|
|||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.analysis.checkers.context.CheckerContext
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|
||||||
import org.jetbrains.kotlin.diagnostics.hasPrimaryConstructor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
|
||||||
|
|
||||||
object FirConstructorInInterfaceChecker : FirRegularClassChecker() {
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
|
||||||
if (!declaration.isInterface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration.source?.hasPrimaryConstructor() == true) {
|
|
||||||
reporter.reportOn(declaration.source, FirErrors.CONSTRUCTOR_IN_INTERFACE, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -861,7 +861,7 @@ class DeclarationsConverter(
|
|||||||
if (primaryConstructor == null &&
|
if (primaryConstructor == null &&
|
||||||
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS && classKind != ClassKind.ENUM_ENTRY)
|
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS && classKind != ClassKind.ENUM_ENTRY)
|
||||||
) return null
|
) return null
|
||||||
if (classWrapper.isInterface()) return null
|
if (primaryConstructor == null && classWrapper.isInterface()) return null
|
||||||
|
|
||||||
var modifiers = Modifier()
|
var modifiers = Modifier()
|
||||||
val valueParameters = mutableListOf<ValueParameter>()
|
val valueParameters = mutableListOf<ValueParameter>()
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.*
|
import org.jetbrains.kotlin.*
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
|
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
@@ -873,10 +872,10 @@ open class RawFirBuilder(
|
|||||||
// TODO: in case we have no primary constructor,
|
// TODO: in case we have no primary constructor,
|
||||||
// it may be not possible to determine delegated super type right here
|
// it may be not possible to determine delegated super type right here
|
||||||
delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef
|
delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef
|
||||||
val shouldNotGenerateImplicitPrimaryConstructor = hasExplicitPrimaryConstructor() || hasSecondaryConstructors() ||
|
val shouldGenerateImplicitPrimaryConstructor =
|
||||||
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)
|
!hasExplicitPrimaryConstructor() && !hasSecondaryConstructors() && !(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)
|
||||||
|
|
||||||
if ((this !is KtClass || !this.isInterface()) && (primaryConstructor != null || !shouldNotGenerateImplicitPrimaryConstructor)) {
|
if (primaryConstructor != null || (this !is KtClass || !this.isInterface()) && shouldGenerateImplicitPrimaryConstructor) {
|
||||||
val firPrimaryConstructor = primaryConstructor.toFirConstructor(
|
val firPrimaryConstructor = primaryConstructor.toFirConstructor(
|
||||||
superTypeCallEntry,
|
superTypeCallEntry,
|
||||||
delegatedSuperTypeRef!!,
|
delegatedSuperTypeRef!!,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface T1 {}
|
|||||||
|
|
||||||
interface T2<T> {}
|
interface T2<T> {}
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>Test()<!> {
|
interface Test<!CONSTRUCTOR_IN_INTERFACE!>()<!> {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Test1 : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>C2<!>() {}
|
interface Test1 : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>C2<!>() {}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -MISSING_CONSTRUCTOR_KEYWORD
|
|
||||||
|
|
||||||
class C(val a: String) {}
|
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>T1(val x: String)<!> {}
|
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>T2 constructor()<!> {}
|
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>T3 private constructor(a: Int)<!> {}
|
|
||||||
|
|
||||||
interface T4 {
|
|
||||||
<!CONSTRUCTOR_IN_INTERFACE!>constructor(a: Int)<!> {
|
|
||||||
val b: Int = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>T5 private ()<!> : T4 {}
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>T6<!> private<!SYNTAX!><!> : T5 {}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -MISSING_CONSTRUCTOR_KEYWORD
|
// !DIAGNOSTICS: -MISSING_CONSTRUCTOR_KEYWORD
|
||||||
|
|
||||||
class C(val a: String) {}
|
class C(val a: String) {}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
open class bar()
|
open class bar()
|
||||||
|
|
||||||
interface <!CONSTRUCTOR_IN_INTERFACE!>Foo()<!> : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>bar<!>(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> {
|
interface Foo<!CONSTRUCTOR_IN_INTERFACE!>()<!> : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>bar<!>(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Foo2 : <!INTERFACE_WITH_SUPERCLASS!>bar<!>, Foo {
|
interface Foo2 : <!INTERFACE_WITH_SUPERCLASS!>bar<!>, Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Foo1() : bar(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, Foo, <!SUPERTYPE_APPEARS_TWICE, UNRESOLVED_REFERENCE!>Foo<!>() {}
|
open class Foo1() : bar(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, Foo, <!SUPERTYPE_APPEARS_TWICE!>Foo<!>() {}
|
||||||
open class Foo12 : bar(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> {}
|
open class Foo12 : bar(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> {}
|
||||||
|
|||||||
Reference in New Issue
Block a user