Add diagnostic on calling inner classes constructors without receiver
Otherwise there will be just an unresolved reference that doesn't give any useful information #KT-8959 Fixed
This commit is contained in:
+6
-1
@@ -31,6 +31,7 @@ enum class WrongResolutionToClassifier(val message: (Name) -> String) {
|
||||
INTERFACE_AS_VALUE({ "Interface $it does not have companion object" }),
|
||||
INTERFACE_AS_FUNCTION({ "Interface $it does not have constructors" }),
|
||||
CLASS_AS_VALUE({ "Class $it does not have companion object" }),
|
||||
INNER_CLASS_CONSTRUCTOR_NO_RECEIVER({ "Constructor of inner class $it can be called only with receiver of containing class" }),
|
||||
OBJECT_AS_FUNCTION({ "Function 'invoke()' is not found in object $it" })
|
||||
}
|
||||
|
||||
@@ -92,7 +93,11 @@ private fun ErrorCandidateContext.asClassifierCall(asFunction: Boolean) {
|
||||
when (classifier.kind) {
|
||||
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
|
||||
ClassKind.OBJECT -> if (asFunction) OBJECT_AS_FUNCTION else return
|
||||
ClassKind.CLASS -> if (asFunction) return else CLASS_AS_VALUE
|
||||
ClassKind.CLASS -> when {
|
||||
asFunction && explicitReceiver is QualifierReceiver? && classifier.isInner -> INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
|
||||
!asFunction -> CLASS_AS_VALUE
|
||||
else -> return
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -41,8 +41,8 @@ fun f() {
|
||||
C.O
|
||||
C.O.InO
|
||||
C.A()
|
||||
C.<!UNRESOLVED_REFERENCE!>B<!>()
|
||||
C.<!RESOLUTION_TO_CLASSIFIER!>B<!>()
|
||||
|
||||
C.E3.<!UNRESOLVED_REFERENCE!>O_O<!>
|
||||
C.E3.<!UNRESOLVED_REFERENCE!>G<!>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
class Outer1 {
|
||||
class Nested
|
||||
|
||||
|
||||
class C1 { val b = Nested() }
|
||||
class C2(val b: Any = Nested())
|
||||
inner class C3 { val b = Nested() }
|
||||
inner class C4(val b: Any = Nested())
|
||||
|
||||
|
||||
inner class Inner
|
||||
|
||||
class C5 { val b = <!UNRESOLVED_REFERENCE!>Inner<!>() }
|
||||
class C6(val b: Any = <!UNRESOLVED_REFERENCE!>Inner<!>())
|
||||
|
||||
class C5 { val b = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>() }
|
||||
class C6(val b: Any = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>())
|
||||
inner class C7 { val b = Inner() }
|
||||
inner class C8(val b: Any = Inner())
|
||||
}
|
||||
@@ -18,15 +18,15 @@ class Outer1 {
|
||||
class Outer2 {
|
||||
class Nested {
|
||||
fun foo() = Outer2()
|
||||
fun bar() = <!UNRESOLVED_REFERENCE!>Inner<!>()
|
||||
fun bar() = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
}
|
||||
inner class Inner {
|
||||
fun foo() = Outer2()
|
||||
fun bar() = Nested()
|
||||
}
|
||||
|
||||
|
||||
fun foo() {
|
||||
Nested()
|
||||
Inner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
// FILE: Outer.kt
|
||||
package abc
|
||||
class Outer {
|
||||
inner class Inner() {
|
||||
constructor(x: Int) : this() {}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun baz() {
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
|
||||
}
|
||||
|
||||
// FILE: imported.kt
|
||||
import abc.Outer
|
||||
import abc.Outer.Inner
|
||||
|
||||
fun bar() {
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
|
||||
|
||||
with(Outer()) {
|
||||
Inner()
|
||||
Inner(1)
|
||||
}
|
||||
}
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
// FILE: Outer.kt
|
||||
package abc
|
||||
class Outer {
|
||||
inner class Inner() {
|
||||
constructor(x: Int) : this() {}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Inner(x: String) {}
|
||||
|
||||
fun baz() {
|
||||
// Diagnostic here could be better (why can't I call the constructor above?)
|
||||
Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
Inner("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
Outer.Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
Outer.Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
Outer.Inner("")
|
||||
}
|
||||
|
||||
// FILE: imported.kt
|
||||
import abc.Outer
|
||||
import abc.Outer.Inner
|
||||
import abc.Outer.Companion.Inner
|
||||
|
||||
fun bar() {
|
||||
Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
Inner("")
|
||||
|
||||
with(Outer()) {
|
||||
Inner()
|
||||
Inner(1)
|
||||
Inner("")
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class Test {
|
||||
}
|
||||
|
||||
fun more(): InnerClass {
|
||||
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
|
||||
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
|
||||
|
||||
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
@@ -23,4 +23,4 @@ class Test {
|
||||
fun foo() {}
|
||||
|
||||
open inner class InnerClass
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class Test {
|
||||
}
|
||||
|
||||
fun more(): InnerClass {
|
||||
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
|
||||
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
|
||||
|
||||
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
@@ -24,4 +24,4 @@ class Test {
|
||||
}
|
||||
|
||||
open inner class InnerClass
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@ class Outer {
|
||||
class Nested {
|
||||
class NestedNested
|
||||
}
|
||||
|
||||
|
||||
inner class Inner {
|
||||
inner class InnerInner
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class Outer {
|
||||
fun f1() = Outer()
|
||||
fun f2() = Outer.Nested()
|
||||
fun f3() = Outer.Nested.NestedNested()
|
||||
fun f4() = Outer.<!UNRESOLVED_REFERENCE!>Inner<!>()
|
||||
fun f5() = Outer.Inner.<!UNRESOLVED_REFERENCE!>InnerInner<!>()
|
||||
fun f4() = Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
fun f5() = Outer.Inner.<!RESOLUTION_TO_CLASSIFIER!>InnerInner<!>()
|
||||
fun f6() = Outer().Inner()
|
||||
fun f7() = Outer().Inner().InnerInner()
|
||||
fun f7() = Outer().Inner().InnerInner()
|
||||
|
||||
@@ -12,5 +12,5 @@ class C {
|
||||
|
||||
fun f() {
|
||||
<!RESOLUTION_TO_CLASSIFIER!>TestInterface<!>()
|
||||
C.<!UNRESOLVED_REFERENCE!>I<!>()
|
||||
}
|
||||
C.<!RESOLUTION_TO_CLASSIFIER!>I<!>()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ class A(
|
||||
n: Nested = foo(),
|
||||
n2: Nested = Nested(),
|
||||
inn: Inner = null!!,
|
||||
inn2: Inner = <!UNRESOLVED_REFERENCE!>Inner<!>(),
|
||||
inn2: Inner = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||
i: Interface = null!!,
|
||||
c: Int = CONST,
|
||||
cc: Int = Companion.CONST,
|
||||
|
||||
@@ -17,7 +17,7 @@ open class S(
|
||||
class A : I by S(
|
||||
foo(),
|
||||
Nested(),
|
||||
<!UNRESOLVED_REFERENCE!>Inner<!>(),
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||
CONST,
|
||||
Companion.CONST,
|
||||
Nested.CONST,
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ open class S(
|
||||
class A : S (
|
||||
foo(),
|
||||
Nested(),
|
||||
<!UNRESOLVED_REFERENCE!>Inner<!>(),
|
||||
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||
CONST,
|
||||
Companion.CONST,
|
||||
Nested.CONST,
|
||||
|
||||
@@ -33,10 +33,10 @@ class E: A() {
|
||||
|
||||
object Z {
|
||||
init {
|
||||
<!UNRESOLVED_REFERENCE!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!>()
|
||||
<!UNRESOLVED_REFERENCE!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>bar<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>bar<!>()
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>D<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>D<!>()
|
||||
C()
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class F: A() {
|
||||
companion object {
|
||||
init {
|
||||
B().fas()
|
||||
<!UNRESOLVED_REFERENCE!>D<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>f<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>D<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>f<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class Y: B() {
|
||||
|
||||
init {
|
||||
B_()
|
||||
B.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||
Y.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
|
||||
B_S()
|
||||
@@ -59,7 +59,7 @@ class Y: B() {
|
||||
val b_s: B_S = null!!
|
||||
|
||||
init {
|
||||
<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||
B_S()
|
||||
}
|
||||
}
|
||||
@@ -83,8 +83,8 @@ class Z: C() {
|
||||
|
||||
init {
|
||||
<!UNRESOLVED_REFERENCE!>A_S<!>()
|
||||
<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||
B_S()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ public class F extends D {
|
||||
class X: D() {
|
||||
init {
|
||||
B_()
|
||||
B.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||
C.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
D.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
X.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||
@@ -79,4 +79,4 @@ class Y: F() {
|
||||
F.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
||||
Y.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@ class Outer {
|
||||
typealias Test5 = Outer.Inner
|
||||
|
||||
val test5 = <!UNRESOLVED_REFERENCE!>Test5<!>()
|
||||
val test5a = Outer.<!UNRESOLVED_REFERENCE!>Inner<!>()
|
||||
val test5a = Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||
val test5b = Outer.<!UNRESOLVED_REFERENCE!>TestInner<!>()
|
||||
val test5c = Outer().<!UNRESOLVED_REFERENCE!>TestInner<!>()
|
||||
val test5d = Outer().Inner()
|
||||
val test5e = Outer().Test5()
|
||||
val test5e = Outer().Test5()
|
||||
|
||||
@@ -11347,6 +11347,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerConstructorsFromQualifiers.kt")
|
||||
public void testInnerConstructorsFromQualifiers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerConstructorsFromQualifiers.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerConstructorsFromQualifiersWithIrrelevantCandidate.kt")
|
||||
public void testInnerConstructorsFromQualifiersWithIrrelevantCandidate() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerConstructorsFromQualifiersWithIrrelevantCandidate.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerErrorForClassObjects.kt")
|
||||
public void testInnerErrorForClassObjects() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.kt");
|
||||
|
||||
Reference in New Issue
Block a user