FIR: implement resolve of unqualified enum references in when
See KT-16768
This commit is contained in:
committed by
teamcity
parent
f35b4b7515
commit
981f8b1871
+52
@@ -4122,6 +4122,58 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class UnqualifiedEnum {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInUnqualifiedEnum() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("correctJava.kt")
|
||||||
|
public void testCorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/correctJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("incorrectJava.kt")
|
||||||
|
public void testIncorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/incorrectJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nested.kt")
|
||||||
|
public void testNested() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/nested.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notInsideBranches.kt")
|
||||||
|
public void testNotInsideBranches() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/notInsideBranches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("priority.kt")
|
||||||
|
public void testPriority() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeAlias.kt")
|
||||||
|
public void testTypeAlias() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/typeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+48
@@ -3685,6 +3685,54 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class UnqualifiedEnum extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInUnqualifiedEnum() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("correctJava.kt")
|
||||||
|
public void testCorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/correctJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("incorrectJava.kt")
|
||||||
|
public void testIncorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/incorrectJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nested.kt")
|
||||||
|
public void testNested() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/nested.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notInsideBranches.kt")
|
||||||
|
public void testNotInsideBranches() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/notInsideBranches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("priority.kt")
|
||||||
|
public void testPriority() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeAlias.kt")
|
||||||
|
public void testTypeAlias() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/typeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FILE: test.kt
|
||||||
|
public final fun foo(javaEnum: R|JavaEnum|): R|kotlin/Int| {
|
||||||
|
^foo when (R|<local>/javaEnum|) {
|
||||||
|
==($subj$, R|/JavaEnum.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|/JavaEnum.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// FILE: JavaEnum.java
|
||||||
|
|
||||||
|
public enum JavaEnum {
|
||||||
|
FIRST,
|
||||||
|
SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun foo(javaEnum: JavaEnum) = when (javaEnum) {
|
||||||
|
FIRST -> 1
|
||||||
|
SECOND -> 2
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FILE: test.kt
|
||||||
|
public final fun foo(javaEnum: R|JavaEnum|): R|kotlin/Unit| {
|
||||||
|
^foo when (R|<local>/javaEnum|) {
|
||||||
|
==($subj$, <Unresolved name: first>#()) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, <Unresolved name: second>#) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FILE: JavaEnum.java
|
||||||
|
|
||||||
|
public enum JavaEnum {
|
||||||
|
FIRST,
|
||||||
|
SECOND;
|
||||||
|
|
||||||
|
public static JavaEnum first() {
|
||||||
|
return FIRST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JavaEnum second = SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun foo(javaEnum: JavaEnum) = <!NO_ELSE_IN_WHEN!>when<!> (javaEnum) {
|
||||||
|
<!UNRESOLVED_REFERENCE!>first<!>() -> 1
|
||||||
|
<!UNRESOLVED_REFERENCE!>second<!> -> 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
FILE: nested.kt
|
||||||
|
public final enum class Outer : R|kotlin/Enum<Outer>| {
|
||||||
|
private constructor(): R|Outer| {
|
||||||
|
super<R|kotlin/Enum<Outer>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry FIRST: R|Outer|
|
||||||
|
public final static enum entry SECOND: R|Outer|
|
||||||
|
public final static fun values(): R|kotlin/Array<Outer>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|Outer| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final enum class Inner : R|kotlin/Enum<Inner>| {
|
||||||
|
private constructor(): R|Inner| {
|
||||||
|
super<R|kotlin/Enum<Inner>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry SECOND: R|Inner|
|
||||||
|
public final static enum entry THIRD: R|Inner|
|
||||||
|
public final static fun values(): R|kotlin/Array<Inner>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|Inner| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun foo(o: R|Outer|, i: R|Inner|): R|kotlin/Int| {
|
||||||
|
^foo when (R|<local>/o|) {
|
||||||
|
==($subj$, R|/Outer.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|/Outer.SECOND|) -> {
|
||||||
|
when (R|<local>/i|) {
|
||||||
|
==($subj$, R|/Inner.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
==($subj$, R|/Inner.THIRD|) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun bar(o: R|Outer|, i: R|Inner|): R|kotlin/Int| {
|
||||||
|
^bar when (R|<local>/o|) {
|
||||||
|
==($subj$, R|/Outer.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|/Outer.SECOND|) -> {
|
||||||
|
local final fun baz(): R|kotlin/Int| {
|
||||||
|
^baz when (R|<local>/i|) {
|
||||||
|
==($subj$, R|/Inner.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
==($subj$, R|/Inner.THIRD|) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
R|<local>/baz|()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
enum class Outer {
|
||||||
|
FIRST, SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Inner {
|
||||||
|
SECOND, THIRD;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(o: Outer, i: Inner): Int {
|
||||||
|
return when (o) {
|
||||||
|
FIRST -> 1
|
||||||
|
SECOND -> when (i) {
|
||||||
|
SECOND -> 2
|
||||||
|
THIRD -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar(o: Outer, i: Inner): Int {
|
||||||
|
return when (o) {
|
||||||
|
FIRST -> 1
|
||||||
|
SECOND -> {
|
||||||
|
fun baz(): Int {
|
||||||
|
return when (i) {
|
||||||
|
SECOND -> 2
|
||||||
|
THIRD -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
FILE: notInsideBranches.kt
|
||||||
|
public final enum class Some : R|kotlin/Enum<Some>| {
|
||||||
|
private constructor(): R|Some| {
|
||||||
|
super<R|kotlin/Enum<Some>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry FIRST: R|Some|
|
||||||
|
public final static enum entry SECOND: R|Some|
|
||||||
|
public final static fun values(): R|kotlin/Array<Some>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|Some| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun foo(s: R|Some|): <ERROR TYPE REF: Cannot infer argument for type parameter K> {
|
||||||
|
^foo when (R|<local>/s|) {
|
||||||
|
==($subj$, R|/Some.FIRST|) -> {
|
||||||
|
<Unresolved name: SECOND>#
|
||||||
|
}
|
||||||
|
==($subj$, R|/Some.SECOND|) -> {
|
||||||
|
<Unresolved name: FIRST>#
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
enum class Some {
|
||||||
|
FIRST,
|
||||||
|
SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(s: Some) = when (s) {
|
||||||
|
FIRST -> <!UNRESOLVED_REFERENCE!>SECOND<!>
|
||||||
|
SECOND -> <!UNRESOLVED_REFERENCE!>FIRST<!>
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
FILE: first.kt
|
||||||
|
package first
|
||||||
|
|
||||||
|
public final enum class First : R|kotlin/Enum<first/First>| {
|
||||||
|
private constructor(): R|first/First| {
|
||||||
|
super<R|kotlin/Enum<first/First>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry ONE: R|first/First|
|
||||||
|
public final static enum entry TWO: R|first/First|
|
||||||
|
public final static fun values(): R|kotlin/Array<first/First>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|first/First| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val THREE: R|first/First| = Q|first/First|.R|first/First.ONE|
|
||||||
|
public get(): R|first/First|
|
||||||
|
FILE: second.kt
|
||||||
|
package second
|
||||||
|
|
||||||
|
public final enum class Second : R|kotlin/Enum<second/Second>| {
|
||||||
|
private constructor(): R|second/Second| {
|
||||||
|
super<R|kotlin/Enum<second/Second>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry THREE: R|second/Second|
|
||||||
|
public final static enum entry FOUR: R|second/Second|
|
||||||
|
public final static fun values(): R|kotlin/Array<second/Second>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|second/Second| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val ONE: R|second/Second| = Q|second/Second|.R|second/Second.THREE|
|
||||||
|
public get(): R|second/Second|
|
||||||
|
public final fun foo(f: R|first/First|): R|kotlin/Unit| {
|
||||||
|
^foo when (R|<local>/f|) {
|
||||||
|
==($subj$, R|second/ONE|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|first/First.TWO|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun bar(s: R|second/Second|): R|kotlin/Unit| {
|
||||||
|
^bar when (R|<local>/s|) {
|
||||||
|
==($subj$, R|first/THREE|) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
==($subj$, R|second/Second.FOUR|) -> {
|
||||||
|
Int(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// FILE: first.kt
|
||||||
|
|
||||||
|
package first
|
||||||
|
|
||||||
|
enum class First {
|
||||||
|
ONE, TWO;
|
||||||
|
}
|
||||||
|
|
||||||
|
val THREE = First.ONE
|
||||||
|
|
||||||
|
// FILE: second.kt
|
||||||
|
|
||||||
|
package second
|
||||||
|
|
||||||
|
import first.First
|
||||||
|
import first.THREE
|
||||||
|
|
||||||
|
enum class Second {
|
||||||
|
THREE, FOUR;
|
||||||
|
}
|
||||||
|
|
||||||
|
val ONE = Second.THREE
|
||||||
|
|
||||||
|
fun foo(f: First) = <!NO_ELSE_IN_WHEN!>when<!> (f) {
|
||||||
|
<!INCOMPATIBLE_TYPES!>ONE<!> -> 1
|
||||||
|
TWO -> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar(s: Second) = <!NO_ELSE_IN_WHEN!>when<!> (s) {
|
||||||
|
<!INCOMPATIBLE_TYPES!>THREE<!> -> 3
|
||||||
|
FOUR -> 4
|
||||||
|
}
|
||||||
|
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
FILE: typeAlias.kt
|
||||||
|
public final enum class Some : R|kotlin/Enum<Some>| {
|
||||||
|
private constructor(): R|Some| {
|
||||||
|
super<R|kotlin/Enum<Some>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry FIRST: R|Some|
|
||||||
|
public final static enum entry SECOND: R|Some|
|
||||||
|
public final static fun values(): R|kotlin/Array<Some>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|Some| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final typealias Other = R|Some|
|
||||||
|
public final fun foo(o: R|Other|): R|kotlin/Int| {
|
||||||
|
^foo when (R|<local>/o|) {
|
||||||
|
==($subj$, R|/Some.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|/Some.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
enum class Some {
|
||||||
|
FIRST,
|
||||||
|
SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias Other = Some
|
||||||
|
|
||||||
|
fun foo(o: Other) = when (o) {
|
||||||
|
FIRST -> 1
|
||||||
|
SECOND -> 2
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
FILE: unqualifiedEnum.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
public final enum class Sample : R|kotlin/Enum<test/Sample>| {
|
||||||
|
private constructor(): R|test/Sample| {
|
||||||
|
super<R|kotlin/Enum<test/Sample>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry FIRST: R|test/Sample|
|
||||||
|
public final static enum entry SECOND: R|test/Sample|
|
||||||
|
public final static enum entry THIRD: R|test/Sample|
|
||||||
|
public final static fun values(): R|kotlin/Array<test/Sample>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|test/Sample| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun trivial(s: R|test/Sample|): R|kotlin/Int| {
|
||||||
|
^trivial when (R|<local>/s|) {
|
||||||
|
==($subj$, R|test/Sample.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==($subj$, R|test/Sample.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
==($subj$, R|test/Sample.THIRD|) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun shouldNotWork(s: R|test/Sample|): R|kotlin/Int| {
|
||||||
|
^shouldNotWork when () {
|
||||||
|
==(R|<local>/s|, <Unresolved name: FIRST>#) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
==(R|<local>/s|, <Unresolved name: SECOND>#) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
==(R|<local>/s|, <Unresolved name: THIRD>#) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Int(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Container : R|kotlin/Any| {
|
||||||
|
public constructor(): R|test/Container| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val SECOND: R|test/Sample| = Q|test/Sample|.R|test/Sample.SECOND|
|
||||||
|
public get(): R|test/Sample|
|
||||||
|
|
||||||
|
public final fun priority(s: R|test/Sample|): R|kotlin/Int| {
|
||||||
|
lval FIRST: R|test/Sample| = Q|test/Sample|.R|test/Sample.THIRD|
|
||||||
|
^priority when (R|<local>/s|) {
|
||||||
|
==($subj$, R|<local>/FIRST|) -> {
|
||||||
|
Int(3)
|
||||||
|
}
|
||||||
|
==($subj$, this@R|test/Container|.R|test/Container.SECOND|) -> {
|
||||||
|
Int(2)
|
||||||
|
}
|
||||||
|
==($subj$, Q|test/Sample|.R|test/Sample.FIRST|) -> {
|
||||||
|
Int(1)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Int(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
enum class Sample {
|
||||||
|
FIRST, SECOND, THIRD;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun trivial(s: Sample): Int {
|
||||||
|
return when (s) {
|
||||||
|
FIRST -> 1
|
||||||
|
SECOND -> 2
|
||||||
|
THIRD -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shouldNotWork(s: Sample): Int {
|
||||||
|
return when {
|
||||||
|
s == <!UNRESOLVED_REFERENCE!>FIRST<!> -> 1
|
||||||
|
s == <!UNRESOLVED_REFERENCE!>SECOND<!> -> 2
|
||||||
|
s == <!UNRESOLVED_REFERENCE!>THIRD<!> -> 3
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Container {
|
||||||
|
val SECOND = test.Sample.SECOND
|
||||||
|
|
||||||
|
fun priority(s: Sample): Int {
|
||||||
|
val FIRST = test.Sample.THIRD
|
||||||
|
return when (s) {
|
||||||
|
FIRST -> 3
|
||||||
|
SECOND -> 2
|
||||||
|
test.Sample.FIRST -> 1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+52
@@ -4122,6 +4122,58 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class UnqualifiedEnum {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInUnqualifiedEnum() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("correctJava.kt")
|
||||||
|
public void testCorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/correctJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("incorrectJava.kt")
|
||||||
|
public void testIncorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/incorrectJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nested.kt")
|
||||||
|
public void testNested() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/nested.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notInsideBranches.kt")
|
||||||
|
public void testNotInsideBranches() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/notInsideBranches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("priority.kt")
|
||||||
|
public void testPriority() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeAlias.kt")
|
||||||
|
public void testTypeAlias() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/typeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+52
@@ -4122,6 +4122,58 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class UnqualifiedEnum {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInUnqualifiedEnum() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("correctJava.kt")
|
||||||
|
public void testCorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/correctJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("incorrectJava.kt")
|
||||||
|
public void testIncorrectJava() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/incorrectJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nested.kt")
|
||||||
|
public void testNested() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/nested.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notInsideBranches.kt")
|
||||||
|
public void testNotInsideBranches() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/notInsideBranches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("priority.kt")
|
||||||
|
public void testPriority() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeAlias.kt")
|
||||||
|
public void testTypeAlias() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/typeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+6
@@ -17236,6 +17236,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testSuspendExtension() throws Exception {
|
public void testSuspendExtension() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt");
|
runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirImport
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
|
||||||
class FirExplicitStarImportingScope(
|
open class FirExplicitStarImportingScope(
|
||||||
imports: List<FirImport>,
|
imports: List<FirImport>,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
|
|||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.scopes.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildImport
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
// Note: at this moment we create this scope for enum classes only,
|
||||||
|
// and only enum entry symbols are allowed to be processed
|
||||||
|
class FirWhenSubjectImportingScope(
|
||||||
|
classId: ClassId, session: FirSession, scopeSession: ScopeSession
|
||||||
|
) : FirExplicitStarImportingScope(
|
||||||
|
listOf(buildResolvedImportByClassId(classId)),
|
||||||
|
session, scopeSession, FirImportingScopeFilter.ALL
|
||||||
|
) {
|
||||||
|
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||||
|
super.processPropertiesByName(name) {
|
||||||
|
if (it is FirEnumEntrySymbol) {
|
||||||
|
processor(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun buildResolvedImportByClassId(classId: ClassId) = buildResolvedImport {
|
||||||
|
delegate = buildImport {
|
||||||
|
importedFqName = classId.asSingleFqName()
|
||||||
|
isAllUnder = true
|
||||||
|
}
|
||||||
|
packageFqName = classId.packageFqName
|
||||||
|
relativeParentClassName = classId.relativeClassName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-2
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
|||||||
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
|
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -104,8 +105,13 @@ internal abstract class FirBaseTowerResolveTask(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ((depth, lexical) in towerDataElementsForName.nonLocalTowerDataElements.withIndex()) {
|
for ((depth, lexical) in towerDataElementsForName.nonLocalTowerDataElements.withIndex()) {
|
||||||
if (!lexical.isLocal && lexical.scope != null) {
|
val scope = lexical.scope
|
||||||
onScope(lexical.scope!!, parentGroup.NonLocal(depth))
|
if (!lexical.isLocal && scope != null) {
|
||||||
|
onScope(
|
||||||
|
scope,
|
||||||
|
if (scope is FirWhenSubjectImportingScope) TowerGroup.UnqualifiedEnum(depth)
|
||||||
|
else parentGroup.NonLocal(depth)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiver = lexical.implicitReceiver
|
val receiver = lexical.implicitReceiver
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ sealed class TowerGroupKind(val index: Byte) : Comparable<TowerGroupKind> {
|
|||||||
|
|
||||||
object QualifierValue : TowerGroupKind(8)
|
object QualifierValue : TowerGroupKind(8)
|
||||||
|
|
||||||
|
class UnqualifiedEnum(depth: Int) : WithDepth(9, depth)
|
||||||
|
|
||||||
object Last : TowerGroupKind(0b1111)
|
object Last : TowerGroupKind(0b1111)
|
||||||
|
|
||||||
override fun compareTo(other: TowerGroupKind): Int {
|
override fun compareTo(other: TowerGroupKind): Int {
|
||||||
@@ -157,6 +159,8 @@ private constructor(
|
|||||||
|
|
||||||
val Member = kindOf(TowerGroupKind.Member)
|
val Member = kindOf(TowerGroupKind.Member)
|
||||||
|
|
||||||
|
fun UnqualifiedEnum(depth: Int) = kindOf(TowerGroupKind.UnqualifiedEnum(depth))
|
||||||
|
|
||||||
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
||||||
|
|
||||||
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
||||||
|
|||||||
+36
-1
@@ -33,9 +33,11 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
|||||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
@@ -77,6 +79,9 @@ class BodyResolveContext(
|
|||||||
@set:PrivateForInline
|
@set:PrivateForInline
|
||||||
var containers: ArrayDeque<FirDeclaration> = ArrayDeque()
|
var containers: ArrayDeque<FirDeclaration> = ArrayDeque()
|
||||||
|
|
||||||
|
@PrivateForInline
|
||||||
|
val whenSubjectImportingScopes: ArrayDeque<FirWhenSubjectImportingScope?> = ArrayDeque()
|
||||||
|
|
||||||
@set:PrivateForInline
|
@set:PrivateForInline
|
||||||
var containingClass: FirRegularClass? = null
|
var containingClass: FirRegularClass? = null
|
||||||
|
|
||||||
@@ -94,7 +99,7 @@ class BodyResolveContext(
|
|||||||
get() = containingClassDeclarations.lastOrNull()
|
get() = containingClassDeclarations.lastOrNull()
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
private inline fun <T> withNewTowerDataForClass(newContexts: FirRegularTowerDataContexts, f: () -> T): T {
|
inline fun <T> withNewTowerDataForClass(newContexts: FirRegularTowerDataContexts, f: () -> T): T {
|
||||||
val old = regularTowerDataContexts
|
val old = regularTowerDataContexts
|
||||||
regularTowerDataContexts = newContexts
|
regularTowerDataContexts = newContexts
|
||||||
return try {
|
return try {
|
||||||
@@ -490,6 +495,36 @@ class BodyResolveContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(PrivateForInline::class)
|
||||||
|
inline fun <T> withWhenSubjectType(
|
||||||
|
subjectType: ConeKotlinType?,
|
||||||
|
sessionHolder: SessionHolder,
|
||||||
|
f: () -> T
|
||||||
|
): T {
|
||||||
|
val session = sessionHolder.session
|
||||||
|
val subjectClassSymbol = (subjectType as? ConeClassLikeType)
|
||||||
|
?.lookupTag?.toFirRegularClassSymbol(session)?.takeIf { it.fir.classKind == ClassKind.ENUM_CLASS }
|
||||||
|
val whenSubjectImportingScope = subjectClassSymbol?.let {
|
||||||
|
FirWhenSubjectImportingScope(it.classId, session, sessionHolder.scopeSession)
|
||||||
|
}
|
||||||
|
whenSubjectImportingScopes.add(whenSubjectImportingScope)
|
||||||
|
return try {
|
||||||
|
f()
|
||||||
|
} finally {
|
||||||
|
whenSubjectImportingScopes.removeLast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(PrivateForInline::class)
|
||||||
|
inline fun <T> withWhenSubjectImportingScope(f: () -> T): T {
|
||||||
|
val whenSubjectImportingScope = whenSubjectImportingScopes.lastOrNull() ?: return f()
|
||||||
|
val newTowerDataContext = towerDataContext.addNonLocalScope(whenSubjectImportingScope)
|
||||||
|
val newContexts = FirRegularTowerDataContexts(newTowerDataContext)
|
||||||
|
return withNewTowerDataForClass(newContexts) {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirConstructor.scopesWithPrimaryConstructorParameters(
|
private fun FirConstructor.scopesWithPrimaryConstructorParameters(
|
||||||
ownerClass: FirClass,
|
ownerClass: FirClass,
|
||||||
session: FirSession
|
session: FirSession
|
||||||
|
|||||||
+31
-29
@@ -12,12 +12,10 @@ import org.jetbrains.kotlin.fir.expressions.*
|
|||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.isUnitOrFlexibleUnit
|
import org.jetbrains.kotlin.fir.resolve.calls.isUnitOrFlexibleUnit
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformWhenSubjectExpressionUsingSmartcastInfo
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
|
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.withExpectedType
|
|
||||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||||
@@ -65,33 +63,35 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
return context.withWhenExpression(whenExpression, session) with@{
|
return context.withWhenExpression(whenExpression, session) with@{
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent)
|
var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
val subjectType = whenExpression.subject?.typeRef?.coneType?.fullyExpandedType(session)
|
||||||
when {
|
context.withWhenSubjectType(subjectType, components) {
|
||||||
whenExpression.branches.isEmpty() -> {}
|
when {
|
||||||
whenExpression.isOneBranch() -> {
|
whenExpression.branches.isEmpty() -> {}
|
||||||
whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextIndependent)
|
whenExpression.isOneBranch() -> {
|
||||||
whenExpression.resultType = whenExpression.branches.first().result.resultType
|
whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextIndependent)
|
||||||
}
|
whenExpression.resultType = whenExpression.branches.first().result.resultType
|
||||||
else -> {
|
|
||||||
whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextDependent)
|
|
||||||
|
|
||||||
whenExpression = syntheticCallGenerator.generateCalleeForWhenExpression(whenExpression, resolutionContext) ?: run {
|
|
||||||
whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null)
|
|
||||||
dataFlowAnalyzer.exitWhenExpression(whenExpression)
|
|
||||||
whenExpression.resultType = buildErrorTypeRef {
|
|
||||||
diagnostic = ConeSimpleDiagnostic("Can't resolve when expression", DiagnosticKind.InferenceError)
|
|
||||||
}
|
|
||||||
return@with whenExpression
|
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextDependent)
|
||||||
|
|
||||||
val completionResult = callCompleter.completeCall(whenExpression, data)
|
whenExpression = syntheticCallGenerator.generateCalleeForWhenExpression(whenExpression, resolutionContext) ?: run {
|
||||||
whenExpression = completionResult.result
|
whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null)
|
||||||
|
dataFlowAnalyzer.exitWhenExpression(whenExpression)
|
||||||
|
whenExpression.resultType = buildErrorTypeRef {
|
||||||
|
diagnostic = ConeSimpleDiagnostic("Can't resolve when expression", DiagnosticKind.InferenceError)
|
||||||
|
}
|
||||||
|
return@withWhenSubjectType whenExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
val completionResult = callCompleter.completeCall(whenExpression, data)
|
||||||
|
whenExpression = completionResult.result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null)
|
||||||
|
dataFlowAnalyzer.exitWhenExpression(whenExpression)
|
||||||
|
whenExpression = whenExpression.replaceReturnTypeIfNotExhaustive()
|
||||||
|
whenExpression
|
||||||
}
|
}
|
||||||
whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null)
|
|
||||||
dataFlowAnalyzer.exitWhenExpression(whenExpression)
|
|
||||||
whenExpression = whenExpression.replaceReturnTypeIfNotExhaustive()
|
|
||||||
whenExpression
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,9 +110,10 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun transformWhenBranch(whenBranch: FirWhenBranch, data: ResolutionMode): FirWhenBranch {
|
override fun transformWhenBranch(whenBranch: FirWhenBranch, data: ResolutionMode): FirWhenBranch {
|
||||||
return whenBranch.also { dataFlowAnalyzer.enterWhenBranchCondition(whenBranch) }
|
dataFlowAnalyzer.enterWhenBranchCondition(whenBranch)
|
||||||
.transformCondition(transformer, withExpectedType(session.builtinTypes.booleanType))
|
return context.withWhenSubjectImportingScope {
|
||||||
.also { dataFlowAnalyzer.exitWhenBranchCondition(it) }
|
whenBranch.transformCondition(transformer, withExpectedType(session.builtinTypes.booleanType))
|
||||||
|
}.also { dataFlowAnalyzer.exitWhenBranchCondition(it) }
|
||||||
.transformResult(transformer, data)
|
.transformResult(transformer, data)
|
||||||
.also { dataFlowAnalyzer.exitWhenBranchResult(it) }
|
.also { dataFlowAnalyzer.exitWhenBranchResult(it) }
|
||||||
|
|
||||||
@@ -186,6 +187,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
): FirStatement {
|
): FirStatement {
|
||||||
val labeledElement = returnExpression.target.labeledElement
|
val labeledElement = returnExpression.target.labeledElement
|
||||||
val expectedTypeRef = labeledElement.returnTypeRef
|
val expectedTypeRef = labeledElement.returnTypeRef
|
||||||
|
|
||||||
@Suppress("IntroduceWhenSubject")
|
@Suppress("IntroduceWhenSubject")
|
||||||
val mode = when {
|
val mode = when {
|
||||||
labeledElement.symbol in context.anonymousFunctionsAnalyzedInDependentContext -> {
|
labeledElement.symbol in context.anonymousFunctionsAnalyzedInDependentContext -> {
|
||||||
|
|||||||
+1
-1
@@ -167,7 +167,7 @@ class FirTowerDataContext private constructor(
|
|||||||
return addNonLocalScope(scope)
|
return addNonLocalScope(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNonLocalScope(scope: FirScope): FirTowerDataContext {
|
fun addNonLocalScope(scope: FirScope): FirTowerDataContext {
|
||||||
val element = scope.asTowerDataElement(isLocal = false)
|
val element = scope.asTowerDataElement(isLocal = false)
|
||||||
return FirTowerDataContext(
|
return FirTowerDataContext(
|
||||||
towerDataElements.add(element),
|
towerDataElements.add(element),
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND: JVM_IR
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
enum class Rainbow {
|
||||||
|
RED,
|
||||||
|
ORANGE,
|
||||||
|
YELLOW,
|
||||||
|
GREEN,
|
||||||
|
CYAN,
|
||||||
|
BLUE,
|
||||||
|
VIOLET
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sym(r: Rainbow) = when (r) {
|
||||||
|
RED -> 'r'
|
||||||
|
ORANGE -> 'o'
|
||||||
|
YELLOW -> 'y'
|
||||||
|
GREEN -> 'g'
|
||||||
|
CYAN -> 'c'
|
||||||
|
BLUE -> 'b'
|
||||||
|
VIOLET -> 'v'
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val s = buildString {
|
||||||
|
for (value in Rainbow.values()) {
|
||||||
|
append(sym(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return if (s == "roygcbv") "OK" else s
|
||||||
|
}
|
||||||
+6
@@ -17236,6 +17236,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testSuspendExtension() throws Exception {
|
public void testSuspendExtension() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt");
|
runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unqualifiedEnum.kt")
|
||||||
|
public void testUnqualifiedEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/unqualifiedEnum.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
Reference in New Issue
Block a user