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_VALUE({ "Interface $it does not have companion object" }),
|
||||||
INTERFACE_AS_FUNCTION({ "Interface $it does not have constructors" }),
|
INTERFACE_AS_FUNCTION({ "Interface $it does not have constructors" }),
|
||||||
CLASS_AS_VALUE({ "Class $it does not have companion object" }),
|
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" })
|
OBJECT_AS_FUNCTION({ "Function 'invoke()' is not found in object $it" })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,11 @@ private fun ErrorCandidateContext.asClassifierCall(asFunction: Boolean) {
|
|||||||
when (classifier.kind) {
|
when (classifier.kind) {
|
||||||
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
|
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
|
||||||
ClassKind.OBJECT -> if (asFunction) OBJECT_AS_FUNCTION else return
|
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
|
else -> return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -41,8 +41,8 @@ fun f() {
|
|||||||
C.O
|
C.O
|
||||||
C.O.InO
|
C.O.InO
|
||||||
C.A()
|
C.A()
|
||||||
C.<!UNRESOLVED_REFERENCE!>B<!>()
|
C.<!RESOLUTION_TO_CLASSIFIER!>B<!>()
|
||||||
|
|
||||||
C.E3.<!UNRESOLVED_REFERENCE!>O_O<!>
|
C.E3.<!UNRESOLVED_REFERENCE!>O_O<!>
|
||||||
C.E3.<!UNRESOLVED_REFERENCE!>G<!>()
|
C.E3.<!UNRESOLVED_REFERENCE!>G<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
class Outer1 {
|
class Outer1 {
|
||||||
class Nested
|
class Nested
|
||||||
|
|
||||||
class C1 { val b = Nested() }
|
class C1 { val b = Nested() }
|
||||||
class C2(val b: Any = Nested())
|
class C2(val b: Any = Nested())
|
||||||
inner class C3 { val b = Nested() }
|
inner class C3 { val b = Nested() }
|
||||||
inner class C4(val b: Any = Nested())
|
inner class C4(val b: Any = Nested())
|
||||||
|
|
||||||
inner class Inner
|
inner class Inner
|
||||||
|
|
||||||
class C5 { val b = <!UNRESOLVED_REFERENCE!>Inner<!>() }
|
class C5 { val b = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>() }
|
||||||
class C6(val b: Any = <!UNRESOLVED_REFERENCE!>Inner<!>())
|
class C6(val b: Any = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>())
|
||||||
inner class C7 { val b = Inner() }
|
inner class C7 { val b = Inner() }
|
||||||
inner class C8(val b: Any = Inner())
|
inner class C8(val b: Any = Inner())
|
||||||
}
|
}
|
||||||
@@ -18,15 +18,15 @@ class Outer1 {
|
|||||||
class Outer2 {
|
class Outer2 {
|
||||||
class Nested {
|
class Nested {
|
||||||
fun foo() = Outer2()
|
fun foo() = Outer2()
|
||||||
fun bar() = <!UNRESOLVED_REFERENCE!>Inner<!>()
|
fun bar() = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||||
}
|
}
|
||||||
inner class Inner {
|
inner class Inner {
|
||||||
fun foo() = Outer2()
|
fun foo() = Outer2()
|
||||||
fun bar() = Nested()
|
fun bar() = Nested()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
Nested()
|
Nested()
|
||||||
Inner()
|
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 {
|
fun more(): InnerClass {
|
||||||
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
|
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
|
||||||
|
|
||||||
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
@@ -23,4 +23,4 @@ class Test {
|
|||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|
||||||
open inner class InnerClass
|
open inner class InnerClass
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun more(): InnerClass {
|
fun more(): InnerClass {
|
||||||
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
|
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
|
||||||
|
|
||||||
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
@@ -24,4 +24,4 @@ class Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open inner class InnerClass
|
open inner class InnerClass
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -2,7 +2,7 @@ class Outer {
|
|||||||
class Nested {
|
class Nested {
|
||||||
class NestedNested
|
class NestedNested
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Inner {
|
inner class Inner {
|
||||||
inner class InnerInner
|
inner class InnerInner
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ class Outer {
|
|||||||
fun f1() = Outer()
|
fun f1() = Outer()
|
||||||
fun f2() = Outer.Nested()
|
fun f2() = Outer.Nested()
|
||||||
fun f3() = Outer.Nested.NestedNested()
|
fun f3() = Outer.Nested.NestedNested()
|
||||||
fun f4() = Outer.<!UNRESOLVED_REFERENCE!>Inner<!>()
|
fun f4() = Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
|
||||||
fun f5() = Outer.Inner.<!UNRESOLVED_REFERENCE!>InnerInner<!>()
|
fun f5() = Outer.Inner.<!RESOLUTION_TO_CLASSIFIER!>InnerInner<!>()
|
||||||
fun f6() = Outer().Inner()
|
fun f6() = Outer().Inner()
|
||||||
fun f7() = Outer().Inner().InnerInner()
|
fun f7() = Outer().Inner().InnerInner()
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ class C {
|
|||||||
|
|
||||||
fun f() {
|
fun f() {
|
||||||
<!RESOLUTION_TO_CLASSIFIER!>TestInterface<!>()
|
<!RESOLUTION_TO_CLASSIFIER!>TestInterface<!>()
|
||||||
C.<!UNRESOLVED_REFERENCE!>I<!>()
|
C.<!RESOLUTION_TO_CLASSIFIER!>I<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class A(
|
|||||||
n: Nested = foo(),
|
n: Nested = foo(),
|
||||||
n2: Nested = Nested(),
|
n2: Nested = Nested(),
|
||||||
inn: Inner = null!!,
|
inn: Inner = null!!,
|
||||||
inn2: Inner = <!UNRESOLVED_REFERENCE!>Inner<!>(),
|
inn2: Inner = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||||
i: Interface = null!!,
|
i: Interface = null!!,
|
||||||
c: Int = CONST,
|
c: Int = CONST,
|
||||||
cc: Int = Companion.CONST,
|
cc: Int = Companion.CONST,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ open class S(
|
|||||||
class A : I by S(
|
class A : I by S(
|
||||||
foo(),
|
foo(),
|
||||||
Nested(),
|
Nested(),
|
||||||
<!UNRESOLVED_REFERENCE!>Inner<!>(),
|
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||||
CONST,
|
CONST,
|
||||||
Companion.CONST,
|
Companion.CONST,
|
||||||
Nested.CONST,
|
Nested.CONST,
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ open class S(
|
|||||||
class A : S (
|
class A : S (
|
||||||
foo(),
|
foo(),
|
||||||
Nested(),
|
Nested(),
|
||||||
<!UNRESOLVED_REFERENCE!>Inner<!>(),
|
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
|
||||||
CONST,
|
CONST,
|
||||||
Companion.CONST,
|
Companion.CONST,
|
||||||
Nested.CONST,
|
Nested.CONST,
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ class E: A() {
|
|||||||
|
|
||||||
object Z {
|
object Z {
|
||||||
init {
|
init {
|
||||||
<!UNRESOLVED_REFERENCE!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!>()
|
<!RESOLUTION_TO_CLASSIFIER!>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!>bar<!>()
|
||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>D<!>()
|
<!RESOLUTION_TO_CLASSIFIER!>D<!>()
|
||||||
C()
|
C()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ class F: A() {
|
|||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
B().fas()
|
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 {
|
init {
|
||||||
B_()
|
B_()
|
||||||
B.<!UNRESOLVED_REFERENCE!>B_<!>()
|
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||||
Y.<!UNRESOLVED_REFERENCE!>B_<!>()
|
Y.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||||
|
|
||||||
B_S()
|
B_S()
|
||||||
@@ -59,7 +59,7 @@ class Y: B() {
|
|||||||
val b_s: B_S = null!!
|
val b_s: B_S = null!!
|
||||||
|
|
||||||
init {
|
init {
|
||||||
<!UNRESOLVED_REFERENCE!>B_<!>()
|
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||||
B_S()
|
B_S()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,8 +83,8 @@ class Z: C() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
<!UNRESOLVED_REFERENCE!>A_S<!>()
|
<!UNRESOLVED_REFERENCE!>A_S<!>()
|
||||||
<!UNRESOLVED_REFERENCE!>B_<!>()
|
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||||
B_S()
|
B_S()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ public class F extends D {
|
|||||||
class X: D() {
|
class X: D() {
|
||||||
init {
|
init {
|
||||||
B_()
|
B_()
|
||||||
B.<!UNRESOLVED_REFERENCE!>B_<!>()
|
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
|
||||||
C.<!UNRESOLVED_REFERENCE!>B_<!>()
|
C.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||||
D.<!UNRESOLVED_REFERENCE!>B_<!>()
|
D.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||||
X.<!UNRESOLVED_REFERENCE!>B_<!>()
|
X.<!UNRESOLVED_REFERENCE!>B_<!>()
|
||||||
@@ -79,4 +79,4 @@ class Y: F() {
|
|||||||
F.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
F.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
||||||
Y.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
Y.<!UNRESOLVED_REFERENCE!>E_S<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -27,8 +27,8 @@ class Outer {
|
|||||||
typealias Test5 = Outer.Inner
|
typealias Test5 = Outer.Inner
|
||||||
|
|
||||||
val test5 = <!UNRESOLVED_REFERENCE!>Test5<!>()
|
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 test5b = Outer.<!UNRESOLVED_REFERENCE!>TestInner<!>()
|
||||||
val test5c = Outer().<!UNRESOLVED_REFERENCE!>TestInner<!>()
|
val test5c = Outer().<!UNRESOLVED_REFERENCE!>TestInner<!>()
|
||||||
val test5d = Outer().Inner()
|
val test5d = Outer().Inner()
|
||||||
val test5e = Outer().Test5()
|
val test5e = Outer().Test5()
|
||||||
|
|||||||
@@ -11347,6 +11347,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("innerErrorForClassObjects.kt")
|
||||||
public void testInnerErrorForClassObjects() throws Exception {
|
public void testInnerErrorForClassObjects() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user