Skip to content

Commit a7fc32c

Browse files
committed
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
1 parent 1e0ae04 commit a7fc32c

File tree

17 files changed

+133
-37
lines changed

17 files changed

+133
-37
lines changed

compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ErrorCandidateFactory.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class WrongResolutionToClassifier(val message: (Name) -> String) {
3131
INTERFACE_AS_VALUE({ "Interface $it does not have companion object" }),
3232
INTERFACE_AS_FUNCTION({ "Interface $it does not have constructors" }),
3333
CLASS_AS_VALUE({ "Class $it does not have companion object" }),
34+
INNER_CLASS_CONSTRUCTOR_NO_RECEIVER({ "Constructor of inner class $it can be called only with receiver of containing class" }),
3435
OBJECT_AS_FUNCTION({ "Function 'invoke()' is not found in object $it" })
3536
}
3637

@@ -92,7 +93,11 @@ private fun ErrorCandidateContext.asClassifierCall(asFunction: Boolean) {
9293
when (classifier.kind) {
9394
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
9495
ClassKind.OBJECT -> if (asFunction) OBJECT_AS_FUNCTION else return
95-
ClassKind.CLASS -> if (asFunction) return else CLASS_AS_VALUE
96+
ClassKind.CLASS -> when {
97+
asFunction && explicitReceiver is QualifierReceiver? && classifier.isInner -> INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
98+
!asFunction -> CLASS_AS_VALUE
99+
else -> return
100+
}
96101
else -> return
97102
}
98103
}

compiler/testData/diagnostics/tests/classObjects/InnerClassAccessThroughEnum.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ fun f() {
4141
C.O
4242
C.O.InO
4343
C.A()
44-
C.<!UNRESOLVED_REFERENCE!>B<!>()
44+
C.<!RESOLUTION_TO_CLASSIFIER!>B<!>()
4545

4646
C.E3.<!UNRESOLVED_REFERENCE!>O_O<!>
4747
C.E3.<!UNRESOLVED_REFERENCE!>G<!>()
48-
}
48+
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
class Outer1 {
22
class Nested
3-
3+
44
class C1 { val b = Nested() }
55
class C2(val b: Any = Nested())
66
inner class C3 { val b = Nested() }
77
inner class C4(val b: Any = Nested())
8-
8+
99
inner class Inner
10-
11-
class C5 { val b = <!UNRESOLVED_REFERENCE!>Inner<!>() }
12-
class C6(val b: Any = <!UNRESOLVED_REFERENCE!>Inner<!>())
10+
11+
class C5 { val b = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>() }
12+
class C6(val b: Any = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>())
1313
inner class C7 { val b = Inner() }
1414
inner class C8(val b: Any = Inner())
1515
}
@@ -18,15 +18,15 @@ class Outer1 {
1818
class Outer2 {
1919
class Nested {
2020
fun foo() = Outer2()
21-
fun bar() = <!UNRESOLVED_REFERENCE!>Inner<!>()
21+
fun bar() = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
2222
}
2323
inner class Inner {
2424
fun foo() = Outer2()
2525
fun bar() = Nested()
2626
}
27-
27+
2828
fun foo() {
2929
Nested()
3030
Inner()
3131
}
32-
}
32+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// !DIAGNOSTICS: -UNUSED_PARAMETER
2+
// SKIP_TXT
3+
// FILE: Outer.kt
4+
package abc
5+
class Outer {
6+
inner class Inner() {
7+
constructor(x: Int) : this() {}
8+
}
9+
10+
companion object {
11+
12+
fun baz() {
13+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
14+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
15+
}
16+
}
17+
}
18+
19+
fun foo() {
20+
Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
21+
Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
22+
}
23+
24+
// FILE: imported.kt
25+
import abc.Outer
26+
import abc.Outer.Inner
27+
28+
fun bar() {
29+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
30+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(1)
31+
32+
with(Outer()) {
33+
Inner()
34+
Inner(1)
35+
}
36+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// !DIAGNOSTICS: -UNUSED_PARAMETER
2+
// SKIP_TXT
3+
// FILE: Outer.kt
4+
package abc
5+
class Outer {
6+
inner class Inner() {
7+
constructor(x: Int) : this() {}
8+
}
9+
10+
companion object {
11+
fun Inner(x: String) {}
12+
13+
fun baz() {
14+
// Diagnostic here could be better (why can't I call the constructor above?)
15+
Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
16+
Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
17+
Inner("")
18+
}
19+
}
20+
}
21+
22+
fun foo() {
23+
Outer.Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
24+
Outer.Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
25+
Outer.Inner("")
26+
}
27+
28+
// FILE: imported.kt
29+
import abc.Outer
30+
import abc.Outer.Inner
31+
import abc.Outer.Companion.Inner
32+
33+
fun bar() {
34+
Inner(<!NO_VALUE_FOR_PARAMETER!>)<!>
35+
Inner(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
36+
Inner("")
37+
38+
with(Outer()) {
39+
Inner()
40+
Inner(1)
41+
Inner("")
42+
}
43+
}

compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Test {
1010
}
1111

1212
fun more(): InnerClass {
13-
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
13+
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
1414

1515
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
1616
<!UNRESOLVED_REFERENCE!>foo<!>()
@@ -23,4 +23,4 @@ class Test {
2323
fun foo() {}
2424

2525
open inner class InnerClass
26-
}
26+
}

compiler/testData/diagnostics/tests/inner/innerErrorForObjects.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Test {
1010
}
1111

1212
fun more(): InnerClass {
13-
val b = <!UNRESOLVED_REFERENCE!>InnerClass<!>()
13+
val b = <!RESOLUTION_TO_CLASSIFIER!>InnerClass<!>()
1414

1515
val <!UNUSED_VARIABLE!>testVal<!> = <!UNRESOLVED_REFERENCE!>inClass<!>
1616
<!UNRESOLVED_REFERENCE!>foo<!>()
@@ -24,4 +24,4 @@ class Test {
2424
}
2525

2626
open inner class InnerClass
27-
}
27+
}

compiler/testData/diagnostics/tests/inner/qualifiedExpression/constructNestedClass.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class Outer {
22
class Nested {
33
class NestedNested
44
}
5-
5+
66
inner class Inner {
77
inner class InnerInner
88
}
@@ -11,7 +11,7 @@ class Outer {
1111
fun f1() = Outer()
1212
fun f2() = Outer.Nested()
1313
fun f3() = Outer.Nested.NestedNested()
14-
fun f4() = Outer.<!UNRESOLVED_REFERENCE!>Inner<!>()
15-
fun f5() = Outer.Inner.<!UNRESOLVED_REFERENCE!>InnerInner<!>()
14+
fun f4() = Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
15+
fun f5() = Outer.Inner.<!RESOLUTION_TO_CLASSIFIER!>InnerInner<!>()
1616
fun f6() = Outer().Inner()
17-
fun f7() = Outer().Inner().InnerInner()
17+
fun f7() = Outer().Inner().InnerInner()

compiler/testData/diagnostics/tests/regressions/kt4827.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ class C {
1212

1313
fun f() {
1414
<!RESOLUTION_TO_CLASSIFIER!>TestInterface<!>()
15-
C.<!UNRESOLVED_REFERENCE!>I<!>()
16-
}
15+
C.<!RESOLUTION_TO_CLASSIFIER!>I<!>()
16+
}

compiler/testData/diagnostics/tests/scopes/classHeader/constructors.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class A(
44
n: Nested = foo(),
55
n2: Nested = Nested(),
66
inn: Inner = null!!,
7-
inn2: Inner = <!UNRESOLVED_REFERENCE!>Inner<!>(),
7+
inn2: Inner = <!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
88
i: Interface = null!!,
99
c: Int = CONST,
1010
cc: Int = Companion.CONST,

compiler/testData/diagnostics/tests/scopes/classHeader/delegation.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ open class S(
1717
class A : I by S(
1818
foo(),
1919
Nested(),
20-
<!UNRESOLVED_REFERENCE!>Inner<!>(),
20+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
2121
CONST,
2222
Companion.CONST,
2323
Nested.CONST,

compiler/testData/diagnostics/tests/scopes/classHeader/superConstructorArguments.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open class S(
1515
class A : S (
1616
foo(),
1717
Nested(),
18-
<!UNRESOLVED_REFERENCE!>Inner<!>(),
18+
<!RESOLUTION_TO_CLASSIFIER!>Inner<!>(),
1919
CONST,
2020
Companion.CONST,
2121
Nested.CONST,

compiler/testData/diagnostics/tests/scopes/inheritance/innerClasses.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ class E: A() {
3333

3434
object Z {
3535
init {
36-
<!UNRESOLVED_REFERENCE!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!>()
37-
<!UNRESOLVED_REFERENCE!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>bar<!>()
36+
<!RESOLUTION_TO_CLASSIFIER!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!>()
37+
<!RESOLUTION_TO_CLASSIFIER!>B<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>bar<!>()
3838

39-
<!UNRESOLVED_REFERENCE!>D<!>()
39+
<!RESOLUTION_TO_CLASSIFIER!>D<!>()
4040
C()
4141
}
4242
}
@@ -58,7 +58,7 @@ class F: A() {
5858
companion object {
5959
init {
6060
B().fas()
61-
<!UNRESOLVED_REFERENCE!>D<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>f<!>()
61+
<!RESOLUTION_TO_CLASSIFIER!>D<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>f<!>()
6262
}
6363
}
64-
}
64+
}

compiler/testData/diagnostics/tests/scopes/inheritance/nestedFromJava.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Y: B() {
4646

4747
init {
4848
B_()
49-
B.<!UNRESOLVED_REFERENCE!>B_<!>()
49+
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
5050
Y.<!UNRESOLVED_REFERENCE!>B_<!>()
5151

5252
B_S()
@@ -59,7 +59,7 @@ class Y: B() {
5959
val b_s: B_S = null!!
6060

6161
init {
62-
<!UNRESOLVED_REFERENCE!>B_<!>()
62+
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
6363
B_S()
6464
}
6565
}
@@ -83,8 +83,8 @@ class Z: C() {
8383

8484
init {
8585
<!UNRESOLVED_REFERENCE!>A_S<!>()
86-
<!UNRESOLVED_REFERENCE!>B_<!>()
86+
<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
8787
B_S()
8888
}
8989
}
90-
}
90+
}

compiler/testData/diagnostics/tests/scopes/inheritance/nestedFromJavaAfterKotlin.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class F extends D {
3636
class X: D() {
3737
init {
3838
B_()
39-
B.<!UNRESOLVED_REFERENCE!>B_<!>()
39+
B.<!RESOLUTION_TO_CLASSIFIER!>B_<!>()
4040
C.<!UNRESOLVED_REFERENCE!>B_<!>()
4141
D.<!UNRESOLVED_REFERENCE!>B_<!>()
4242
X.<!UNRESOLVED_REFERENCE!>B_<!>()
@@ -79,4 +79,4 @@ class Y: F() {
7979
F.<!UNRESOLVED_REFERENCE!>E_S<!>()
8080
Y.<!UNRESOLVED_REFERENCE!>E_S<!>()
8181
}
82-
}
82+
}

compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class Outer {
2727
typealias Test5 = Outer.Inner
2828

2929
val test5 = <!UNRESOLVED_REFERENCE!>Test5<!>()
30-
val test5a = Outer.<!UNRESOLVED_REFERENCE!>Inner<!>()
30+
val test5a = Outer.<!RESOLUTION_TO_CLASSIFIER!>Inner<!>()
3131
val test5b = Outer.<!UNRESOLVED_REFERENCE!>TestInner<!>()
3232
val test5c = Outer().<!UNRESOLVED_REFERENCE!>TestInner<!>()
3333
val test5d = Outer().Inner()
34-
val test5e = Outer().Test5()
34+
val test5e = Outer().Test5()

compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11347,6 +11347,18 @@ public void testInnerClassesInStaticParameters() throws Exception {
1134711347
doTest(fileName);
1134811348
}
1134911349

11350+
@TestMetadata("innerConstructorsFromQualifiers.kt")
11351+
public void testInnerConstructorsFromQualifiers() throws Exception {
11352+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerConstructorsFromQualifiers.kt");
11353+
doTest(fileName);
11354+
}
11355+
11356+
@TestMetadata("innerConstructorsFromQualifiersWithIrrelevantCandidate.kt")
11357+
public void testInnerConstructorsFromQualifiersWithIrrelevantCandidate() throws Exception {
11358+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerConstructorsFromQualifiersWithIrrelevantCandidate.kt");
11359+
doTest(fileName);
11360+
}
11361+
1135011362
@TestMetadata("innerErrorForClassObjects.kt")
1135111363
public void testInnerErrorForClassObjects() throws Exception {
1135211364
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.kt");

0 commit comments

Comments
 (0)