Compare commits

...

6 Commits

46 changed files with 802 additions and 93 deletions

View File

@@ -1,5 +1,5 @@
annotation class A() {
<!ANNOTATION_CLASS_MEMBER!>constructor(s: Nothing?) {}<!>
<!ANNOTATION_CLASS_MEMBER!><!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: Nothing?)<!> {}<!>
<!ANNOTATION_CLASS_MEMBER!>init {}<!>
<!ANNOTATION_CLASS_MEMBER!>fun foo() {}<!>
<!ANNOTATION_CLASS_MEMBER!>val bar: Nothing?<!>

View File

@@ -5,7 +5,7 @@ FILE: annotationClassMember.kt
}
public constructor(s: R|kotlin/Nothing?|): R|A| {
this<R|A|>()
super<R|kotlin/Any|>()
}
init {

View File

@@ -0,0 +1,67 @@
class B
class C
class A() {
constructor(a: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("test") {}
constructor(a: String) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(10) {}
constructor(a: Boolean) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>('\n') {}
constructor(a: Char) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(0.0) {}
constructor(a: Double) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(false) {}
constructor(b: B) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(3.14159265) {}
constructor(c: C) : this() {}
constructor(a: List<Int>) : this(C()) {}
}
class D {
constructor(i: Boolean) {}
constructor(i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(3) {}
}
class E<T> {
// this is not an error about the
// selection of the proper constructor
// but a type mismatch for the first
// argument
constructor(e: T, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 10) {}
}
class I<T> {
// this is not an error about the
// selection of the proper constructor
// but a type mismatch for the first
// argument
constructor(e: T, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 10)
}
class J<T> {
constructor(e: T, i: Int) : this(i, 10)
constructor(e: Int, i: Int)
}
class F(s: String) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(i: Boolean)<!> {}
constructor(i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(3) {}
}
class G(x: Int) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor()<!> {}
}
class H(x: Int) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor()<!>
}
class K(x: Int) {
constructor() : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>() {}
}
class M {
constructor(m: Int)
}
class U : M {
<!INAPPLICABLE_CANDIDATE!>constructor()<!>
}

View File

@@ -0,0 +1,139 @@
FILE: cyclicConstructorDelegationCall.kt
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public constructor(a: R|kotlin/Int|): R|A| {
this<R|A|>(String(test))
}
public constructor(a: R|kotlin/String|): R|A| {
this<R|A|>(Int(10))
}
public constructor(a: R|kotlin/Boolean|): R|A| {
this<R|A|>(Char(10))
}
public constructor(a: R|kotlin/Char|): R|A| {
this<R|A|>(Double(0.0))
}
public constructor(a: R|kotlin/Double|): R|A| {
this<R|A|>(Boolean(false))
}
public constructor(b: R|B|): R|A| {
this<R|A|>(Double(3.14159265))
}
public constructor(c: R|C|): R|A| {
this<R|A|>()
}
public constructor(a: R|kotlin/collections/List<kotlin/Int>|): R|A| {
this<R|A|>(R|/C.C|())
}
}
public final class D : R|kotlin/Any| {
public constructor(i: R|kotlin/Boolean|): R|D| {
super<R|kotlin/Any|>()
}
public constructor(i: R|kotlin/Int|): R|D| {
this<R|D|>(Int(3))
}
}
public final class E<T> : R|kotlin/Any| {
public constructor<T>(e: R|T|, i: R|kotlin/Int|): R|E<T>| {
this<R|E<T>|>(R|<local>/i|, Int(10))
}
}
public final class I<T> : R|kotlin/Any| {
public constructor<T>(e: R|T|, i: R|kotlin/Int|): R|I<T>| {
this<R|I<T>|>(R|<local>/i|, Int(10))
}
}
public final class J<T> : R|kotlin/Any| {
public constructor<T>(e: R|T|, i: R|kotlin/Int|): R|J<T>| {
this<R|J<T>|>(R|<local>/i|, Int(10))
}
public constructor<T>(e: R|kotlin/Int|, i: R|kotlin/Int|): R|J<T>| {
super<R|kotlin/Any|>()
}
}
public final class F : R|kotlin/Any| {
public constructor(s: R|kotlin/String|): R|F| {
super<R|kotlin/Any|>()
}
public constructor(i: R|kotlin/Boolean|): R|F| {
super<R|kotlin/Any|>()
}
public constructor(i: R|kotlin/Int|): R|F| {
this<R|F|>(Int(3))
}
}
public final class G : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|G| {
super<R|kotlin/Any|>()
}
public constructor(): R|G| {
super<R|kotlin/Any|>()
}
}
public final class H : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|H| {
super<R|kotlin/Any|>()
}
public constructor(): R|H| {
super<R|kotlin/Any|>()
}
}
public final class K : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|K| {
super<R|kotlin/Any|>()
}
public constructor(): R|K| {
this<R|K|>()
}
}
public final class M : R|kotlin/Any| {
public constructor(m: R|kotlin/Int|): R|M| {
super<R|kotlin/Any|>()
}
}
public final class U : R|M| {
public constructor(): R|U| {
super<R|M|>()
}
}

View File

@@ -0,0 +1,6 @@
enum class A {
A(1), B(2), C("test");
constructor(x: Int) : <!DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR!>super<!>()
constructor(t: String) : this(10)
}

View File

@@ -0,0 +1,38 @@
FILE: delegationSuperCallInEnumConstructor.kt
public final enum class A : R|kotlin/Enum<A>| {
public final static enum entry A: R|A| = object : R|A| {
private constructor(): R|<anonymous>| {
super<R|A|>(Int(1))
}
}
public final static enum entry B: R|A| = object : R|A| {
private constructor(): R|<anonymous>| {
super<R|A|>(Int(2))
}
}
public final static enum entry C: R|A| = object : R|A| {
private constructor(): R|<anonymous>| {
super<R|A|>(String(test))
}
}
private constructor(x: R|kotlin/Int|): R|A| {
super<R|kotlin/Enum<A>|>()
}
private constructor(t: R|kotlin/String|): R|A| {
this<R|A|>(Int(10))
}
public final static fun values(): R|kotlin/Array<A>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|A| {
}
}

View File

@@ -0,0 +1,18 @@
class A(x: Int) {
constructor(z: String) : this(10)
}
class B : A {
<!EXPLICIT_DELEGATION_CALL_REQUIRED, NONE_APPLICABLE!>constructor()<!>
constructor(z: String) : this()
}
<!SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR!>class C : A(20) {
<!EXPLICIT_DELEGATION_CALL_REQUIRED, NONE_APPLICABLE!>constructor()<!>
constructor(z: String) : this()
}<!>
class D() : A(20) {
<!NONE_APPLICABLE, PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(x: Int)<!>
constructor(z: String) : this()
}

View File

@@ -0,0 +1,45 @@
FILE: explicitDelegationCallRequired.kt
public final class A : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|A| {
super<R|kotlin/Any|>()
}
public constructor(z: R|kotlin/String|): R|A| {
this<R|A|>(Int(10))
}
}
public final class B : R|A| {
public constructor(): R|B| {
super<R|A|>()
}
public constructor(z: R|kotlin/String|): R|B| {
this<R|B|>()
}
}
public final class C : R|A| {
public constructor(): R|C| {
super<R|A|>()
}
public constructor(z: R|kotlin/String|): R|C| {
this<R|C|>()
}
}
public final class D : R|A| {
public constructor(): R|D| {
super<R|A|>(Int(20))
}
public constructor(x: R|kotlin/Int|): R|D| {
super<R|A|>()
}
public constructor(z: R|kotlin/String|): R|D| {
this<R|D|>()
}
}

View File

@@ -0,0 +1,9 @@
data class A {}
<!PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS!>data class B {
constructor()
}<!>
<!PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS!>data class C {
constructor(x: Int)
}<!>

View File

@@ -0,0 +1,21 @@
FILE: primaryConstructorRequiredForDataClass.kt
public final data class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final fun copy(): R|A|
}
public final data class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public final data class C : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|C| {
super<R|kotlin/Any|>()
}
}

View File

@@ -0,0 +1,11 @@
class A
class B : A
class C(x: Int)
<!INAPPLICABLE_CANDIDATE!>class D : C<!>
class E : C(10)
class F() : C(10)
<!SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR!>class G : C(10) {
constructor() : super(1)
}<!>

View File

@@ -0,0 +1,43 @@
FILE: supertypeInitializedWithoutPrimaryConstructor.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public final class B : R|A| {
public constructor(): R|B| {
super<R|A|>()
}
}
public final class C : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|C| {
super<R|kotlin/Any|>()
}
}
public final class D : R|C| {
public constructor(): R|D| {
super<R|C|>()
}
}
public final class E : R|C| {
public constructor(): R|E| {
super<R|C|>(Int(10))
}
}
public final class F : R|C| {
public constructor(): R|F| {
super<R|C|>(Int(10))
}
}
public final class G : R|C| {
public constructor(): R|G| {
super<R|C|>(Int(1))
}
}

View File

@@ -916,6 +916,21 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.kt");
}
@TestMetadata("cyclicConstructorDelegationCall.kt")
public void testCyclicConstructorDelegationCall() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/cyclicConstructorDelegationCall.kt");
}
@TestMetadata("delegationSuperCallInEnumConstructor.kt")
public void testDelegationSuperCallInEnumConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationSuperCallInEnumConstructor.kt");
}
@TestMetadata("explicitDelegationCallRequired.kt")
public void testExplicitDelegationCallRequired() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt");
}
@TestMetadata("incompatibleModifiers.kt")
public void testIncompatibleModifiers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt");
@@ -946,6 +961,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
}
@TestMetadata("primaryConstructorRequiredForDataClass.kt")
public void testPrimaryConstructorRequiredForDataClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/primaryConstructorRequiredForDataClass.kt");
}
@TestMetadata("projectionsOnNonClassTypeArguments.kt")
public void testProjectionsOnNonClassTypeArguments() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt");
@@ -981,6 +1001,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superclassNotAccessibleFromInterface.kt");
}
@TestMetadata("supertypeInitializedWithoutPrimaryConstructor.kt")
public void testSupertypeInitializedWithoutPrimaryConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.kt");
}
@TestMetadata("typeArgumentsNotAllowed.kt")
public void testTypeArgumentsNotAllowed() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.kt");

View File

@@ -916,6 +916,21 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.kt");
}
@TestMetadata("cyclicConstructorDelegationCall.kt")
public void testCyclicConstructorDelegationCall() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/cyclicConstructorDelegationCall.kt");
}
@TestMetadata("delegationSuperCallInEnumConstructor.kt")
public void testDelegationSuperCallInEnumConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationSuperCallInEnumConstructor.kt");
}
@TestMetadata("explicitDelegationCallRequired.kt")
public void testExplicitDelegationCallRequired() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt");
}
@TestMetadata("incompatibleModifiers.kt")
public void testIncompatibleModifiers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt");
@@ -946,6 +961,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
}
@TestMetadata("primaryConstructorRequiredForDataClass.kt")
public void testPrimaryConstructorRequiredForDataClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/primaryConstructorRequiredForDataClass.kt");
}
@TestMetadata("projectionsOnNonClassTypeArguments.kt")
public void testProjectionsOnNonClassTypeArguments() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt");
@@ -981,6 +1001,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superclassNotAccessibleFromInterface.kt");
}
@TestMetadata("supertypeInitializedWithoutPrimaryConstructor.kt")
public void testSupertypeInitializedWithoutPrimaryConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.kt");
}
@TestMetadata("typeArgumentsNotAllowed.kt")
public void testTypeArgumentsNotAllowed() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.kt");

View File

@@ -20,6 +20,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(
FirInfixFunctionDeclarationChecker,
FirExposedVisibilityDeclarationChecker,
FirCommonConstructorDelegationIssuesChecker,
FirSupertypeInitializedWithoutPrimaryConstructor,
FirDelegationSuperCallInEnumConstructorChecker,
FirPrimaryConstructorRequiredForDataClassChecker,
)
override val constructorCheckers: List<FirConstructorChecker> = listOf(

View File

@@ -0,0 +1,114 @@
/*
* 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.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirCommonConstructorDelegationIssuesChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass) {
return
}
val cyclicConstructors = mutableSetOf<FirConstructor>()
var hasPrimaryConstructor = false
// secondary; non-cyclic;
// candidates for further analysis
val otherConstructors = mutableSetOf<FirConstructor>()
for (it in declaration.declarations) {
if (it is FirConstructor) {
if (!it.isPrimary) {
otherConstructors += it
it.findCycle(cyclicConstructors)?.let { visited ->
cyclicConstructors += visited
}
} else {
hasPrimaryConstructor = true
}
}
}
otherConstructors -= cyclicConstructors
if (hasPrimaryConstructor) {
for (it in otherConstructors) {
if (it.delegatedConstructor?.isThis != true) {
if (it.delegatedConstructor?.source != null) {
reporter.reportPrimaryConstructorDelegationCallExpected(it.delegatedConstructor?.source)
} else {
reporter.reportPrimaryConstructorDelegationCallExpected(it.source)
}
}
}
} else {
for (it in otherConstructors) {
val callee = it.delegatedConstructor?.calleeReference
// couldn't find proper super() constructor implicitly
if (
callee is FirErrorNamedReference && callee.diagnostic is ConeAmbiguityError &&
it.delegatedConstructor?.source?.kind is FirFakeSourceElementKind
) {
reporter.reportExplicitDelegationCallRequired(it.source)
}
}
}
cyclicConstructors.forEach {
reporter.reportCyclicConstructorDelegationCall(it.delegatedConstructor?.source)
}
}
private fun FirConstructor.findCycle(knownCyclicConstructors: Set<FirConstructor> = emptySet()): Set<FirConstructor>? {
val visitedConstructors = mutableSetOf(this)
var it = this
var delegated = this.getDelegated()
while (!it.isPrimary && delegated != null) {
if (delegated in visitedConstructors || delegated in knownCyclicConstructors) {
return visitedConstructors
}
it = delegated
delegated = delegated.getDelegated()
visitedConstructors.add(it)
}
return null
}
private fun FirConstructor.getDelegated(): FirConstructor? = delegatedConstructor
?.calleeReference.safeAs<FirResolvedNamedReference>()
?.resolvedSymbol
?.fir.safeAs()
private fun DiagnosticReporter.reportCyclicConstructorDelegationCall(source: FirSourceElement?) {
source?.let { report(FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL.on(it)) }
}
private fun DiagnosticReporter.reportPrimaryConstructorDelegationCallExpected(source: FirSourceElement?) {
source?.let { report(FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(it)) }
}
private fun DiagnosticReporter.reportExplicitDelegationCallRequired(source: FirSourceElement?) {
source?.let { report(FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED.on(it)) }
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
object FirDelegationSuperCallInEnumConstructorChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass || declaration.classKind != ClassKind.ENUM_CLASS) {
return
}
for (it in declaration.declarations) {
if (
it is FirConstructor && !it.isPrimary &&
it.delegatedConstructor?.isThis == false &&
it.delegatedConstructor?.source?.kind !is FirFakeSourceElementKind
) {
reporter.report(it.delegatedConstructor?.source)
}
}
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(it)) }
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.isData
object FirPrimaryConstructorRequiredForDataClassChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass || declaration.classKind != ClassKind.CLASS || !declaration.isData) {
return
}
val hasPrimaryConstructor = declaration.declarations.any { it is FirConstructor && it.isPrimary }
if (!hasPrimaryConstructor) {
reporter.report(declaration.source)
}
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) }
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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 com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.lightNode
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
object FirSupertypeInitializedWithoutPrimaryConstructor : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass || declaration.classKind == ClassKind.INTERFACE) {
return
}
val hasSupertypeWithConstructor = declaration.source?.anySupertypeHasConstructorParentheses() == true
val hasPrimaryConstructor = declaration.declarations.any { it is FirConstructor && it.isPrimary }
if (hasSupertypeWithConstructor && !hasPrimaryConstructor) {
reporter.report(declaration.source)
}
}
private fun FirSourceElement.anySupertypeHasConstructorParentheses(): Boolean {
val localPsi = psi
val localLightNode = lightNode
if (localPsi != null && localPsi !is PsiErrorElement) {
return localPsi.anySupertypeHasConstructorParentheses()
} else if (localLightNode != null && this is FirLightSourceElement) {
return localLightNode.anySupertypeHasConstructorParentheses(tree)
}
return false
}
private fun PsiElement.anySupertypeHasConstructorParentheses(): Boolean {
return children.isNotEmpty() && children[0] !is PsiErrorElement && children[0].children.any { it is KtSuperTypeCallEntry }
}
private fun LighterASTNode.anySupertypeHasConstructorParentheses(tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
val superTypes = getChildren(tree).find { it.tokenType == KtNodeTypes.SUPER_TYPE_LIST }
?: return false
return superTypes.getChildren(tree).any { it.tokenType == KtNodeTypes.SUPER_TYPE_CALL_ENTRY }
}
private fun LighterASTNode.getChildren(tree: FlyweightCapableTreeStructure<LighterASTNode>): List<LighterASTNode> {
val children = Ref<Array<LighterASTNode?>>()
val count = tree.getChildren(this, children)
return if (count > 0) children.get().filterNotNull() else emptyList()
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(it)) }
}
}

View File

@@ -64,6 +64,13 @@ object FirErrors {
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER)
val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>()
val CYCLIC_CONSTRUCTOR_DELEGATION_CALL by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED by warning0<FirSourceElement, PsiElement>()
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>()
val DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS by warning0<FirSourceElement, PsiElement>()
val EXPLICIT_DELEGATION_CALL_REQUIRED by warning0<FirSourceElement, PsiElement>()
// Exposed visibility group
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()

View File

@@ -465,7 +465,7 @@ class DeclarationsConverter(
)
//parse primary constructor
val primaryConstructorWrapper = convertPrimaryConstructor(
primaryConstructor, classNode, classWrapper, delegatedConstructorSource,
primaryConstructor, selfType.source, classWrapper, delegatedConstructorSource,
delegationSpecifiers?.primaryConstructorBody
)
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
@@ -572,7 +572,7 @@ class DeclarationsConverter(
superTypeCallEntry = superTypeCallEntry
)
//parse primary constructor
convertPrimaryConstructor(primaryConstructor, objectLiteral, classWrapper, delegatedConstructorSource, primaryConstructorBody)
convertPrimaryConstructor(primaryConstructor, typeRef.source, classWrapper, delegatedConstructorSource, primaryConstructorBody)
?.let { this.declarations += it.firConstructor }
//parse declarations
@@ -643,9 +643,7 @@ class DeclarationsConverter(
superTypeCallEntry = enumSuperTypeCallEntry
)
superTypeRefs += enumClassWrapper.delegatedSuperTypeRef
convertPrimaryConstructor(null, enumEntry, enumClassWrapper, null)?.let {
declarations += it.firConstructor
}
convertPrimaryConstructor(null, null, enumClassWrapper, null)?.let { declarations += it.firConstructor }
classBodyNode?.also { declarations += convertClassBody(it, enumClassWrapper) }
}
}
@@ -693,7 +691,7 @@ class DeclarationsConverter(
*/
private fun convertPrimaryConstructor(
primaryConstructor: LighterASTNode?,
classNode: LighterASTNode,
selfTypeSource: FirSourceElement?,
classWrapper: ClassWrapper,
delegatedConstructorSource: FirLightSourceElement?,
body: FirBlock? = null
@@ -712,7 +710,7 @@ class DeclarationsConverter(
val defaultVisibility = classWrapper.defaultConstructorVisibility()
val firDelegatedCall = buildDelegatedConstructorCall {
source = delegatedConstructorSource
source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = classWrapper.delegatedSuperTypeRef
isThis = false
extractArgumentsFrom(classWrapper.superTypeCallEntry, stubMode)
@@ -730,7 +728,7 @@ class DeclarationsConverter(
return PrimaryConstructor(
buildPrimaryConstructor {
source = primaryConstructor?.toFirSourceElement()
?: classNode.toFirSourceElement(FirFakeSourceElementKind.ImplicitConstructor)
?: selfTypeSource?.fakeElement(FirFakeSourceElementKind.ImplicitConstructor)
session = baseSession
origin = FirDeclarationOrigin.Source
returnTypeRef = classWrapper.delegatedSelfTypeRef
@@ -834,7 +832,7 @@ class DeclarationsConverter(
}
val isImplicit = constructorDelegationCall.asText.isEmpty()
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
val isThis = thisKeywordPresent //|| (isImplicit && classWrapper.hasPrimaryConstructor)
val delegatedType =
when {
isThis -> classWrapper.delegatedSelfTypeRef
@@ -842,7 +840,11 @@ class DeclarationsConverter(
}
return buildDelegatedConstructorCall {
source = constructorDelegationCall.toFirSourceElement()
source = if (isImplicit) {
constructorDelegationCall.toFirSourceElement().fakeElement(FirFakeSourceElementKind.ImplicitConstructor)
} else {
constructorDelegationCall.toFirSourceElement()
}
constructedTypeRef = delegatedType
this.isThis = isThis
extractArgumentsFrom(firValueArguments, stubMode)
@@ -1340,7 +1342,11 @@ class DeclarationsConverter(
val primaryConstructorBody: FirBlock?
)
private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode, containerSymbol: AbstractFirBasedSymbol<*>, delegatedTypeRef: FirTypeRef): DelegationSpecifiers {
private fun convertDelegationSpecifiers(
delegationSpecifiers: LighterASTNode,
containerSymbol: AbstractFirBasedSymbol<*>,
delegatedTypeRef: FirTypeRef
): DelegationSpecifiers {
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
@@ -1350,7 +1356,9 @@ class DeclarationsConverter(
var delegateNumber = 0
delegationSpecifiers.forEachChildren {
when (it.tokenType) {
SUPER_TYPE_ENTRY -> superTypeRefs += convertType(it)
SUPER_TYPE_ENTRY -> {
superTypeRefs += convertType(it)
}
SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply {
delegatedSuperTypeRef = first
superTypeRefs += first
@@ -1358,7 +1366,14 @@ class DeclarationsConverter(
delegateConstructorSource = it.toFirSourceElement(FirFakeSourceElementKind.DelegatingConstructorCall)
}
DELEGATED_SUPER_TYPE_ENTRY -> {
superTypeRefs += convertExplicitDelegation(it, delegateNumber, delegateFields, initializeDelegateStatements, containerSymbol, delegatedTypeRef)
superTypeRefs += convertExplicitDelegation(
it,
delegateNumber,
delegateFields,
initializeDelegateStatements,
containerSymbol,
delegatedTypeRef
)
delegateNumber++
}
}

View File

@@ -1095,8 +1095,12 @@ class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef,
hasPrimaryConstructor: Boolean,
): FirDelegatedConstructorCall {
val isThis = isCallToThis || (isImplicit && hasPrimaryConstructor)
val source = this.toFirSourceElement()
val isThis = isCallToThis //|| (isImplicit && hasPrimaryConstructor)
val source = if (isImplicit) {
this.toFirSourceElement(FirFakeSourceElementKind.ImplicitConstructor)
} else {
this.toFirSourceElement()
}
val delegatedType = when {
isThis -> delegatedSelfTypeRef
else -> delegatedSuperTypeRef

View File

@@ -7,7 +7,7 @@ class Foo {
bar = ""
}
constructor(a: Int) : this(a) {
constructor(a: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(a) {
bar = "a"
}
}

View File

@@ -7,12 +7,12 @@ class Foo {
bar = ""
}
constructor(a: Int) : this(a, 0, 0) {
constructor(a: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(a, 0, 0) {
}
constructor(a: Int, b: Int) : this(a) {
constructor(a: Int, b: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(a) {
}
constructor(a: Int, b: Int, c: Int) : this(a, b) {
constructor(a: Int, b: Int, c: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(a, b) {
}
}

View File

@@ -2,7 +2,7 @@
fun test(vararg x1: Int, vararg x2: Int) {
fun test2(vararg x1: Int, vararg x2: Int) {
class LocalClass(vararg x1: Int, vararg x2: Int) {
constructor(vararg x1: Int, vararg x2: Int, xx: Int) {}
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(vararg x1: Int, vararg x2: Int, xx: Int)<!> {}
}
fun test3(vararg x1: Int, vararg x2: Int) {}
}
@@ -20,7 +20,7 @@ abstract class C(vararg x1: Int, vararg x2: Int, b: Boolean) {
abstract fun test2(vararg x1: Int, vararg x2: Int)
class CC(vararg x1: Int, vararg x2: Int, b: Boolean) {
constructor(vararg x1: Int, vararg x2: Int) {}
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(vararg x1: Int, vararg x2: Int)<!> {}
fun test(vararg x1: Int, vararg x2: Int) {}
}
}
@@ -29,7 +29,7 @@ object O {
fun test(vararg x1: Int, vararg x2: Int) {}
class CC(vararg x1: Int, vararg x2: Int, b: Boolean) {
constructor(vararg x1: Int, vararg x2: Int) {}
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(vararg x1: Int, vararg x2: Int)<!> {}
fun test(vararg x1: Int, vararg x2: Int) {}
}
}

View File

@@ -7,7 +7,7 @@ expect enum class En(x: Int) {
E2(42),
;
<!NONE_APPLICABLE!>constructor(s: String)<!>
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: String)<!>
}
expect enum class En2 {

View File

@@ -8,7 +8,7 @@ expect open class A {
}
expect class B : A {
<!NONE_APPLICABLE!>constructor(i: Int)<!>
<!EXPLICIT_DELEGATION_CALL_REQUIRED, NONE_APPLICABLE!>constructor(i: Int)<!>
constructor() : super("B")
}

View File

@@ -9,7 +9,7 @@ expect class Foo(
"no"
}
constructor(s: String) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: String)<!> {
"no"
}

View File

@@ -4,7 +4,7 @@
// FILE: common.kt
expect class Foo(zzz: Int) {
<!NONE_APPLICABLE!>constructor(aaa: Boolean)<!>
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(aaa: Boolean)<!>
fun f1(xxx: String): String
}

View File

@@ -1,20 +0,0 @@
object A {
<!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
init {}
}
enum class B {
X() {
<!CONSTRUCTOR_IN_OBJECT, NONE_APPLICABLE!>constructor()<!>
}
}
class C {
companion object {
<!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
}
}
val anonObject = object {
<!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
object A {
<!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
init {}

View File

@@ -1,33 +1,33 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A1 {
constructor(): this()
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>()
}
class A2(x: Byte) {
constructor(x1: Int): this(x1, 1)
constructor(x1: Int, x2: Int): this(x1, x2, 2)
constructor(x1: Int, x2: Int, x3: Int): this(x1)
constructor(x1: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, 1)
constructor(x1: Int, x2: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, x2, 2)
constructor(x1: Int, x2: Int, x3: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1)
// delegating to previously declared cycle
constructor(x1: Double): this(1)
constructor(x1: Double): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(1)
// delegating to cycle declared after
constructor(x1: String): this(1L)
constructor(x1: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(1L)
constructor(x1: Long): this(x1, 1L)
constructor(x1: Long, x2: Long): this(x1, x2, 2L)
constructor(x1: Long, x2: Long, x3: Long): this(x1)
constructor(x1: Long): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, 1L)
constructor(x1: Long, x2: Long): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, x2, 2L)
constructor(x1: Long, x2: Long, x3: Long): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1)
// no cycle, just call to primary constuctor
constructor(x1: Double, x2: Double): this(x1, x2, 1.0)
constructor(x1: Double, x2: Double, x3: Double): this(x1, x2, x3, 1.0)
constructor(x1: Double, x2: Double, x3: Double, x4: Double): this(1.toByte())
constructor(): this("x", "y")
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("x", "y")
constructor(x1: String, x2: String): this(x1, x2, "")
constructor(x1: String, x2: String, x3: String): this(x1, x2)
constructor(x1: String, x2: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, x2, "")
constructor(x1: String, x2: String, x3: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x1, x2)
}
open class B(x: Byte)

View File

@@ -7,8 +7,8 @@ data class A2(val y: String, val z: Int) {
constructor(x: String): this(x, 0)
}
data class A3 {
<!PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS!>data class A3 {
constructor()
}
}<!>
data class A4 internal constructor()

View File

@@ -6,7 +6,7 @@ enum class A {
constructor(x: Int)
constructor(x: Int, y: Int): this(x+y)
constructor(x: Double): this(x.toInt(), 1)
constructor(x: String): super(x, 1)
constructor(x: String): <!DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR!>super<!>(x, 1)
}
enum class B(x: Int) {
@@ -14,7 +14,7 @@ enum class B(x: Int) {
constructor(x: Int, y: Int): this(x+y)
constructor(x: Double): this(x.toInt(), 1)
constructor(x: String): super(x, 1)
constructor(x: String): <!DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR, PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>super<!>(x, 1)
}
enum class C {

View File

@@ -26,7 +26,7 @@ open class B2 {
}
class A2 : B2 {
<!NONE_APPLICABLE!>constructor()<!>
<!EXPLICIT_DELEGATION_CALL_REQUIRED, NONE_APPLICABLE!>constructor()<!>
constructor(x: Int) : <!NONE_APPLICABLE!>super<!>()
}

View File

@@ -1,8 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A(x: Int) {
constructor()
}
open class B(x: Int)
class C(x: Int) : B(x) {
constructor(): super(1)
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A(x: Int) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor()<!>

View File

@@ -17,5 +17,5 @@ class A1<R> : B<R> {
}
class A2<R> {
constructor(t: R, i: Int) : this(i, 1)
constructor(t: R, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 1)
}

View File

@@ -3,13 +3,13 @@
open class B<R1, R2>(x: R1, y: R2)
class A0<T1, T2> {
constructor(x: T1, y: T2): this(x, y)
constructor(x: T1, y: T2): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, y)
constructor(x: T1, y: T2, z: T2): this(x, 1) // ok, delegates to constructor(x: T1, y: Int)
constructor(x: T1, y: T2, z: T2): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, 1) // ok, delegates to constructor(x: T1, y: Int)
constructor(x: T1, y: Int): this(x, "")
constructor(x: T1): this(x, 1)
constructor(x: T1, y: T2, z: String): this(y, x)
constructor(x: T1, y: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, "")
constructor(x: T1): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, 1)
constructor(x: T1, y: T2, z: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(y, x)
}
class A1<T1, T2> : B<T1, T2> {

View File

@@ -1,5 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
open class B(x: Int)
class A : B(1) {
<!SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR!>class A : B(1) {
constructor(): super(1)
}
}<!>

View File

@@ -2,6 +2,6 @@
open class A(p1: String)
class B() : A("") {
constructor(s: String) {
<!INAPPLICABLE_CANDIDATE, PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: String)<!> {
}
}

View File

@@ -1,3 +0,0 @@
class X<T>(val t: T) {
constructor(t: String): this(t)
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class X<T>(val t: T) {
constructor(t: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(t)
}

View File

@@ -1,4 +1,4 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class X<T> {
constructor(t: T, i: Int): this(i, 1)
constructor(t: T, i: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 1)
}

View File

@@ -1,9 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A(x: String = "", y: String = "") {
constructor(x: String, y: String): this(x, y)
constructor(): this("", "")
constructor(): this("", "")
constructor(x: String, y: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, y)
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("", "")
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("", "")
}
class B {
@@ -14,9 +14,9 @@ fun B(x: Int) {}
class Outer {
class A(x: String = "", y: String = "") {
constructor(x: String, y: String): this(x, y)
constructor(): this("", "")
constructor(): this("", "")
constructor(x: String, y: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, y)
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("", "")
constructor(): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>("", "")
}
class B {

View File

@@ -6,5 +6,5 @@ open class B(x: Double) {
interface C
class A : B, C {
constructor(): <!NONE_APPLICABLE!>super<!>(' ')
<!NONE_APPLICABLE!>constructor(x: Int)<!>
<!EXPLICIT_DELEGATION_CALL_REQUIRED, NONE_APPLICABLE!>constructor(x: Int)<!>
}