From 90021f3eceea33af43efb41ba7633904552d3688 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 12 Feb 2020 12:17:58 +0300 Subject: [PATCH] [FIR-TEST] Reorganize tests for data flow analysis --- .../resolve/smartcasts/booleanOperators_0.dot | 503 ------------------ .../{ => booleans}/booleanOperators.dot | 0 .../{ => booleans}/booleanOperators.kt | 0 .../{ => booleans}/booleanOperators.txt | 0 .../{ => booleans}/equalsToBoolean.dot | 0 .../{ => booleans}/equalsToBoolean.kt | 0 .../{ => booleans}/equalsToBoolean.txt | 0 .../{ => boundSmartcasts}/boundSmartcasts.dot | 200 +++++++ .../{ => boundSmartcasts}/boundSmartcasts.kt | 30 ++ .../{ => boundSmartcasts}/boundSmartcasts.txt | 41 ++ .../boundSmartcastsInBranches.dot | 0 .../boundSmartcastsInBranches.kt | 0 .../boundSmartcastsInBranches.txt | 0 .../{ => controlStructures}/elvis.dot | 0 .../{ => controlStructures}/elvis.kt | 0 .../{ => controlStructures}/elvis.txt | 0 .../{ => controlStructures}/returns.dot | 139 +++++ .../{ => controlStructures}/returns.kt | 12 + .../{ => controlStructures}/returns.txt | 23 + .../{ => controlStructures}/simpleIf.dot | 0 .../{ => controlStructures}/simpleIf.kt | 0 .../{ => controlStructures}/simpleIf.txt | 0 .../smartcastFromArgument.dot | 0 .../smartcastFromArgument.kt | 0 .../smartcastFromArgument.txt | 0 .../{ => controlStructures}/when.dot | 0 .../{ => controlStructures}/when.kt | 0 .../{ => controlStructures}/when.txt | 0 .../{ => lambdas}/inPlaceLambdas.dot | 0 .../{ => lambdas}/inPlaceLambdas.kt | 0 .../{ => lambdas}/inPlaceLambdas.txt | 0 .../{ => lambdas}/smartcastOnLambda.dot | 0 .../{ => lambdas}/smartcastOnLambda.kt | 0 .../{ => lambdas}/smartcastOnLambda.txt | 0 .../dataFlowInfoFromWhileCondition.dot | 0 .../dataFlowInfoFromWhileCondition.kt | 0 .../dataFlowInfoFromWhileCondition.txt | 0 .../smartcasts/{ => loops}/endlessLoops.dot | 0 .../smartcasts/{ => loops}/endlessLoops.kt | 0 .../smartcasts/{ => loops}/endlessLoops.txt | 0 .../resolve/smartcasts/multipleCasts.dot | 139 +++++ ...notBoundSmartcasts.kt => multipleCasts.kt} | 32 +- .../resolve/smartcasts/multipleCasts.txt | 31 ++ .../resolve/smartcasts/notBoundSmartcasts.dot | 339 ------------ .../resolve/smartcasts/notBoundSmartcasts.txt | 72 --- .../problems/smartcastOnBangBang.dot | 59 ++ .../problems/smartcastOnBangBang.kt | 7 + .../problems/smartcastOnBangBang.txt | 11 + .../implicitReceiverAsWhenSubject.dot | 0 .../implicitReceiverAsWhenSubject.kt | 0 .../implicitReceiverAsWhenSubject.txt | 0 .../{ => receivers}/implicitReceivers.dot | 0 .../{ => receivers}/implicitReceivers.kt | 0 .../{ => receivers}/implicitReceivers.txt | 0 .../thisOfExtensionProperty.dot | 0 .../thisOfExtensionProperty.kt | 0 .../thisOfExtensionProperty.txt | 0 .../assignSafeCall.dot} | 2 +- .../assignSafeCall.kt} | 0 .../assignSafeCall.txt} | 2 +- .../safeCalls/safeCallAndEqualityToBool.dot | 290 ++++++++++ .../safeCalls/safeCallAndEqualityToBool.kt | 31 ++ .../safeCalls/safeCallAndEqualityToBool.txt | 45 ++ .../smartcasts/{ => safeCalls}/safeCalls.dot | 0 .../smartcasts/{ => safeCalls}/safeCalls.kt | 0 .../smartcasts/{ => safeCalls}/safeCalls.txt | 0 .../{ => stability}/overridenOpenVal.dot | 0 .../{ => stability}/overridenOpenVal.kt | 0 .../{ => stability}/overridenOpenVal.txt | 0 .../{ => variables}/delayedAssignment.dot | 0 .../{ => variables}/delayedAssignment.kt | 0 .../{ => variables}/delayedAssignment.txt | 0 .../smartcastAfterReassignment.dot | 0 .../smartcastAfterReassignment.kt | 0 .../smartcastAfterReassignment.txt | 0 .../stdlib/problems/complexSmartCasts.kt | 70 +-- .../stdlib/problems/complexSmartCasts.txt | 88 +-- .../FirDiagnosticsWithCfgTestGenerated.java | 348 ++++++++---- 78 files changed, 1324 insertions(+), 1190 deletions(-) delete mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators_0.dot rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/booleanOperators.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/booleanOperators.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/booleanOperators.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/equalsToBoolean.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/equalsToBoolean.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => booleans}/equalsToBoolean.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcasts.dot (57%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcasts.kt (52%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcasts.txt (55%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcastsInBranches.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcastsInBranches.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => boundSmartcasts}/boundSmartcastsInBranches.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/elvis.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/elvis.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/elvis.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/returns.dot (69%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/returns.kt (76%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/returns.txt (67%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/simpleIf.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/simpleIf.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/simpleIf.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/smartcastFromArgument.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/smartcastFromArgument.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/smartcastFromArgument.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/when.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/when.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => controlStructures}/when.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/inPlaceLambdas.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/inPlaceLambdas.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/inPlaceLambdas.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/smartcastOnLambda.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/smartcastOnLambda.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => lambdas}/smartcastOnLambda.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/dataFlowInfoFromWhileCondition.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/dataFlowInfoFromWhileCondition.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/dataFlowInfoFromWhileCondition.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/endlessLoops.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/endlessLoops.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => loops}/endlessLoops.txt (100%) create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.dot rename compiler/fir/resolve/testData/resolve/smartcasts/{notBoundSmartcasts.kt => multipleCasts.kt} (55%) create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.txt delete mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.dot delete mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.txt create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.dot create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.txt rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceiverAsWhenSubject.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceiverAsWhenSubject.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceiverAsWhenSubject.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceivers.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceivers.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/implicitReceivers.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/thisOfExtensionProperty.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/thisOfExtensionProperty.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => receivers}/thisOfExtensionProperty.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{anotherBoundSmartcasts.dot => safeCalls/assignSafeCall.dot} (99%) rename compiler/fir/resolve/testData/resolve/smartcasts/{anotherBoundSmartcasts.kt => safeCalls/assignSafeCall.kt} (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{anotherBoundSmartcasts.txt => safeCalls/assignSafeCall.txt} (98%) create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.dot create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt create mode 100644 compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.txt rename compiler/fir/resolve/testData/resolve/smartcasts/{ => safeCalls}/safeCalls.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => safeCalls}/safeCalls.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => safeCalls}/safeCalls.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => stability}/overridenOpenVal.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => stability}/overridenOpenVal.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => stability}/overridenOpenVal.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/delayedAssignment.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/delayedAssignment.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/delayedAssignment.txt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/smartcastAfterReassignment.dot (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/smartcastAfterReassignment.kt (100%) rename compiler/fir/resolve/testData/resolve/smartcasts/{ => variables}/smartcastAfterReassignment.txt (100%) diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators_0.dot b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators_0.dot deleted file mode 100644 index f901a823488..00000000000 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators_0.dot +++ /dev/null @@ -1,503 +0,0 @@ -digraph booleanOperators_kt { - graph [splines=ortho nodesep=3] - node [shape=box penwidth=2] - edge [penwidth=2] - - subgraph cluster_0 { - color=red - 0 [label="Enter function foo" style="filled" fillcolor=red]; - 1 [label="Exit function foo" style="filled" fillcolor=red]; - } - - 0 -> {1}; - - subgraph cluster_1 { - color=red - 2 [label="Enter function bool" style="filled" fillcolor=red]; - 3 [label="Exit function bool" style="filled" fillcolor=red]; - } - - 2 -> {3}; - - subgraph cluster_2 { - color=red - 4 [label="Enter function bar" style="filled" fillcolor=red]; - 5 [label="Exit function bar" style="filled" fillcolor=red]; - } - - 4 -> {5}; - - subgraph cluster_3 { - color=red - 6 [label="Enter function baz" style="filled" fillcolor=red]; - 7 [label="Exit function baz" style="filled" fillcolor=red]; - } - - 6 -> {7}; - - subgraph cluster_4 { - color=red - 8 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_5 { - color=blue - 9 [label="Enter when"]; - subgraph cluster_6 { - color=blue - 10 [label="Enter when branch condition "]; - subgraph cluster_7 { - color=blue - 11 [label="Enter &&"]; - 12 [label="Access variable R|/x|"]; - 13 [label="Type operator: x is B"]; - 14 [label="Exit left part of &&"]; - 15 [label="Enter right part of &&"]; - 16 [label="Access variable R|/x|"]; - 17 [label="Type operator: x is C"]; - 18 [label="Exit &&"]; - } - 19 [label="Exit when branch condition"]; - } - 20 [label="Synthetic else branch"]; - 21 [label="Enter when branch result"]; - subgraph cluster_8 { - color=blue - 22 [label="Enter block"]; - 23 [label="Access variable R|/x|"]; - 24 [label="Function call: R|/x|.R|/A.foo|()"]; - 25 [label="Access variable R|/x|"]; - 26 [label="Function call: R|/x|.R|/B.bar|()"]; - 27 [label="Access variable R|/x|"]; - 28 [label="Function call: R|/x|.R|/C.baz|()"]; - 29 [label="Exit block"]; - } - 30 [label="Exit when branch result"]; - 31 [label="Exit when"]; - } - 32 [label="Exit function test_1" style="filled" fillcolor=red]; - } - - 8 -> {9}; - 9 -> {10}; - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {14}; - 14 -> {18 15}; - 15 -> {16}; - 16 -> {17}; - 17 -> {18}; - 18 -> {19}; - 19 -> {21 20}; - 20 -> {31}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {30}; - 30 -> {31}; - 31 -> {32}; - - subgraph cluster_9 { - color=red - 33 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_10 { - color=blue - 34 [label="Enter when"]; - subgraph cluster_11 { - color=blue - 35 [label="Enter when branch condition "]; - subgraph cluster_12 { - color=blue - 36 [label="Enter ||"]; - 37 [label="Access variable R|/x|"]; - 38 [label="Type operator: x is B"]; - 39 [label="Exit left part of ||"]; - 40 [label="Enter right part of ||"]; - 41 [label="Access variable R|/x|"]; - 42 [label="Type operator: x is C"]; - 43 [label="Exit ||"]; - } - 44 [label="Exit when branch condition"]; - } - 45 [label="Synthetic else branch"]; - 46 [label="Enter when branch result"]; - subgraph cluster_13 { - color=blue - 47 [label="Enter block"]; - 48 [label="Access variable R|/x|"]; - 49 [label="Function call: R|/x|.R|/A.foo|()"]; - 50 [label="Access variable R|/x|"]; - 51 [label="Function call: R|/x|.#()"]; - 52 [label="Access variable R|/x|"]; - 53 [label="Function call: R|/x|.#()"]; - 54 [label="Exit block"]; - } - 55 [label="Exit when branch result"]; - 56 [label="Exit when"]; - } - 57 [label="Exit function test_2" style="filled" fillcolor=red]; - } - - 33 -> {34}; - 34 -> {35}; - 35 -> {36}; - 36 -> {37}; - 37 -> {38}; - 38 -> {39}; - 39 -> {43 40}; - 40 -> {41}; - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; - 44 -> {46 45}; - 45 -> {56}; - 46 -> {47}; - 47 -> {48}; - 48 -> {49}; - 49 -> {50}; - 50 -> {51}; - 51 -> {52}; - 52 -> {53}; - 53 -> {54}; - 54 -> {55}; - 55 -> {56}; - 56 -> {57}; - - subgraph cluster_14 { - color=red - 58 [label="Enter function test_3" style="filled" fillcolor=red]; - subgraph cluster_15 { - color=blue - 59 [label="Enter when"]; - subgraph cluster_16 { - color=blue - 60 [label="Enter when branch condition "]; - 61 [label="Access variable R|/x|"]; - 62 [label="Type operator: x !is A"]; - 63 [label="Function call: (R|/x| !is R|A|).R|kotlin/Boolean.not|()"]; - 64 [label="Exit when branch condition"]; - } - 65 [label="Synthetic else branch"]; - 66 [label="Enter when branch result"]; - subgraph cluster_17 { - color=blue - 67 [label="Enter block"]; - 68 [label="Access variable R|/x|"]; - 69 [label="Function call: R|/x|.R|/A.foo|()"]; - 70 [label="Exit block"]; - } - 71 [label="Exit when branch result"]; - 72 [label="Exit when"]; - } - 73 [label="Exit function test_3" style="filled" fillcolor=red]; - } - - 58 -> {59}; - 59 -> {60}; - 60 -> {61}; - 61 -> {62}; - 62 -> {63}; - 63 -> {64}; - 64 -> {66 65}; - 65 -> {72}; - 66 -> {67}; - 67 -> {68}; - 68 -> {69}; - 69 -> {70}; - 70 -> {71}; - 71 -> {72}; - 72 -> {73}; - - subgraph cluster_18 { - color=red - 74 [label="Enter function test_4" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 75 [label="Enter when"]; - subgraph cluster_20 { - color=blue - 76 [label="Enter when branch condition "]; - subgraph cluster_21 { - color=blue - 77 [label="Enter ||"]; - 78 [label="Access variable R|/x|"]; - 79 [label="Type operator: x !is String"]; - 80 [label="Exit left part of ||"]; - 81 [label="Enter right part of ||"]; - 82 [label="Access variable R|/x|"]; - 83 [label="Access variable R|kotlin/String.length|"]; - 84 [label="Const: Int(0)"]; - 85 [label="Operator =="]; - 86 [label="Exit ||"]; - } - 87 [label="Exit when branch condition"]; - } - 88 [label="Synthetic else branch"]; - 89 [label="Enter when branch result"]; - subgraph cluster_22 { - color=blue - 90 [label="Enter block"]; - 91 [label="Access variable R|/x|"]; - 92 [label="Access variable #"]; - 93 [label="Exit block"]; - } - 94 [label="Exit when branch result"]; - 95 [label="Exit when"]; - } - 96 [label="Access variable R|/x|"]; - 97 [label="Access variable #"]; - 98 [label="Exit function test_4" style="filled" fillcolor=red]; - } - - 74 -> {75}; - 75 -> {76}; - 76 -> {77}; - 77 -> {78}; - 78 -> {79}; - 79 -> {80}; - 80 -> {86 81}; - 81 -> {82}; - 82 -> {83}; - 83 -> {84}; - 84 -> {85}; - 85 -> {86}; - 86 -> {87}; - 87 -> {89 88}; - 88 -> {95}; - 89 -> {90}; - 90 -> {91}; - 91 -> {92}; - 92 -> {93}; - 93 -> {94}; - 94 -> {95}; - 95 -> {96}; - 96 -> {97}; - 97 -> {98}; - - subgraph cluster_23 { - color=red - 99 [label="Enter function test_5" style="filled" fillcolor=red]; - subgraph cluster_24 { - color=blue - 100 [label="Enter when"]; - subgraph cluster_25 { - color=blue - 101 [label="Enter when branch condition "]; - subgraph cluster_26 { - color=blue - 102 [label="Enter ||"]; - 103 [label="Access variable R|/x|"]; - 104 [label="Const: Null(null)"]; - 105 [label="Operator !="]; - 106 [label="Exit left part of ||"]; - 107 [label="Enter right part of ||"]; - 108 [label="Const: Boolean(false)"]; - 109 [label="Exit ||"]; - } - 110 [label="Exit when branch condition"]; - } - 111 [label="Synthetic else branch"]; - 112 [label="Enter when branch result"]; - subgraph cluster_27 { - color=blue - 113 [label="Enter block"]; - 114 [label="Access variable R|/x|"]; - 115 [label="Function call: R|/x|.#()"]; - 116 [label="Exit block"]; - } - 117 [label="Exit when branch result"]; - 118 [label="Exit when"]; - } - 119 [label="Exit function test_5" style="filled" fillcolor=red]; - } - - 99 -> {100}; - 100 -> {101}; - 101 -> {102}; - 102 -> {103}; - 103 -> {104}; - 104 -> {105}; - 105 -> {106}; - 106 -> {109 107}; - 107 -> {108}; - 108 -> {109}; - 109 -> {110}; - 110 -> {112 111}; - 111 -> {118}; - 112 -> {113}; - 113 -> {114}; - 114 -> {115}; - 115 -> {116}; - 116 -> {117}; - 117 -> {118}; - 118 -> {119}; - - subgraph cluster_28 { - color=red - 120 [label="Enter function test_6" style="filled" fillcolor=red]; - subgraph cluster_29 { - color=blue - 121 [label="Enter when"]; - subgraph cluster_30 { - color=blue - 122 [label="Enter when branch condition "]; - subgraph cluster_31 { - color=blue - 123 [label="Enter ||"]; - 124 [label="Const: Boolean(false)"]; - 125 [label="Exit left part of ||"]; - 126 [label="Enter right part of ||"]; - 127 [label="Access variable R|/x|"]; - 128 [label="Const: Null(null)"]; - 129 [label="Operator !="]; - 130 [label="Stub" style="filled" fillcolor=gray]; - 131 [label="Exit ||"]; - } - 132 [label="Exit when branch condition"]; - } - 133 [label="Synthetic else branch"]; - 134 [label="Enter when branch result"]; - subgraph cluster_32 { - color=blue - 135 [label="Enter block"]; - 136 [label="Access variable R|/x|"]; - 137 [label="Function call: R|/x|.#()"]; - 138 [label="Exit block"]; - } - 139 [label="Exit when branch result"]; - 140 [label="Exit when"]; - } - 141 [label="Exit function test_6" style="filled" fillcolor=red]; - } - - 120 -> {121}; - 121 -> {122}; - 122 -> {123}; - 123 -> {124}; - 124 -> {125}; - 125 -> {126}; - 125 -> {130} [style=dotted]; - 126 -> {127}; - 127 -> {128}; - 128 -> {129}; - 129 -> {131}; - 130 -> {131} [style=dotted]; - 131 -> {132}; - 132 -> {134 133}; - 133 -> {140}; - 134 -> {135}; - 135 -> {136}; - 136 -> {137}; - 137 -> {138}; - 138 -> {139}; - 139 -> {140}; - 140 -> {141}; - - subgraph cluster_33 { - color=red - 142 [label="Enter function test_7" style="filled" fillcolor=red]; - subgraph cluster_34 { - color=blue - 143 [label="Enter when"]; - subgraph cluster_35 { - color=blue - 144 [label="Enter when branch condition "]; - subgraph cluster_36 { - color=blue - 145 [label="Enter &&"]; - 146 [label="Access variable R|/x|"]; - 147 [label="Type operator: x is A"]; - 148 [label="Exit left part of &&"]; - 149 [label="Enter right part of &&"]; - 150 [label="Access variable R|/x|"]; - 151 [label="Function call: R|/x|.R|/A.bool|()"]; - 152 [label="Exit &&"]; - } - 153 [label="Exit when branch condition"]; - } - 154 [label="Synthetic else branch"]; - 155 [label="Enter when branch result"]; - subgraph cluster_37 { - color=blue - 156 [label="Enter block"]; - 157 [label="Access variable R|/x|"]; - 158 [label="Function call: R|/x|.R|/A.foo|()"]; - 159 [label="Exit block"]; - } - 160 [label="Exit when branch result"]; - 161 [label="Exit when"]; - } - 162 [label="Exit function test_7" style="filled" fillcolor=red]; - } - - 142 -> {143}; - 143 -> {144}; - 144 -> {145}; - 145 -> {146}; - 146 -> {147}; - 147 -> {148}; - 148 -> {152 149}; - 149 -> {150}; - 150 -> {151}; - 151 -> {152}; - 152 -> {153}; - 153 -> {155 154}; - 154 -> {161}; - 155 -> {156}; - 156 -> {157}; - 157 -> {158}; - 158 -> {159}; - 159 -> {160}; - 160 -> {161}; - 161 -> {162}; - - subgraph cluster_38 { - color=red - 163 [label="Enter function test_8" style="filled" fillcolor=red]; - subgraph cluster_39 { - color=blue - 164 [label="Enter when"]; - subgraph cluster_40 { - color=blue - 165 [label="Enter when branch condition "]; - 166 [label="Access variable R|/x|"]; - 167 [label="Type operator: x !is A"]; - 168 [label="Function call: (R|/x| !is R|A|).R|kotlin/Boolean.not|()"]; - 169 [label="Exit when branch condition"]; - } - 170 [label="Synthetic else branch"]; - 171 [label="Enter when branch result"]; - subgraph cluster_41 { - color=blue - 172 [label="Enter block"]; - 173 [label="Access variable R|/x|"]; - 174 [label="Function call: R|/x|.R|/A.foo|()"]; - 175 [label="Exit block"]; - } - 176 [label="Exit when branch result"]; - 177 [label="Exit when"]; - } - 178 [label="Exit function test_8" style="filled" fillcolor=red]; - } - - 163 -> {164}; - 164 -> {165}; - 165 -> {166}; - 166 -> {167}; - 167 -> {168}; - 168 -> {169}; - 169 -> {171 170}; - 170 -> {177}; - 171 -> {172}; - 172 -> {173}; - 173 -> {174}; - 174 -> {175}; - 175 -> {176}; - 176 -> {177}; - 177 -> {178}; - -} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.dot b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.kt b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.txt b/compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.dot b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot similarity index 57% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot index 68640b0a970..c4c2668e0dd 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot @@ -278,4 +278,204 @@ digraph boundSmartcasts_kt { 100 -> {101}; 101 -> {102}; + subgraph cluster_21 { + color=red + 103 [label="Enter function " style="filled" fillcolor=red]; + 104 [label="Exit function " style="filled" fillcolor=red]; + } + + 103 -> {104}; + + subgraph cluster_22 { + color=red + 105 [label="Enter function getter" style="filled" fillcolor=red]; + 106 [label="Exit function getter" style="filled" fillcolor=red]; + } + + 105 -> {106}; + + subgraph cluster_23 { + color=red + 107 [label="Enter property" style="filled" fillcolor=red]; + 108 [label="Access variable R|/any|"]; + 109 [label="Exit property" style="filled" fillcolor=red]; + } + + 107 -> {108}; + 108 -> {109}; + + subgraph cluster_24 { + color=red + 110 [label="Enter function baz" style="filled" fillcolor=red]; + 111 [label="Exit function baz" style="filled" fillcolor=red]; + } + + 110 -> {111}; + + subgraph cluster_25 { + color=red + 112 [label="Enter function test_5" style="filled" fillcolor=red]; + subgraph cluster_26 { + color=blue + 113 [label="Enter when"]; + 114 [label="Access variable R|/d|"]; + 115 [label="Access variable R|/D.any|"]; + 116 [label="Variable declaration: lval : R|kotlin/Any?|"]; + subgraph cluster_27 { + color=blue + 117 [label="Enter when branch condition "]; + 118 [label="Const: Null(null)"]; + 119 [label="Operator =="]; + 120 [label="Exit when branch condition"]; + } + subgraph cluster_28 { + color=blue + 121 [label="Enter when branch condition else"]; + 122 [label="Exit when branch condition"]; + } + 123 [label="Enter when branch result"]; + subgraph cluster_29 { + color=blue + 124 [label="Enter block"]; + 125 [label="Access variable R|/|"]; + 126 [label="Exit block"]; + } + 127 [label="Exit when branch result"]; + 128 [label="Enter when branch result"]; + subgraph cluster_30 { + color=blue + 129 [label="Enter block"]; + 130 [label="Jump: ^test_5 Unit"]; + 131 [label="Stub" style="filled" fillcolor=gray]; + 132 [label="Exit block" style="filled" fillcolor=gray]; + } + 133 [label="Exit when branch result" style="filled" fillcolor=gray]; + 134 [label="Exit when"]; + } + 135 [label="Variable declaration: lval a: R|kotlin/Any|"]; + 136 [label="Access variable R|/a|"]; + 137 [label="Function call: R|/a|.R|/baz|()"]; + 138 [label="Access variable R|/d|"]; + 139 [label="Access variable R|/D.any|"]; + 140 [label="Function call: R|/d|.R|/D.any|.R|/baz|()"]; + 141 [label="Access variable R|/a|"]; + 142 [label="Type operator: a as A"]; + 143 [label="Access variable R|/a|"]; + 144 [label="Function call: R|/a|.R|/A.foo|()"]; + 145 [label="Exit function test_5" style="filled" fillcolor=red]; + } + + 112 -> {113}; + 113 -> {114}; + 114 -> {115}; + 115 -> {116}; + 116 -> {117}; + 117 -> {118}; + 118 -> {119}; + 119 -> {120}; + 120 -> {128 121}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124}; + 124 -> {125}; + 125 -> {126}; + 126 -> {127}; + 127 -> {134}; + 128 -> {129}; + 129 -> {130}; + 130 -> {145}; + 130 -> {131} [style=dotted]; + 131 -> {132} [style=dotted]; + 132 -> {133} [style=dotted]; + 133 -> {134} [style=dotted]; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; + 138 -> {139}; + 139 -> {140}; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {144}; + 144 -> {145}; + + subgraph cluster_31 { + color=red + 146 [label="Enter function test_6" style="filled" fillcolor=red]; + 147 [label="Access variable R|/d1|"]; + 148 [label="Access variable R|/D.any|"]; + 149 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 150 [label="Access variable R|/a|"]; + 151 [label="Type operator: a as A"]; + 152 [label="Access variable R|/a|"]; + 153 [label="Function call: R|/a|.R|/A.foo|()"]; + 154 [label="Access variable R|/d1|"]; + 155 [label="Access variable R|/D.any|"]; + 156 [label="Function call: R|/d1|.R|/D.any|.R|/A.foo|()"]; + 157 [label="Access variable R|/d1|"]; + 158 [label="Access variable R|/D.any|"]; + 159 [label="Function call: R|/d1|.R|/D.any|.R|/baz|()"]; + 160 [label="Exit function test_6" style="filled" fillcolor=red]; + } + + 146 -> {147}; + 147 -> {148}; + 148 -> {149}; + 149 -> {150}; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; + 153 -> {154}; + 154 -> {155}; + 155 -> {156}; + 156 -> {157}; + 157 -> {158}; + 158 -> {159}; + 159 -> {160}; + + subgraph cluster_32 { + color=red + 161 [label="Enter function test_7" style="filled" fillcolor=red]; + 162 [label="Access variable R|/d1|"]; + 163 [label="Enter safe call"]; + 164 [label="Access variable R|/D.any|"]; + 165 [label="Exit safe call"]; + 166 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 167 [label="Access variable R|/d2|"]; + 168 [label="Enter safe call"]; + 169 [label="Access variable R|/D.any|"]; + 170 [label="Exit safe call"]; + 171 [label="Variable declaration: lval b: R|kotlin/Any?|"]; + 172 [label="Access variable R|/a|"]; + 173 [label="Type operator: a as A"]; + 174 [label="Access variable R|/a|"]; + 175 [label="Function call: R|/a|.R|/A.foo|()"]; + 176 [label="Access variable R|/b|"]; + 177 [label="Type operator: b as B"]; + 178 [label="Access variable R|/b|"]; + 179 [label="Function call: R|/b|.R|/B.bar|()"]; + 180 [label="Exit function test_7" style="filled" fillcolor=red]; + } + + 161 -> {162}; + 162 -> {163 165}; + 163 -> {164}; + 164 -> {165}; + 165 -> {166}; + 166 -> {167}; + 167 -> {168 170}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {173}; + 173 -> {174}; + 174 -> {175}; + 175 -> {176}; + 176 -> {177}; + 177 -> {178}; + 178 -> {179}; + 179 -> {180}; + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.kt b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.kt similarity index 52% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.kt index fa075a6123c..b68d1a8c135 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.kt @@ -44,4 +44,34 @@ fun test_4(y: Any) { x.foo() y.foo() } +} + +class D(val any: Any?) + +fun Any.baz() {} + +fun test_5(d: D) { + // Elvis operator is converted into == function call + val a = d.any ?: return + a.baz() // should be OK + d.any.baz() // should be OK + a as A + a.foo() // should be OK +} + +fun test_6(d1: D) { + val a = d1.any + a as A + a.foo() // should be OK + d1.any.foo() // should be OK + d1.any.baz() // should be OK +} + +fun test_7(d1: D, d2: D) { + val a = d1?.any + val b = d2?.any + a as A + a.foo() // should be OK + b as B + b.bar() // should be OK } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.txt b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt similarity index 55% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt index 76cf4cda2a5..ce8ee033138 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt @@ -58,3 +58,44 @@ FILE: boundSmartcasts.kt } } + public final class D : R|kotlin/Any| { + public constructor(any: R|kotlin/Any?|): R|D| { + super() + } + + public final val any: R|kotlin/Any?| = R|/any| + public get(): R|kotlin/Any?| + + } + public final fun R|kotlin/Any|.baz(): R|kotlin/Unit| { + } + public final fun test_5(d: R|D|): R|kotlin/Unit| { + lval a: R|kotlin/Any| = when (lval : R|kotlin/Any?| = R|/d|.R|/D.any|) { + ==($subj$, Null(null)) -> { + ^test_5 Unit + } + else -> { + R|/| + } + } + + R|/a|.R|/baz|() + R|/d|.R|/D.any|.R|/baz|() + (R|/a| as R|A|) + R|/a|.R|/A.foo|() + } + public final fun test_6(d1: R|D|): R|kotlin/Unit| { + lval a: R|kotlin/Any?| = R|/d1|.R|/D.any| + (R|/a| as R|A|) + R|/a|.R|/A.foo|() + R|/d1|.R|/D.any|.R|/A.foo|() + R|/d1|.R|/D.any|.R|/baz|() + } + public final fun test_7(d1: R|D|, d2: R|D|): R|kotlin/Unit| { + lval a: R|kotlin/Any?| = R|/d1|?.R|/D.any| + lval b: R|kotlin/Any?| = R|/d2|?.R|/D.any| + (R|/a| as R|A|) + R|/a|.R|/A.foo|() + (R|/b| as R|B|) + R|/b|.R|/B.bar|() + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.dot b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.kt b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.txt b/compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/elvis.dot b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/elvis.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/elvis.kt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/elvis.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/elvis.txt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/elvis.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/returns.dot b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.dot similarity index 69% rename from compiler/fir/resolve/testData/resolve/smartcasts/returns.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.dot index e55bdc4441f..ecc2ae48ed3 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/returns.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.dot @@ -341,4 +341,143 @@ digraph returns_kt { 118 -> {119}; 119 -> {120}; + subgraph cluster_29 { + color=red + 121 [label="Enter function runHigherOrder" style="filled" fillcolor=red]; + 122 [label="Function call: R|/f|.R|FakeOverride|()"]; + 123 [label="Jump: ^runHigherOrder R|/f|.R|FakeOverride|()"]; + 124 [label="Stub" style="filled" fillcolor=gray]; + 125 [label="Exit function runHigherOrder" style="filled" fillcolor=red]; + } + + 121 -> {122}; + 122 -> {123}; + 123 -> {125}; + 123 -> {124} [style=dotted]; + 124 -> {125} [style=dotted]; + + subgraph cluster_30 { + color=red + 126 [label="Enter function getter" style="filled" fillcolor=red]; + 127 [label="Access variable R|kotlin/String.length|"]; + 128 [label="Jump: ^ this@R|/ext|.R|kotlin/String.length|"]; + 129 [label="Stub" style="filled" fillcolor=gray]; + 130 [label="Exit function getter" style="filled" fillcolor=red]; + } + + 126 -> {127}; + 127 -> {128}; + 128 -> {130}; + 128 -> {129} [style=dotted]; + 129 -> {130} [style=dotted]; + + subgraph cluster_31 { + color=red + 131 [label="Enter property" style="filled" fillcolor=red]; + 132 [label="Exit property" style="filled" fillcolor=red]; + } + + 131 -> {132}; + + subgraph cluster_32 { + color=red + 133 [label="Enter function test_4" style="filled" fillcolor=red]; + 134 [label="Access variable R|/a|"]; + 135 [label="Type operator: a as? String"]; + 136 [label="Variable declaration: lval s: R|kotlin/String?|"]; + subgraph cluster_33 { + color=blue + 137 [label="Enter when"]; + 138 [label="Access variable R|/s|"]; + 139 [label="Enter safe call"]; + 140 [label="Access variable R|/ext|"]; + 141 [label="Exit safe call"]; + 142 [label="Variable declaration: lval : R|kotlin/Int?|"]; + subgraph cluster_34 { + color=blue + 143 [label="Enter when branch condition "]; + 144 [label="Const: Null(null)"]; + 145 [label="Operator =="]; + 146 [label="Exit when branch condition"]; + } + subgraph cluster_35 { + color=blue + 147 [label="Enter when branch condition else"]; + 148 [label="Exit when branch condition"]; + } + 149 [label="Enter when branch result"]; + subgraph cluster_36 { + color=blue + 150 [label="Enter block"]; + 151 [label="Access variable R|/|"]; + 152 [label="Exit block"]; + } + 153 [label="Exit when branch result"]; + 154 [label="Enter when branch result"]; + subgraph cluster_37 { + color=blue + 155 [label="Enter block"]; + 156 [label="Jump: ^test_4 Unit"]; + 157 [label="Stub" style="filled" fillcolor=gray]; + 158 [label="Exit block" style="filled" fillcolor=gray]; + } + 159 [label="Exit when branch result" style="filled" fillcolor=gray]; + 160 [label="Exit when"]; + } + 161 [label="Variable declaration: lval length: R|kotlin/Int|"]; + 162 [label="Postponed enter to lambda"]; + 163 [label="Postponed exit from lambda"]; + 164 [label="Function call: R|/runHigherOrder|( = runHigherOrder@fun (): R|kotlin/Boolean| { + ^ R|/s|.R|kotlin/text/isNotEmpty|() +} +)"]; + 165 [label="Exit function test_4" style="filled" fillcolor=red]; + } + + 133 -> {134}; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; + 138 -> {139 141}; + 139 -> {140}; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {144}; + 144 -> {145}; + 145 -> {146}; + 146 -> {154 147}; + 147 -> {148}; + 148 -> {149}; + 149 -> {150}; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; + 153 -> {160}; + 154 -> {155}; + 155 -> {156}; + 156 -> {165}; + 156 -> {157} [style=dotted]; + 157 -> {158} [style=dotted]; + 158 -> {159} [style=dotted]; + 159 -> {160} [style=dotted]; + 160 -> {161}; + 161 -> {162}; + 162 -> {163 163} [color=green]; + 163 -> {164}; + 164 -> {165}; + + subgraph cluster_38 { + color=red + 166 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 167 [label="Access variable R|/s|"]; + 168 [label="Function call: R|/s|.R|kotlin/text/isNotEmpty|()"]; + 169 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + + 166 -> {167}; + 167 -> {168}; + 168 -> {169}; + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/returns.kt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.kt similarity index 76% rename from compiler/fir/resolve/testData/resolve/smartcasts/returns.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.kt index 5a0d1ca390f..e88de7b7fb9 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/returns.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.kt @@ -47,4 +47,16 @@ fun test_3(x: Any) { x.foo() x.bar() x.baz() +} + +fun runHigherOrder(f: () -> T): T = f() + +val String.ext: Int get() = length + +fun test_4(a: Any?) { + val s = a as? String + val length = s?.ext ?: return + runHigherOrder { + s.isNotEmpty() // Should be OK + } } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/returns.txt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.txt similarity index 67% rename from compiler/fir/resolve/testData/resolve/smartcasts/returns.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.txt index 1a7d51ef421..aa455f7dacd 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/returns.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.txt @@ -65,3 +65,26 @@ FILE: returns.kt R|/x|.#() R|/x|.#() } + public final fun runHigherOrder(f: R|() -> T|): R|T| { + ^runHigherOrder R|/f|.R|FakeOverride|() + } + public final val R|kotlin/String|.ext: R|kotlin/Int| + public get(): R|kotlin/Int| { + ^ this@R|/ext|.R|kotlin/String.length| + } + public final fun test_4(a: R|kotlin/Any?|): R|kotlin/Unit| { + lval s: R|kotlin/String?| = (R|/a| as? R|kotlin/String|) + lval length: R|kotlin/Int| = when (lval : R|kotlin/Int?| = R|/s|?.R|/ext|) { + ==($subj$, Null(null)) -> { + ^test_4 Unit + } + else -> { + R|/| + } + } + + R|/runHigherOrder|( = runHigherOrder@fun (): R|kotlin/Boolean| { + ^ R|/s|.R|kotlin/text/isNotEmpty|() + } + ) + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.dot b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.kt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.txt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.dot b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.kt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.txt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.dot b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/when.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.kt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/when.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.txt b/compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/when.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.dot b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.kt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.txt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.dot b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.kt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.txt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.dot b/compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.kt b/compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.txt b/compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.dot b/compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.kt b/compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.txt b/compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.dot b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.dot new file mode 100644 index 00000000000..93589321a11 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.dot @@ -0,0 +1,139 @@ +digraph multipleCasts_kt { + graph [splines=ortho nodesep=3] + node [shape=box penwidth=2] + edge [penwidth=2] + + subgraph cluster_0 { + color=red + 0 [label="Enter function foo" style="filled" fillcolor=red]; + 1 [label="Exit function foo" style="filled" fillcolor=red]; + } + + 0 -> {1}; + + subgraph cluster_1 { + color=red + 2 [label="Enter function foo" style="filled" fillcolor=red]; + 3 [label="Exit function foo" style="filled" fillcolor=red]; + } + + 2 -> {3}; + + subgraph cluster_2 { + color=red + 4 [label="Enter function getAny" style="filled" fillcolor=red]; + 5 [label="Const: Null(null)"]; + 6 [label="Jump: ^getAny Null(null)"]; + 7 [label="Stub" style="filled" fillcolor=gray]; + 8 [label="Exit function getAny" style="filled" fillcolor=red]; + } + + 4 -> {5}; + 5 -> {6}; + 6 -> {8}; + 6 -> {7} [style=dotted]; + 7 -> {8} [style=dotted]; + + subgraph cluster_3 { + color=red + 9 [label="Enter function test_0" style="filled" fillcolor=red]; + 10 [label="Function call: R|/getAny|()"]; + 11 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 12 [label="Function call: R|/getAny|()"]; + 13 [label="Variable declaration: lval b: R|kotlin/Any?|"]; + 14 [label="Access variable R|/a|"]; + 15 [label="Type operator: a as A"]; + 16 [label="Access variable R|/a|"]; + 17 [label="Function call: R|/a|.R|/A.foo|()"]; + 18 [label="Access variable R|/b|"]; + 19 [label="Type operator: b as B"]; + 20 [label="Access variable R|/b|"]; + 21 [label="Function call: R|/b|.R|/B.foo|()"]; + 22 [label="Exit function test_0" style="filled" fillcolor=red]; + } + + 9 -> {10}; + 10 -> {11}; + 11 -> {12}; + 12 -> {13}; + 13 -> {14}; + 14 -> {15}; + 15 -> {16}; + 16 -> {17}; + 17 -> {18}; + 18 -> {19}; + 19 -> {20}; + 20 -> {21}; + 21 -> {22}; + + subgraph cluster_4 { + color=red + 23 [label="Enter function test_1" style="filled" fillcolor=red]; + 24 [label="Function call: R|/getAny|()"]; + 25 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 26 [label="Function call: R|/getAny|()"]; + 27 [label="Variable declaration: lval b: R|kotlin/Any?|"]; + subgraph cluster_5 { + color=blue + 28 [label="Enter when"]; + subgraph cluster_6 { + color=blue + 29 [label="Enter when branch condition "]; + subgraph cluster_7 { + color=blue + 30 [label="Enter &&"]; + 31 [label="Access variable R|/a|"]; + 32 [label="Type operator: a is A"]; + 33 [label="Exit left part of &&"]; + 34 [label="Enter right part of &&"]; + 35 [label="Access variable R|/b|"]; + 36 [label="Type operator: b is B"]; + 37 [label="Exit &&"]; + } + 38 [label="Exit when branch condition"]; + } + 39 [label="Synthetic else branch"]; + 40 [label="Enter when branch result"]; + subgraph cluster_8 { + color=blue + 41 [label="Enter block"]; + 42 [label="Access variable R|/a|"]; + 43 [label="Function call: R|/a|.R|/A.foo|()"]; + 44 [label="Access variable R|/b|"]; + 45 [label="Function call: R|/b|.R|/B.foo|()"]; + 46 [label="Exit block"]; + } + 47 [label="Exit when branch result"]; + 48 [label="Exit when"]; + } + 49 [label="Exit function test_1" style="filled" fillcolor=red]; + } + + 23 -> {24}; + 24 -> {25}; + 25 -> {26}; + 26 -> {27}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {31}; + 31 -> {32}; + 32 -> {33}; + 33 -> {37 34}; + 34 -> {35}; + 35 -> {36}; + 36 -> {37}; + 37 -> {38}; + 38 -> {40 39}; + 39 -> {48}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + +} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.kt b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.kt similarity index 55% rename from compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.kt index 5d823ed732e..7638385bc1a 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.kt @@ -25,34 +25,4 @@ fun test_1() { a.foo() b.foo() } -} - -class D(val any: Any?) - -fun Any.baz() {} - -fun test_2(d: D) { - // Elvis operator is converted into == function call - val a = d.any ?: return - a.baz() - d.any.baz() - a as A - a.foo() -} - -fun test_3(d1: D) { - val a = d1.any - a as A - a.foo() - d1.any.foo() - d1.any.baz() -} - -fun test_4(d1: D, d2: D) { - val a = d1?.any - val b = d2?.any - a as A - a.foo() - b as B - b.foo() // should be OK -} +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.txt b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.txt new file mode 100644 index 00000000000..d22b90ad1cc --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.txt @@ -0,0 +1,31 @@ +FILE: multipleCasts.kt + public abstract interface A : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Int| + + } + public abstract interface B : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Int| + + } + public final fun getAny(): R|kotlin/Any?| { + ^getAny Null(null) + } + public final fun test_0(): R|kotlin/Unit| { + lval a: R|kotlin/Any?| = R|/getAny|() + lval b: R|kotlin/Any?| = R|/getAny|() + (R|/a| as R|A|) + R|/a|.R|/A.foo|() + (R|/b| as R|B|) + R|/b|.R|/B.foo|() + } + public final fun test_1(): R|kotlin/Unit| { + lval a: R|kotlin/Any?| = R|/getAny|() + lval b: R|kotlin/Any?| = R|/getAny|() + when () { + (R|/a| is R|A|) && (R|/b| is R|B|) -> { + R|/a|.R|/A.foo|() + R|/b|.R|/B.foo|() + } + } + + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.dot b/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.dot deleted file mode 100644 index b368cfa1b22..00000000000 --- a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.dot +++ /dev/null @@ -1,339 +0,0 @@ -digraph notBoundSmartcasts_kt { - graph [splines=ortho nodesep=3] - node [shape=box penwidth=2] - edge [penwidth=2] - - subgraph cluster_0 { - color=red - 0 [label="Enter function foo" style="filled" fillcolor=red]; - 1 [label="Exit function foo" style="filled" fillcolor=red]; - } - - 0 -> {1}; - - subgraph cluster_1 { - color=red - 2 [label="Enter function foo" style="filled" fillcolor=red]; - 3 [label="Exit function foo" style="filled" fillcolor=red]; - } - - 2 -> {3}; - - subgraph cluster_2 { - color=red - 4 [label="Enter function getAny" style="filled" fillcolor=red]; - 5 [label="Const: Null(null)"]; - 6 [label="Jump: ^getAny Null(null)"]; - 7 [label="Stub" style="filled" fillcolor=gray]; - 8 [label="Exit function getAny" style="filled" fillcolor=red]; - } - - 4 -> {5}; - 5 -> {6}; - 6 -> {8}; - 6 -> {7} [style=dotted]; - 7 -> {8} [style=dotted]; - - subgraph cluster_3 { - color=red - 9 [label="Enter function test_0" style="filled" fillcolor=red]; - 10 [label="Function call: R|/getAny|()"]; - 11 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 12 [label="Function call: R|/getAny|()"]; - 13 [label="Variable declaration: lval b: R|kotlin/Any?|"]; - 14 [label="Access variable R|/a|"]; - 15 [label="Type operator: a as A"]; - 16 [label="Access variable R|/a|"]; - 17 [label="Function call: R|/a|.R|/A.foo|()"]; - 18 [label="Access variable R|/b|"]; - 19 [label="Type operator: b as B"]; - 20 [label="Access variable R|/b|"]; - 21 [label="Function call: R|/b|.R|/B.foo|()"]; - 22 [label="Exit function test_0" style="filled" fillcolor=red]; - } - - 9 -> {10}; - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {14}; - 14 -> {15}; - 15 -> {16}; - 16 -> {17}; - 17 -> {18}; - 18 -> {19}; - 19 -> {20}; - 20 -> {21}; - 21 -> {22}; - - subgraph cluster_4 { - color=red - 23 [label="Enter function test_1" style="filled" fillcolor=red]; - 24 [label="Function call: R|/getAny|()"]; - 25 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 26 [label="Function call: R|/getAny|()"]; - 27 [label="Variable declaration: lval b: R|kotlin/Any?|"]; - subgraph cluster_5 { - color=blue - 28 [label="Enter when"]; - subgraph cluster_6 { - color=blue - 29 [label="Enter when branch condition "]; - subgraph cluster_7 { - color=blue - 30 [label="Enter &&"]; - 31 [label="Access variable R|/a|"]; - 32 [label="Type operator: a is A"]; - 33 [label="Exit left part of &&"]; - 34 [label="Enter right part of &&"]; - 35 [label="Access variable R|/b|"]; - 36 [label="Type operator: b is B"]; - 37 [label="Exit &&"]; - } - 38 [label="Exit when branch condition"]; - } - 39 [label="Synthetic else branch"]; - 40 [label="Enter when branch result"]; - subgraph cluster_8 { - color=blue - 41 [label="Enter block"]; - 42 [label="Access variable R|/a|"]; - 43 [label="Function call: R|/a|.R|/A.foo|()"]; - 44 [label="Access variable R|/b|"]; - 45 [label="Function call: R|/b|.R|/B.foo|()"]; - 46 [label="Exit block"]; - } - 47 [label="Exit when branch result"]; - 48 [label="Exit when"]; - } - 49 [label="Exit function test_1" style="filled" fillcolor=red]; - } - - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {30}; - 30 -> {31}; - 31 -> {32}; - 32 -> {33}; - 33 -> {37 34}; - 34 -> {35}; - 35 -> {36}; - 36 -> {37}; - 37 -> {38}; - 38 -> {40 39}; - 39 -> {48}; - 40 -> {41}; - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; - 44 -> {45}; - 45 -> {46}; - 46 -> {47}; - 47 -> {48}; - 48 -> {49}; - - subgraph cluster_9 { - color=red - 50 [label="Enter function " style="filled" fillcolor=red]; - 51 [label="Exit function " style="filled" fillcolor=red]; - } - - 50 -> {51}; - - subgraph cluster_10 { - color=red - 52 [label="Enter function getter" style="filled" fillcolor=red]; - 53 [label="Exit function getter" style="filled" fillcolor=red]; - } - - 52 -> {53}; - - subgraph cluster_11 { - color=red - 54 [label="Enter property" style="filled" fillcolor=red]; - 55 [label="Access variable R|/any|"]; - 56 [label="Exit property" style="filled" fillcolor=red]; - } - - 54 -> {55}; - 55 -> {56}; - - subgraph cluster_12 { - color=red - 57 [label="Enter function baz" style="filled" fillcolor=red]; - 58 [label="Exit function baz" style="filled" fillcolor=red]; - } - - 57 -> {58}; - - subgraph cluster_13 { - color=red - 59 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_14 { - color=blue - 60 [label="Enter when"]; - 61 [label="Access variable R|/d|"]; - 62 [label="Access variable R|/D.any|"]; - 63 [label="Variable declaration: lval : R|kotlin/Any?|"]; - subgraph cluster_15 { - color=blue - 64 [label="Enter when branch condition "]; - 65 [label="Const: Null(null)"]; - 66 [label="Operator =="]; - 67 [label="Exit when branch condition"]; - } - subgraph cluster_16 { - color=blue - 68 [label="Enter when branch condition else"]; - 69 [label="Exit when branch condition"]; - } - 70 [label="Enter when branch result"]; - subgraph cluster_17 { - color=blue - 71 [label="Enter block"]; - 72 [label="Access variable R|/|"]; - 73 [label="Exit block"]; - } - 74 [label="Exit when branch result"]; - 75 [label="Enter when branch result"]; - subgraph cluster_18 { - color=blue - 76 [label="Enter block"]; - 77 [label="Jump: ^test_2 Unit"]; - 78 [label="Stub" style="filled" fillcolor=gray]; - 79 [label="Exit block" style="filled" fillcolor=gray]; - } - 80 [label="Exit when branch result" style="filled" fillcolor=gray]; - 81 [label="Exit when"]; - } - 82 [label="Variable declaration: lval a: R|kotlin/Any|"]; - 83 [label="Access variable R|/a|"]; - 84 [label="Function call: R|/a|.R|/baz|()"]; - 85 [label="Access variable R|/d|"]; - 86 [label="Access variable R|/D.any|"]; - 87 [label="Function call: R|/d|.R|/D.any|.R|/baz|()"]; - 88 [label="Access variable R|/a|"]; - 89 [label="Type operator: a as A"]; - 90 [label="Access variable R|/a|"]; - 91 [label="Function call: R|/a|.R|/A.foo|()"]; - 92 [label="Exit function test_2" style="filled" fillcolor=red]; - } - - 59 -> {60}; - 60 -> {61}; - 61 -> {62}; - 62 -> {63}; - 63 -> {64}; - 64 -> {65}; - 65 -> {66}; - 66 -> {67}; - 67 -> {75 68}; - 68 -> {69}; - 69 -> {70}; - 70 -> {71}; - 71 -> {72}; - 72 -> {73}; - 73 -> {74}; - 74 -> {81}; - 75 -> {76}; - 76 -> {77}; - 77 -> {92}; - 77 -> {78} [style=dotted]; - 78 -> {79} [style=dotted]; - 79 -> {80} [style=dotted]; - 80 -> {81} [style=dotted]; - 81 -> {82}; - 82 -> {83}; - 83 -> {84}; - 84 -> {85}; - 85 -> {86}; - 86 -> {87}; - 87 -> {88}; - 88 -> {89}; - 89 -> {90}; - 90 -> {91}; - 91 -> {92}; - - subgraph cluster_19 { - color=red - 93 [label="Enter function test_3" style="filled" fillcolor=red]; - 94 [label="Access variable R|/d1|"]; - 95 [label="Access variable R|/D.any|"]; - 96 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 97 [label="Access variable R|/a|"]; - 98 [label="Type operator: a as A"]; - 99 [label="Access variable R|/a|"]; - 100 [label="Function call: R|/a|.R|/A.foo|()"]; - 101 [label="Access variable R|/d1|"]; - 102 [label="Access variable R|/D.any|"]; - 103 [label="Function call: R|/d1|.R|/D.any|.R|/A.foo|()"]; - 104 [label="Access variable R|/d1|"]; - 105 [label="Access variable R|/D.any|"]; - 106 [label="Function call: R|/d1|.R|/D.any|.R|/baz|()"]; - 107 [label="Exit function test_3" style="filled" fillcolor=red]; - } - - 93 -> {94}; - 94 -> {95}; - 95 -> {96}; - 96 -> {97}; - 97 -> {98}; - 98 -> {99}; - 99 -> {100}; - 100 -> {101}; - 101 -> {102}; - 102 -> {103}; - 103 -> {104}; - 104 -> {105}; - 105 -> {106}; - 106 -> {107}; - - subgraph cluster_20 { - color=red - 108 [label="Enter function test_4" style="filled" fillcolor=red]; - 109 [label="Access variable R|/d1|"]; - 110 [label="Enter safe call"]; - 111 [label="Access variable R|/D.any|"]; - 112 [label="Exit safe call"]; - 113 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 114 [label="Access variable R|/d2|"]; - 115 [label="Enter safe call"]; - 116 [label="Access variable R|/D.any|"]; - 117 [label="Exit safe call"]; - 118 [label="Variable declaration: lval b: R|kotlin/Any?|"]; - 119 [label="Access variable R|/a|"]; - 120 [label="Type operator: a as A"]; - 121 [label="Access variable R|/a|"]; - 122 [label="Function call: R|/a|.R|/A.foo|()"]; - 123 [label="Access variable R|/b|"]; - 124 [label="Type operator: b as B"]; - 125 [label="Access variable R|/b|"]; - 126 [label="Function call: R|/b|.R|/B.foo|()"]; - 127 [label="Exit function test_4" style="filled" fillcolor=red]; - } - - 108 -> {109}; - 109 -> {110 112}; - 110 -> {111}; - 111 -> {112}; - 112 -> {113}; - 113 -> {114}; - 114 -> {115 117}; - 115 -> {116}; - 116 -> {117}; - 117 -> {118}; - 118 -> {119}; - 119 -> {120}; - 120 -> {121}; - 121 -> {122}; - 122 -> {123}; - 123 -> {124}; - 124 -> {125}; - 125 -> {126}; - 126 -> {127}; - -} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.txt b/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.txt deleted file mode 100644 index b722bb9a361..00000000000 --- a/compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.txt +++ /dev/null @@ -1,72 +0,0 @@ -FILE: notBoundSmartcasts.kt - public abstract interface A : R|kotlin/Any| { - public abstract fun foo(): R|kotlin/Int| - - } - public abstract interface B : R|kotlin/Any| { - public abstract fun foo(): R|kotlin/Int| - - } - public final fun getAny(): R|kotlin/Any?| { - ^getAny Null(null) - } - public final fun test_0(): R|kotlin/Unit| { - lval a: R|kotlin/Any?| = R|/getAny|() - lval b: R|kotlin/Any?| = R|/getAny|() - (R|/a| as R|A|) - R|/a|.R|/A.foo|() - (R|/b| as R|B|) - R|/b|.R|/B.foo|() - } - public final fun test_1(): R|kotlin/Unit| { - lval a: R|kotlin/Any?| = R|/getAny|() - lval b: R|kotlin/Any?| = R|/getAny|() - when () { - (R|/a| is R|A|) && (R|/b| is R|B|) -> { - R|/a|.R|/A.foo|() - R|/b|.R|/B.foo|() - } - } - - } - public final class D : R|kotlin/Any| { - public constructor(any: R|kotlin/Any?|): R|D| { - super() - } - - public final val any: R|kotlin/Any?| = R|/any| - public get(): R|kotlin/Any?| - - } - public final fun R|kotlin/Any|.baz(): R|kotlin/Unit| { - } - public final fun test_2(d: R|D|): R|kotlin/Unit| { - lval a: R|kotlin/Any| = when (lval : R|kotlin/Any?| = R|/d|.R|/D.any|) { - ==($subj$, Null(null)) -> { - ^test_2 Unit - } - else -> { - R|/| - } - } - - R|/a|.R|/baz|() - R|/d|.R|/D.any|.R|/baz|() - (R|/a| as R|A|) - R|/a|.R|/A.foo|() - } - public final fun test_3(d1: R|D|): R|kotlin/Unit| { - lval a: R|kotlin/Any?| = R|/d1|.R|/D.any| - (R|/a| as R|A|) - R|/a|.R|/A.foo|() - R|/d1|.R|/D.any|.R|/A.foo|() - R|/d1|.R|/D.any|.R|/baz|() - } - public final fun test_4(d1: R|D|, d2: R|D|): R|kotlin/Unit| { - lval a: R|kotlin/Any?| = R|/d1|?.R|/D.any| - lval b: R|kotlin/Any?| = R|/d2|?.R|/D.any| - (R|/a| as R|A|) - R|/a|.R|/A.foo|() - (R|/b| as R|B|) - R|/b|.R|/B.foo|() - } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.dot b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.dot new file mode 100644 index 00000000000..56cd099fca5 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.dot @@ -0,0 +1,59 @@ +digraph smartcastOnBangBang_kt { + graph [splines=ortho nodesep=3] + node [shape=box penwidth=2] + edge [penwidth=2] + + subgraph cluster_0 { + color=red + 0 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_1 { + color=blue + 1 [label="Enter when"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter when branch condition "]; + 3 [label="Access variable R|/a|"]; + 4 [label="Type operator: a is String?"]; + 5 [label="Exit when branch condition"]; + } + 6 [label="Synthetic else branch"]; + 7 [label="Enter when branch result"]; + subgraph cluster_3 { + color=blue + 8 [label="Enter block"]; + 9 [label="Access variable R|/a|"]; + 10 [label="Check not null: R|/a|!!"]; + 11 [label="Function call: #(R|/a|!!)"]; + 12 [label="Exit block"]; + } + 13 [label="Exit when branch result"]; + 14 [label="Exit when"]; + } + 15 [label="Exit function test_1" style="filled" fillcolor=red]; + } + + 0 -> {1}; + 1 -> {2}; + 2 -> {3}; + 3 -> {4}; + 4 -> {5}; + 5 -> {7 6}; + 6 -> {14}; + 7 -> {8}; + 8 -> {9}; + 9 -> {10}; + 10 -> {11}; + 11 -> {12}; + 12 -> {13}; + 13 -> {14}; + 14 -> {15}; + + subgraph cluster_4 { + color=red + 16 [label="Enter function takeString" style="filled" fillcolor=red]; + 17 [label="Exit function takeString" style="filled" fillcolor=red]; + } + + 16 -> {17}; + +} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt new file mode 100644 index 00000000000..7cac4f782de --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt @@ -0,0 +1,7 @@ +fun test_1(a: X) { + if (a is String?) { + takeString(a!!) + } +} + +fun takeString(s: String) {} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.txt b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.txt new file mode 100644 index 00000000000..e5bd22f0345 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.txt @@ -0,0 +1,11 @@ +FILE: smartcastOnBangBang.kt + public final fun test_1(a: R|X|): R|kotlin/Unit| { + when () { + (R|/a| is R|kotlin/String?|) -> { + #(R|/a|!!) + } + } + + } + public final fun takeString(s: R|kotlin/String|): R|kotlin/Unit| { + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.dot b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.kt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.txt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.dot b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.kt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.txt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.dot b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.kt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.txt b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.dot b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot similarity index 99% rename from compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot index a1952a3cfbb..98bbe530082 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot @@ -1,4 +1,4 @@ -digraph anotherBoundSmartcasts_kt { +digraph assignSafeCall_kt { graph [splines=ortho nodesep=3] node [shape=box penwidth=2] edge [penwidth=2] diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.kt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.txt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt similarity index 98% rename from compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt index 03dbb21d101..2aa4fdd92c1 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt @@ -1,4 +1,4 @@ -FILE: anotherBoundSmartcasts.kt +FILE: assignSafeCall.kt public final class A : R|kotlin/Any| { public constructor(): R|A| { super() diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.dot b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.dot new file mode 100644 index 00000000000..592070762c3 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.dot @@ -0,0 +1,290 @@ +digraph safeCallAndEqualityToBool_kt { + graph [splines=ortho nodesep=3] + node [shape=box penwidth=2] + edge [penwidth=2] + + subgraph cluster_0 { + color=red + 0 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_1 { + color=blue + 1 [label="Enter when"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter when branch condition "]; + 3 [label="Access variable R|/s|"]; + 4 [label="Enter safe call"]; + 5 [label="Function call: R|/s|?.R|kotlin/text/isNotEmpty|()"]; + 6 [label="Exit safe call"]; + 7 [label="Const: Boolean(true)"]; + 8 [label="Operator =="]; + 9 [label="Exit when branch condition"]; + } + subgraph cluster_3 { + color=blue + 10 [label="Enter when branch condition else"]; + 11 [label="Exit when branch condition"]; + } + 12 [label="Enter when branch result"]; + subgraph cluster_4 { + color=blue + 13 [label="Enter block"]; + 14 [label="Access variable R|/s|"]; + 15 [label="Access variable #"]; + 16 [label="Exit block"]; + } + 17 [label="Exit when branch result"]; + 18 [label="Enter when branch result"]; + subgraph cluster_5 { + color=blue + 19 [label="Enter block"]; + 20 [label="Access variable R|/s|"]; + 21 [label="Access variable R|kotlin/String.length|"]; + 22 [label="Exit block"]; + } + 23 [label="Exit when branch result"]; + 24 [label="Exit when"]; + } + 25 [label="Exit function test_1" style="filled" fillcolor=red]; + } + + 0 -> {1}; + 1 -> {2}; + 2 -> {3}; + 3 -> {4 6}; + 4 -> {5}; + 5 -> {6}; + 6 -> {7}; + 7 -> {8}; + 8 -> {9}; + 9 -> {18 10}; + 10 -> {11}; + 11 -> {12}; + 12 -> {13}; + 13 -> {14}; + 14 -> {15}; + 15 -> {16}; + 16 -> {17}; + 17 -> {24}; + 18 -> {19}; + 19 -> {20}; + 20 -> {21}; + 21 -> {22}; + 22 -> {23}; + 23 -> {24}; + 24 -> {25}; + + subgraph cluster_6 { + color=red + 26 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_7 { + color=blue + 27 [label="Enter when"]; + subgraph cluster_8 { + color=blue + 28 [label="Enter when branch condition "]; + 29 [label="Access variable R|/s|"]; + 30 [label="Enter safe call"]; + 31 [label="Function call: R|/s|?.R|kotlin/text/isNotEmpty|()"]; + 32 [label="Exit safe call"]; + 33 [label="Const: Boolean(false)"]; + 34 [label="Operator =="]; + 35 [label="Exit when branch condition"]; + } + subgraph cluster_9 { + color=blue + 36 [label="Enter when branch condition else"]; + 37 [label="Exit when branch condition"]; + } + 38 [label="Enter when branch result"]; + subgraph cluster_10 { + color=blue + 39 [label="Enter block"]; + 40 [label="Access variable R|/s|"]; + 41 [label="Access variable #"]; + 42 [label="Exit block"]; + } + 43 [label="Exit when branch result"]; + 44 [label="Enter when branch result"]; + subgraph cluster_11 { + color=blue + 45 [label="Enter block"]; + 46 [label="Access variable R|/s|"]; + 47 [label="Access variable R|kotlin/String.length|"]; + 48 [label="Exit block"]; + } + 49 [label="Exit when branch result"]; + 50 [label="Exit when"]; + } + 51 [label="Exit function test_2" style="filled" fillcolor=red]; + } + + 26 -> {27}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30 32}; + 30 -> {31}; + 31 -> {32}; + 32 -> {33}; + 33 -> {34}; + 34 -> {35}; + 35 -> {44 36}; + 36 -> {37}; + 37 -> {38}; + 38 -> {39}; + 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; + 43 -> {50}; + 44 -> {45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50}; + 50 -> {51}; + + subgraph cluster_12 { + color=red + 52 [label="Enter function test_3" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 53 [label="Enter when"]; + subgraph cluster_14 { + color=blue + 54 [label="Enter when branch condition "]; + 55 [label="Access variable R|/s|"]; + 56 [label="Enter safe call"]; + 57 [label="Function call: R|/s|?.R|kotlin/text/isNotEmpty|()"]; + 58 [label="Exit safe call"]; + 59 [label="Const: Boolean(true)"]; + 60 [label="Operator !="]; + 61 [label="Exit when branch condition"]; + } + subgraph cluster_15 { + color=blue + 62 [label="Enter when branch condition else"]; + 63 [label="Exit when branch condition"]; + } + 64 [label="Enter when branch result"]; + subgraph cluster_16 { + color=blue + 65 [label="Enter block"]; + 66 [label="Access variable R|/s|"]; + 67 [label="Access variable R|kotlin/String.length|"]; + 68 [label="Exit block"]; + } + 69 [label="Exit when branch result"]; + 70 [label="Enter when branch result"]; + subgraph cluster_17 { + color=blue + 71 [label="Enter block"]; + 72 [label="Access variable R|/s|"]; + 73 [label="Access variable #"]; + 74 [label="Exit block"]; + } + 75 [label="Exit when branch result"]; + 76 [label="Exit when"]; + } + 77 [label="Exit function test_3" style="filled" fillcolor=red]; + } + + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 55 -> {56 58}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {70 62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; + 65 -> {66}; + 66 -> {67}; + 67 -> {68}; + 68 -> {69}; + 69 -> {76}; + 70 -> {71}; + 71 -> {72}; + 72 -> {73}; + 73 -> {74}; + 74 -> {75}; + 75 -> {76}; + 76 -> {77}; + + subgraph cluster_18 { + color=red + 78 [label="Enter function test_4" style="filled" fillcolor=red]; + subgraph cluster_19 { + color=blue + 79 [label="Enter when"]; + subgraph cluster_20 { + color=blue + 80 [label="Enter when branch condition "]; + 81 [label="Access variable R|/s|"]; + 82 [label="Enter safe call"]; + 83 [label="Function call: R|/s|?.R|kotlin/text/isNotEmpty|()"]; + 84 [label="Exit safe call"]; + 85 [label="Const: Boolean(false)"]; + 86 [label="Operator !="]; + 87 [label="Exit when branch condition"]; + } + subgraph cluster_21 { + color=blue + 88 [label="Enter when branch condition else"]; + 89 [label="Exit when branch condition"]; + } + 90 [label="Enter when branch result"]; + subgraph cluster_22 { + color=blue + 91 [label="Enter block"]; + 92 [label="Access variable R|/s|"]; + 93 [label="Access variable R|kotlin/String.length|"]; + 94 [label="Exit block"]; + } + 95 [label="Exit when branch result"]; + 96 [label="Enter when branch result"]; + subgraph cluster_23 { + color=blue + 97 [label="Enter block"]; + 98 [label="Access variable R|/s|"]; + 99 [label="Access variable #"]; + 100 [label="Exit block"]; + } + 101 [label="Exit when branch result"]; + 102 [label="Exit when"]; + } + 103 [label="Exit function test_4" style="filled" fillcolor=red]; + } + + 78 -> {79}; + 79 -> {80}; + 80 -> {81}; + 81 -> {82 84}; + 82 -> {83}; + 83 -> {84}; + 84 -> {85}; + 85 -> {86}; + 86 -> {87}; + 87 -> {96 88}; + 88 -> {89}; + 89 -> {90}; + 90 -> {91}; + 91 -> {92}; + 92 -> {93}; + 93 -> {94}; + 94 -> {95}; + 95 -> {102}; + 96 -> {97}; + 97 -> {98}; + 98 -> {99}; + 99 -> {100}; + 100 -> {101}; + 101 -> {102}; + 102 -> {103}; + +} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt new file mode 100644 index 00000000000..247fbaadf63 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt @@ -0,0 +1,31 @@ +fun test_1(s: String?) { + if (s?.isNotEmpty() == true) { + s.length // Should be OK + } else { + s.length // Should be bad + } +} + +fun test_2(s: String?) { + if (s?.isNotEmpty() == false) { + s.length // Should be OK + } else { + s.length // Should be bad + } +} + +fun test_3(s: String?) { + if (s?.isNotEmpty() != true) { + s.length // Should be bad + } else { + s.length // Should be OK + } +} + +fun test_4(s: String?) { + if (s?.isNotEmpty() != false) { + s.length // Should be bad + } else { + s.length // Should be OK + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.txt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.txt new file mode 100644 index 00000000000..3c85c6e1d67 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.txt @@ -0,0 +1,45 @@ +FILE: safeCallAndEqualityToBool.kt + public final fun test_1(s: R|kotlin/String?|): R|kotlin/Unit| { + when () { + ==(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(true)) -> { + R|/s|.R|kotlin/String.length| + } + else -> { + R|/s|.# + } + } + + } + public final fun test_2(s: R|kotlin/String?|): R|kotlin/Unit| { + when () { + ==(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(false)) -> { + R|/s|.R|kotlin/String.length| + } + else -> { + R|/s|.# + } + } + + } + public final fun test_3(s: R|kotlin/String?|): R|kotlin/Unit| { + when () { + !=(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(true)) -> { + R|/s|.# + } + else -> { + R|/s|.R|kotlin/String.length| + } + } + + } + public final fun test_4(s: R|kotlin/String?|): R|kotlin/Unit| { + when () { + !=(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(false)) -> { + R|/s|.# + } + else -> { + R|/s|.R|kotlin/String.length| + } + } + + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.dot b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.kt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.txt b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.dot b/compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.kt b/compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.txt b/compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.dot b/compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.kt b/compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.txt b/compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.txt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.dot b/compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.dot similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.dot rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.dot diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.kt b/compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.kt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.kt rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.kt diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.txt b/compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.txt similarity index 100% rename from compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.txt rename to compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.txt diff --git a/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.kt b/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.kt index 769a21a8b29..feeb5f29c34 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.kt +++ b/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.kt @@ -1,71 +1,31 @@ -fun runHigherOrder(f: () -> T): T = f() - -val String.ext: Int get() = length - -fun foo(a: Any?) { - val s = a as? String - val length = s?.ext ?: return - runHigherOrder { - s.isNotEmpty() - } -} - -fun bar(s: String?) { - if (s?.isNotEmpty() == true) { - s.length - } else { - s.length - } -} - -fun bar_2(s: String?) { - if (s?.isNotEmpty() == false) { - s.length - } else { - s.length - } -} - -fun bar_3(s: String?) { - if (s?.isNotEmpty() != true) { - s.length - } else { - s.length - } -} - -fun bar_4(s: String?) { - if (s?.isNotEmpty() != false) { - s.length - } else { - s.length - } -} - -fun baz(s: String?) { +fun test_1(s: String?) { + // contracts related when { - !s.isNullOrEmpty() -> s.length + !s.isNullOrEmpty() -> s.length // Should be OK } } -fun bazz(s: String?) { - s?.let { use(it) } +fun test_2(s: String?) { + s?.let { + takeString(it) // Should be OK + takeString(s) // Should be OK + } } class Wrapper(val s: String?) { fun withThis() { if (s != null) { - use(this.s) + takeString(this.s) // Should be OK } if (this.s != null) { - use(s) + takeString(s) // Should be OK } } } fun Any.withInvoke(f: String.() -> Unit) { if (this is String) { - f() + f() // Should be OK } } @@ -73,11 +33,5 @@ fun String.withInvoke(f: String.() -> Unit) { f() } -fun withBangBang(a: X) { - if (a is String?) { - use(a!!) - } -} - -fun use(s: String) {} +fun takeString(s: String) {} diff --git a/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.txt b/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.txt index 993376163fd..326bda59e4d 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/problems/complexSmartCasts.txt @@ -1,72 +1,5 @@ FILE: complexSmartCasts.kt - public final fun runHigherOrder(f: R|() -> T|): R|T| { - ^runHigherOrder R|/f|.R|FakeOverride|() - } - public final val R|kotlin/String|.ext: R|kotlin/Int| - public get(): R|kotlin/Int| { - ^ this@R|/ext|.R|kotlin/String.length| - } - public final fun foo(a: R|kotlin/Any?|): R|kotlin/Unit| { - lval s: R|kotlin/String?| = (R|/a| as? R|kotlin/String|) - lval length: R|kotlin/Int| = when (lval : R|kotlin/Int?| = R|/s|?.R|/ext|) { - ==($subj$, Null(null)) -> { - ^foo Unit - } - else -> { - R|/| - } - } - - R|/runHigherOrder|( = runHigherOrder@fun (): R|kotlin/Boolean| { - ^ R|/s|.R|kotlin/text/isNotEmpty|() - } - ) - } - public final fun bar(s: R|kotlin/String?|): R|kotlin/Unit| { - when () { - ==(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(true)) -> { - R|/s|.R|kotlin/String.length| - } - else -> { - R|/s|.# - } - } - - } - public final fun bar_2(s: R|kotlin/String?|): R|kotlin/Unit| { - when () { - ==(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(false)) -> { - R|/s|.R|kotlin/String.length| - } - else -> { - R|/s|.# - } - } - - } - public final fun bar_3(s: R|kotlin/String?|): R|kotlin/Unit| { - when () { - !=(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(true)) -> { - R|/s|.# - } - else -> { - R|/s|.R|kotlin/String.length| - } - } - - } - public final fun bar_4(s: R|kotlin/String?|): R|kotlin/Unit| { - when () { - !=(R|/s|?.R|kotlin/text/isNotEmpty|(), Boolean(false)) -> { - R|/s|.# - } - else -> { - R|/s|.R|kotlin/String.length| - } - } - - } - public final fun baz(s: R|kotlin/String?|): R|kotlin/Unit| { + public final fun test_1(s: R|kotlin/String?|): R|kotlin/Unit| { when () { R|/s|.R|kotlin/text/isNullOrEmpty|().R|kotlin/Boolean.not|() -> { R|/s|.# @@ -74,9 +7,10 @@ FILE: complexSmartCasts.kt } } - public final fun bazz(s: R|kotlin/String?|): R|kotlin/Unit| { + public final fun test_2(s: R|kotlin/String?|): R|kotlin/Unit| { R|/s|?.R|kotlin/let|( = let@fun (it: R|kotlin/String|): R|kotlin/Unit| { - R|/use|(R|/it|) + R|/takeString|(R|/it|) + R|/takeString|(R|/s|) } ) } @@ -91,13 +25,13 @@ FILE: complexSmartCasts.kt public final fun withThis(): R|kotlin/Unit| { when () { !=(this@R|/Wrapper|.R|/Wrapper.s|, Null(null)) -> { - R|/use|(this@R|/Wrapper|.R|/Wrapper.s|) + R|/takeString|(this@R|/Wrapper|.R|/Wrapper.s|) } } when () { !=(this@R|/Wrapper|.R|/Wrapper.s|, Null(null)) -> { - R|/use|(this@R|/Wrapper|.R|/Wrapper.s|) + R|/takeString|(this@R|/Wrapper|.R|/Wrapper.s|) } } @@ -115,13 +49,5 @@ FILE: complexSmartCasts.kt public final fun R|kotlin/String|.withInvoke(f: R|kotlin/String.() -> kotlin/Unit|): R|kotlin/Unit| { R|/f|.R|FakeOverride|(this@R|/withInvoke|) } - public final fun withBangBang(a: R|X|): R|kotlin/Unit| { - when () { - (R|/a| is R|kotlin/String?|) -> { - #(R|/a|!!) - } - } - - } - public final fun use(s: R|kotlin/String|): R|kotlin/Unit| { + public final fun takeString(s: R|kotlin/String|): R|kotlin/Unit| { } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithCfgTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithCfgTestGenerated.java index 092702abf78..bc8c11194ed 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithCfgTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithCfgTestGenerated.java @@ -123,84 +123,24 @@ public class FirDiagnosticsWithCfgTestGenerated extends AbstractFirDiagnosticsWi KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } - @TestMetadata("anotherBoundSmartcasts.kt") - public void testAnotherBoundSmartcasts() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/anotherBoundSmartcasts.kt"); - } - @TestMetadata("bangbang.kt") public void testBangbang() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/bangbang.kt"); } - @TestMetadata("booleanOperators.kt") - public void testBooleanOperators() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt"); - } - - @TestMetadata("boundSmartcasts.kt") - public void testBoundSmartcasts() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts.kt"); - } - - @TestMetadata("boundSmartcastsInBranches.kt") - public void testBoundSmartcastsInBranches() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcastsInBranches.kt"); - } - @TestMetadata("casts.kt") public void testCasts() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/casts.kt"); } - @TestMetadata("dataFlowInfoFromWhileCondition.kt") - public void testDataFlowInfoFromWhileCondition() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/dataFlowInfoFromWhileCondition.kt"); - } - - @TestMetadata("delayedAssignment.kt") - public void testDelayedAssignment() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/delayedAssignment.kt"); - } - - @TestMetadata("elvis.kt") - public void testElvis() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/elvis.kt"); - } - - @TestMetadata("endlessLoops.kt") - public void testEndlessLoops() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/endlessLoops.kt"); - } - @TestMetadata("equalsAndIdentity.kt") public void testEqualsAndIdentity() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/equalsAndIdentity.kt"); } - @TestMetadata("equalsToBoolean.kt") - public void testEqualsToBoolean() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/equalsToBoolean.kt"); - } - - @TestMetadata("implicitReceiverAsWhenSubject.kt") - public void testImplicitReceiverAsWhenSubject() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/implicitReceiverAsWhenSubject.kt"); - } - - @TestMetadata("implicitReceivers.kt") - public void testImplicitReceivers() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/implicitReceivers.kt"); - } - - @TestMetadata("inPlaceLambdas.kt") - public void testInPlaceLambdas() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/inPlaceLambdas.kt"); - } - - @TestMetadata("notBoundSmartcasts.kt") - public void testNotBoundSmartcasts() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/notBoundSmartcasts.kt"); + @TestMetadata("multipleCasts.kt") + public void testMultipleCasts() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/multipleCasts.kt"); } @TestMetadata("nullability.kt") @@ -208,59 +148,259 @@ public class FirDiagnosticsWithCfgTestGenerated extends AbstractFirDiagnosticsWi runTest("compiler/fir/resolve/testData/resolve/smartcasts/nullability.kt"); } - @TestMetadata("overridenOpenVal.kt") - public void testOverridenOpenVal() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/overridenOpenVal.kt"); - } - - @TestMetadata("returns.kt") - public void testReturns() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/returns.kt"); - } - - @TestMetadata("safeCalls.kt") - public void testSafeCalls() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls.kt"); - } - - @TestMetadata("simpleIf.kt") - public void testSimpleIf() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.kt"); - } - @TestMetadata("smartCastInInit.kt") public void testSmartCastInInit() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartCastInInit.kt"); } - @TestMetadata("smartcastAfterReassignment.kt") - public void testSmartcastAfterReassignment() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartcastAfterReassignment.kt"); - } - - @TestMetadata("smartcastFromArgument.kt") - public void testSmartcastFromArgument() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartcastFromArgument.kt"); - } - - @TestMetadata("smartcastOnLambda.kt") - public void testSmartcastOnLambda() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartcastOnLambda.kt"); - } - @TestMetadata("smartcastToNothing.kt") public void testSmartcastToNothing() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartcastToNothing.kt"); } - @TestMetadata("thisOfExtensionProperty.kt") - public void testThisOfExtensionProperty() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/thisOfExtensionProperty.kt"); + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/booleans") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Booleans extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInBooleans() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/booleans"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("booleanOperators.kt") + public void testBooleanOperators() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/booleans/booleanOperators.kt"); + } + + @TestMetadata("equalsToBoolean.kt") + public void testEqualsToBoolean() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/booleans/equalsToBoolean.kt"); + } } - @TestMetadata("when.kt") - public void testWhen() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/smartcasts/when.kt"); + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class BoundSmartcasts extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInBoundSmartcasts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("boundSmartcasts.kt") + public void testBoundSmartcasts() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.kt"); + } + + @TestMetadata("boundSmartcastsInBranches.kt") + public void testBoundSmartcastsInBranches() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ControlStructures extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInControlStructures() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("elvis.kt") + public void testElvis() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/elvis.kt"); + } + + @TestMetadata("returns.kt") + public void testReturns() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/returns.kt"); + } + + @TestMetadata("simpleIf.kt") + public void testSimpleIf() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/simpleIf.kt"); + } + + @TestMetadata("smartcastFromArgument.kt") + public void testSmartcastFromArgument() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.kt"); + } + + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/controlStructures/when.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/lambdas") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Lambdas extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInLambdas() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/lambdas"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("inPlaceLambdas.kt") + public void testInPlaceLambdas() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt"); + } + + @TestMetadata("smartcastOnLambda.kt") + public void testSmartcastOnLambda() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/lambdas/smartcastOnLambda.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/loops") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Loops extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInLoops() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/loops"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("dataFlowInfoFromWhileCondition.kt") + public void testDataFlowInfoFromWhileCondition() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.kt"); + } + + @TestMetadata("endlessLoops.kt") + public void testEndlessLoops() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/loops/endlessLoops.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/problems") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Problems extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInProblems() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("smartcastOnBangBang.kt") + public void testSmartcastOnBangBang() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/receivers") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Receivers extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInReceivers() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/receivers"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("implicitReceiverAsWhenSubject.kt") + public void testImplicitReceiverAsWhenSubject() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceiverAsWhenSubject.kt"); + } + + @TestMetadata("implicitReceivers.kt") + public void testImplicitReceivers() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.kt"); + } + + @TestMetadata("thisOfExtensionProperty.kt") + public void testThisOfExtensionProperty() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/receivers/thisOfExtensionProperty.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SafeCalls extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSafeCalls() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("assignSafeCall.kt") + public void testAssignSafeCall() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/assignSafeCall.kt"); + } + + @TestMetadata("safeCallAndEqualityToBool.kt") + public void testSafeCallAndEqualityToBool() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt"); + } + + @TestMetadata("safeCalls.kt") + public void testSafeCalls() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/stability") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Stability extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInStability() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/stability"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("overridenOpenVal.kt") + public void testOverridenOpenVal() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/stability/overridenOpenVal.kt"); + } + } + + @TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/variables") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Variables extends AbstractFirDiagnosticsWithCfgTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInVariables() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/variables"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("delayedAssignment.kt") + public void testDelayedAssignment() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/variables/delayedAssignment.kt"); + } + + @TestMetadata("smartcastAfterReassignment.kt") + public void testSmartcastAfterReassignment() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/variables/smartcastAfterReassignment.kt"); + } } } }