diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt index 9a6d6cebc34..e0ff9d0cebd 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt @@ -36,7 +36,7 @@ internal class KtFirSymbolProvider( psi = psi, ) - psi.isLoopParameter -> { + psi.isLoopParameter || psi.isCatchParameter -> { firSymbolBuilder.variableLikeBuilder.buildLocalVariableSymbol( psi.resolveToFirSymbolOfType(firResolveSession) ) diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/expressions/tryExpression.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/expressions/tryExpression.txt index 29d8c22ae19..d8766d2b577 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/expressions/tryExpression.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/expressions/tryExpression.txt @@ -9,4 +9,4 @@ try { catch (e: R|kotlin/Throwable|) { } finally { -} +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/catchParameter.fir.txt b/compiler/fir/analysis-tests/testData/resolve/catchParameter.fir.txt index 5041043b1c8..21dfc856a06 100644 --- a/compiler/fir/analysis-tests/testData/resolve/catchParameter.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/catchParameter.fir.txt @@ -3,7 +3,7 @@ FILE: catchParameter.kt public final fun test(): R|kotlin/Unit| { try { } - catch (e: R|kotlin/NullPointerException| = R|java/lang/NullPointerException.NullPointerException|()) { + catch (e: R|kotlin/NullPointerException|) { } try { @@ -23,7 +23,7 @@ FILE: catchParameter.kt try { } - catch (e: R|kotlin/Int| = Int(5)) { + catch (e: R|kotlin/Int|) { } try { diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot index 76d56b33386..4a4323b57a3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot @@ -68,40 +68,41 @@ digraph complex_kt { subgraph cluster_12 { color=blue 27 [label="Catch enter"]; + 28 [label="Variable declaration: closeException: R|kotlin/Throwable|"]; subgraph cluster_13 { color=blue - 28 [label="Enter block"]; - 29 [label="Access variable R|/cause|"]; - 30 [label="Smart cast: R|/cause|"]; - 31 [label="Access variable R|/closeException|"]; - 32 [label="Function call: R|/cause|.R|kotlin/Throwable.addSuppressed|(...)"]; - 33 [label="Exit block"]; + 29 [label="Enter block"]; + 30 [label="Access variable R|/cause|"]; + 31 [label="Smart cast: R|/cause|"]; + 32 [label="Access variable R|/closeException|"]; + 33 [label="Function call: R|/cause|.R|kotlin/Throwable.addSuppressed|(...)"]; + 34 [label="Exit block"]; } - 34 [label="Catch exit"]; + 35 [label="Catch exit"]; } - 35 [label="Try expression exit"]; + 36 [label="Try expression exit"]; } - 36 [label="Exit block"]; + 37 [label="Exit block"]; } - 37 [label="Exit when branch result"]; - 38 [label="Enter when branch result"]; + 38 [label="Exit when branch result"]; + 39 [label="Enter when branch result"]; subgraph cluster_14 { color=blue - 39 [label="Enter block"]; - 40 [label="Function call: this@R|/closeFinally|.R|/AutoCloseable.close|()"]; - 41 [label="Exit block"]; + 40 [label="Enter block"]; + 41 [label="Function call: this@R|/closeFinally|.R|/AutoCloseable.close|()"]; + 42 [label="Exit block"]; } - 42 [label="Exit when branch result"]; - 43 [label="Enter when branch result"]; + 43 [label="Exit when branch result"]; + 44 [label="Enter when branch result"]; subgraph cluster_15 { color=blue - 44 [label="Enter block"]; - 45 [label="Exit block"]; + 45 [label="Enter block"]; + 46 [label="Exit block"]; } - 46 [label="Exit when branch result"]; - 47 [label="Exit when"]; + 47 [label="Exit when branch result"]; + 48 [label="Exit when"]; } - 48 [label="Jump: ^closeFinally when () { + 49 [label="Jump: ^closeFinally when () { ==(this@R|/closeFinally|, Null(null)) -> { } ==(R|/cause|, Null(null)) -> { @@ -118,10 +119,10 @@ digraph complex_kt { } } "]; - 49 [label="Stub" style="filled" fillcolor=gray]; - 50 [label="Exit block" style="filled" fillcolor=gray]; + 50 [label="Stub" style="filled" fillcolor=gray]; + 51 [label="Exit block" style="filled" fillcolor=gray]; } - 51 [label="Exit function closeFinally" style="filled" fillcolor=red]; + 52 [label="Exit function closeFinally" style="filled" fillcolor=red]; } 4 -> {5}; 5 -> {6}; @@ -130,12 +131,12 @@ digraph complex_kt { 8 -> {9}; 9 -> {10}; 10 -> {11}; - 11 -> {43 12}; + 11 -> {44 12}; 12 -> {13}; 13 -> {14}; 14 -> {15}; 15 -> {16}; - 16 -> {38 17}; + 16 -> {39 17}; 17 -> {18}; 18 -> {19}; 19 -> {20}; @@ -145,9 +146,9 @@ digraph complex_kt { 23 -> {24}; 24 -> {25}; 25 -> {26}; - 26 -> {35 27}; + 26 -> {36 27}; 27 -> {28}; - 27 -> {51} [label=onUncaughtException]; + 27 -> {52} [label=onUncaughtException]; 28 -> {29}; 29 -> {30}; 30 -> {31}; @@ -157,93 +158,93 @@ digraph complex_kt { 34 -> {35}; 35 -> {36}; 36 -> {37}; - 37 -> {47}; - 38 -> {39}; + 37 -> {38}; + 38 -> {48}; 39 -> {40}; 40 -> {41}; 41 -> {42}; - 42 -> {47}; - 43 -> {44}; + 42 -> {43}; + 43 -> {48}; 44 -> {45}; 45 -> {46}; 46 -> {47}; 47 -> {48}; - 48 -> {51}; - 48 -> {49} [style=dotted]; + 48 -> {49}; + 49 -> {52}; 49 -> {50} [style=dotted]; 50 -> {51} [style=dotted]; + 51 -> {52} [style=dotted]; subgraph cluster_16 { color=red - 52 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red]; + 53 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red]; subgraph cluster_17 { color=blue - 53 [label="Enter block"]; + 54 [label="Enter block"]; subgraph cluster_18 { color=blue - 54 [label="Enter block"]; - 55 [label="Access variable this@R|/firstIsInstanceOrNull|"]; - 56 [label="Function call: this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|()"]; - 57 [label="Variable declaration: lval : R|kotlin/collections/Iterator|"]; + 55 [label="Enter block"]; + 56 [label="Access variable this@R|/firstIsInstanceOrNull|"]; + 57 [label="Function call: this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|()"]; + 58 [label="Variable declaration: lval : R|kotlin/collections/Iterator|"]; subgraph cluster_19 { color=blue - 58 [label="Enter while loop"]; + 59 [label="Enter while loop"]; subgraph cluster_20 { color=blue - 59 [label="Enter loop condition"]; - 60 [label="Access variable R|/|"]; - 61 [label="Function call: R|/|.R|SubstitutionOverride|()"]; - 62 [label="Exit loop condition"]; + 60 [label="Enter loop condition"]; + 61 [label="Access variable R|/|"]; + 62 [label="Function call: R|/|.R|SubstitutionOverride|()"]; + 63 [label="Exit loop condition"]; } subgraph cluster_21 { color=blue - 63 [label="Enter loop block"]; + 64 [label="Enter loop block"]; subgraph cluster_22 { color=blue - 64 [label="Enter block"]; - 65 [label="Access variable R|/|"]; - 66 [label="Function call: R|/|.R|SubstitutionOverride|()"]; - 67 [label="Variable declaration: lval element: R|kotlin/Any?|"]; + 65 [label="Enter block"]; + 66 [label="Access variable R|/|"]; + 67 [label="Function call: R|/|.R|SubstitutionOverride|()"]; + 68 [label="Variable declaration: lval element: R|kotlin/Any?|"]; subgraph cluster_23 { color=blue - 68 [label="Enter when"]; + 69 [label="Enter when"]; subgraph cluster_24 { color=blue - 69 [label="Enter when branch condition "]; - 70 [label="Access variable R|/element|"]; - 71 [label="Type operator: (R|/element| is R|T|)"]; - 72 [label="Exit when branch condition"]; + 70 [label="Enter when branch condition "]; + 71 [label="Access variable R|/element|"]; + 72 [label="Type operator: (R|/element| is R|T|)"]; + 73 [label="Exit when branch condition"]; } - 73 [label="Synthetic else branch"]; - 74 [label="Enter when branch result"]; + 74 [label="Synthetic else branch"]; + 75 [label="Enter when branch result"]; subgraph cluster_25 { color=blue - 75 [label="Enter block"]; - 76 [label="Access variable R|/element|"]; - 77 [label="Smart cast: R|/element|"]; - 78 [label="Jump: ^firstIsInstanceOrNull R|/element|"]; - 79 [label="Stub" style="filled" fillcolor=gray]; - 80 [label="Exit block" style="filled" fillcolor=gray]; + 76 [label="Enter block"]; + 77 [label="Access variable R|/element|"]; + 78 [label="Smart cast: R|/element|"]; + 79 [label="Jump: ^firstIsInstanceOrNull R|/element|"]; + 80 [label="Stub" style="filled" fillcolor=gray]; + 81 [label="Exit block" style="filled" fillcolor=gray]; } - 81 [label="Exit when branch result" style="filled" fillcolor=gray]; - 82 [label="Exit when"]; + 82 [label="Exit when branch result" style="filled" fillcolor=gray]; + 83 [label="Exit when"]; } - 83 [label="Exit block"]; + 84 [label="Exit block"]; } - 84 [label="Exit loop block"]; + 85 [label="Exit loop block"]; } - 85 [label="Exit whileloop"]; + 86 [label="Exit whileloop"]; } - 86 [label="Exit block"]; + 87 [label="Exit block"]; } - 87 [label="Const: Null(null)"]; - 88 [label="Jump: ^firstIsInstanceOrNull Null(null)"]; - 89 [label="Stub" style="filled" fillcolor=gray]; - 90 [label="Exit block" style="filled" fillcolor=gray]; + 88 [label="Const: Null(null)"]; + 89 [label="Jump: ^firstIsInstanceOrNull Null(null)"]; + 90 [label="Stub" style="filled" fillcolor=gray]; + 91 [label="Exit block" style="filled" fillcolor=gray]; } - 91 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red]; + 92 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red]; } - 52 -> {53}; 53 -> {54}; 54 -> {55}; 55 -> {56}; @@ -253,8 +254,8 @@ digraph complex_kt { 59 -> {60}; 60 -> {61}; 61 -> {62}; - 62 -> {85 63}; - 63 -> {64}; + 62 -> {63}; + 63 -> {86 64}; 64 -> {65}; 65 -> {66}; 66 -> {67}; @@ -263,26 +264,27 @@ digraph complex_kt { 69 -> {70}; 70 -> {71}; 71 -> {72}; - 72 -> {74 73}; - 73 -> {82}; - 74 -> {75}; + 72 -> {73}; + 73 -> {75 74}; + 74 -> {83}; 75 -> {76}; 76 -> {77}; 77 -> {78}; - 78 -> {91}; - 78 -> {79} [style=dotted]; + 78 -> {79}; + 79 -> {92}; 79 -> {80} [style=dotted]; 80 -> {81} [style=dotted]; 81 -> {82} [style=dotted]; - 82 -> {83}; + 82 -> {83} [style=dotted]; 83 -> {84}; - 84 -> {59} [color=green style=dashed]; - 85 -> {86}; + 84 -> {85}; + 85 -> {60} [color=green style=dashed]; 86 -> {87}; 87 -> {88}; - 88 -> {91}; - 88 -> {89} [style=dotted]; + 88 -> {89}; + 89 -> {92}; 89 -> {90} [style=dotted]; 90 -> {91} [style=dotted]; + 91 -> {92} [style=dotted]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot index 7941a541602..ee65cb4e35e 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot @@ -135,14 +135,14 @@ digraph inplaceLambdaInControlFlowExpressions_kt { 44 [label="Postponed enter to lambda"]; subgraph cluster_16 { color=blue - 59 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 60 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_17 { color=blue - 60 [label="Enter block"]; - 61 [label="Function call: R|/materialize|()"]; - 62 [label="Exit block"]; + 61 [label="Enter block"]; + 62 [label="Function call: R|/materialize|()"]; + 63 [label="Exit block"]; } - 63 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 64 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 45 [label="Postponed exit from lambda"]; 46 [label="Function call: R|kotlin/run|(...)"]; @@ -153,36 +153,37 @@ digraph inplaceLambdaInControlFlowExpressions_kt { subgraph cluster_18 { color=blue 49 [label="Catch enter"]; + 50 [label="Variable declaration: e: R|kotlin/Exception|"]; subgraph cluster_19 { color=blue - 50 [label="Enter block"]; - 51 [label="Const: String()"]; - 52 [label="Exit block"]; + 51 [label="Enter block"]; + 52 [label="Const: String()"]; + 53 [label="Exit block"]; } - 53 [label="Catch exit"]; + 54 [label="Catch exit"]; } - 54 [label="Try expression exit"]; + 55 [label="Try expression exit"]; } - 55 [label="Call arguments union" style="filled" fillcolor=yellow]; - 56 [label="Variable declaration: lval x: R|kotlin/String|"]; - 57 [label="Exit block"]; + 56 [label="Call arguments union" style="filled" fillcolor=yellow]; + 57 [label="Variable declaration: lval x: R|kotlin/String|"]; + 58 [label="Exit block"]; } - 58 [label="Exit function test_2" style="filled" fillcolor=red]; + 59 [label="Exit function test_2" style="filled" fillcolor=red]; } 39 -> {40}; 40 -> {41}; 41 -> {42 49}; 42 -> {43}; 43 -> {44}; - 44 -> {59}; + 44 -> {60}; 44 -> {45} [color=red]; - 44 -> {59} [style=dashed]; + 44 -> {60} [style=dashed]; 45 -> {46}; 46 -> {47}; 47 -> {48}; - 48 -> {54 49}; + 48 -> {55 49}; 49 -> {50}; - 49 -> {58} [label=onUncaughtException]; + 49 -> {59} [label=onUncaughtException]; 50 -> {51}; 51 -> {52}; 52 -> {53}; @@ -191,56 +192,57 @@ digraph inplaceLambdaInControlFlowExpressions_kt { 55 -> {56}; 56 -> {57}; 57 -> {58}; - 59 -> {60}; + 58 -> {59}; 60 -> {61}; 61 -> {62}; 62 -> {63}; - 63 -> {55} [color=red]; - 63 -> {45} [color=green]; + 63 -> {64}; + 64 -> {56} [color=red]; + 64 -> {45} [color=green]; subgraph cluster_20 { color=red - 64 [label="Enter function test_3" style="filled" fillcolor=red]; + 65 [label="Enter function test_3" style="filled" fillcolor=red]; subgraph cluster_21 { color=blue - 65 [label="Enter block"]; - 66 [label="Postponed enter to lambda"]; + 66 [label="Enter block"]; + 67 [label="Postponed enter to lambda"]; subgraph cluster_22 { color=blue - 74 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 75 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_23 { color=blue - 75 [label="Enter block"]; - 76 [label="Function call: R|/materialize|()"]; - 77 [label="Exit block"]; + 76 [label="Enter block"]; + 77 [label="Function call: R|/materialize|()"]; + 78 [label="Exit block"]; } - 78 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 79 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 67 [label="Postponed exit from lambda"]; - 68 [label="Function call: R|kotlin/run|(...)"]; - 69 [label="Check not null: R|kotlin/run|(...)!!"]; - 70 [label="Call arguments union" style="filled" fillcolor=yellow]; - 71 [label="Variable declaration: lval x: R|kotlin/String|"]; - 72 [label="Exit block"]; + 68 [label="Postponed exit from lambda"]; + 69 [label="Function call: R|kotlin/run|(...)"]; + 70 [label="Check not null: R|kotlin/run|(...)!!"]; + 71 [label="Call arguments union" style="filled" fillcolor=yellow]; + 72 [label="Variable declaration: lval x: R|kotlin/String|"]; + 73 [label="Exit block"]; } - 73 [label="Exit function test_3" style="filled" fillcolor=red]; + 74 [label="Exit function test_3" style="filled" fillcolor=red]; } - 64 -> {65}; 65 -> {66}; - 66 -> {74}; - 66 -> {67} [color=red]; - 66 -> {74} [style=dashed]; - 67 -> {68}; + 66 -> {67}; + 67 -> {75}; + 67 -> {68} [color=red]; + 67 -> {75} [style=dashed]; 68 -> {69}; 69 -> {70}; 70 -> {71}; 71 -> {72}; 72 -> {73}; - 74 -> {75}; + 73 -> {74}; 75 -> {76}; 76 -> {77}; 77 -> {78}; - 78 -> {70} [color=red]; - 78 -> {67} [color=green]; + 78 -> {79}; + 79 -> {71} [color=red]; + 79 -> {68} [color=green]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot index b13b821b403..6f79da27a30 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot @@ -269,39 +269,40 @@ digraph propertiesAndInitBlocks_kt { subgraph cluster_27 { color=blue 87 [label="Catch enter"]; + 88 [label="Variable declaration: e: R|kotlin/Exception|"]; subgraph cluster_28 { color=blue - 88 [label="Enter block"]; - 89 [label="Const: Int(2)"]; - 90 [label="Exit block"]; + 89 [label="Enter block"]; + 90 [label="Const: Int(2)"]; + 91 [label="Exit block"]; } - 91 [label="Catch exit"]; + 92 [label="Catch exit"]; } subgraph cluster_29 { color=blue - 92 [label="Enter finally"]; + 93 [label="Enter finally"]; subgraph cluster_30 { color=blue - 93 [label="Enter block"]; - 94 [label="Const: Int(0)"]; - 95 [label="Exit block"]; + 94 [label="Enter block"]; + 95 [label="Const: Int(0)"]; + 96 [label="Exit block"]; } - 96 [label="Exit finally"]; + 97 [label="Exit finally"]; } - 97 [label="Try expression exit"]; + 98 [label="Try expression exit"]; } - 98 [label="Exit property" style="filled" fillcolor=red]; + 99 [label="Exit property" style="filled" fillcolor=red]; } 80 -> {81}; 81 -> {82 87}; - 81 -> {92} [label=onUncaughtException]; + 81 -> {93} [label=onUncaughtException]; 82 -> {83}; 83 -> {84}; 84 -> {85}; 85 -> {86}; - 86 -> {92 87}; + 86 -> {93 87}; 87 -> {88}; - 87 -> {92} [label=onUncaughtException]; + 87 -> {93} [label=onUncaughtException]; 88 -> {89}; 89 -> {90}; 90 -> {91}; @@ -311,7 +312,8 @@ digraph propertiesAndInitBlocks_kt { 94 -> {95}; 95 -> {96}; 96 -> {97}; - 96 -> {98} [label=onUncaughtException]; 97 -> {98}; + 97 -> {99} [label=onUncaughtException]; + 98 -> {99}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot index d39a20b3769..0a0408483db 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot @@ -27,301 +27,311 @@ digraph tryCatch_kt { subgraph cluster_5 { color=blue 9 [label="Catch enter"]; + 10 [label="Variable declaration: e: R|kotlin/Exception|"]; subgraph cluster_6 { color=blue - 10 [label="Enter block"]; - 11 [label="Const: Int(3)"]; - 12 [label="Variable declaration: lval z: R|kotlin/Int|"]; - 13 [label="Exit block"]; + 11 [label="Enter block"]; + 12 [label="Const: Int(3)"]; + 13 [label="Variable declaration: lval z: R|kotlin/Int|"]; + 14 [label="Exit block"]; } - 14 [label="Catch exit"]; + 15 [label="Catch exit"]; } subgraph cluster_7 { color=blue - 15 [label="Catch enter"]; + 16 [label="Catch enter"]; + 17 [label="Variable declaration: e: R|kotlin/RuntimeException|"]; subgraph cluster_8 { color=blue - 16 [label="Enter block"]; - 17 [label="Const: Int(2)"]; - 18 [label="Variable declaration: lval y: R|kotlin/Int|"]; - 19 [label="Exit block"]; + 18 [label="Enter block"]; + 19 [label="Const: Int(2)"]; + 20 [label="Variable declaration: lval y: R|kotlin/Int|"]; + 21 [label="Exit block"]; } - 20 [label="Catch exit"]; + 22 [label="Catch exit"]; } - 21 [label="Try expression exit"]; + 23 [label="Try expression exit"]; } - 22 [label="Exit block"]; + 24 [label="Exit block"]; } - 23 [label="Exit function test_1" style="filled" fillcolor=red]; + 25 [label="Exit function test_1" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; - 2 -> {3 15 9}; + 2 -> {3 16 9}; 3 -> {4}; 4 -> {5}; 5 -> {6}; 6 -> {7}; 7 -> {8}; - 8 -> {21 15 9}; + 8 -> {23 16 9}; 9 -> {10}; - 9 -> {23} [label=onUncaughtException]; + 9 -> {25} [label=onUncaughtException]; 10 -> {11}; 11 -> {12}; 12 -> {13}; 13 -> {14}; - 14 -> {21}; - 15 -> {16}; - 15 -> {23} [label=onUncaughtException]; + 14 -> {15}; + 15 -> {23}; 16 -> {17}; + 16 -> {25} [label=onUncaughtException]; 17 -> {18}; 18 -> {19}; 19 -> {20}; 20 -> {21}; 21 -> {22}; 22 -> {23}; + 23 -> {24}; + 24 -> {25}; subgraph cluster_9 { color=red - 24 [label="Enter function test_2" style="filled" fillcolor=red]; + 26 [label="Enter function test_2" style="filled" fillcolor=red]; subgraph cluster_10 { color=blue - 25 [label="Enter block"]; + 27 [label="Enter block"]; subgraph cluster_11 { color=blue - 26 [label="Try expression enter"]; + 28 [label="Try expression enter"]; subgraph cluster_12 { color=blue - 27 [label="Try main block enter"]; + 29 [label="Try main block enter"]; subgraph cluster_13 { color=blue - 28 [label="Enter block"]; - 29 [label="Const: Int(1)"]; - 30 [label="Exit block"]; + 30 [label="Enter block"]; + 31 [label="Const: Int(1)"]; + 32 [label="Exit block"]; } - 31 [label="Try main block exit"]; + 33 [label="Try main block exit"]; } subgraph cluster_14 { color=blue - 32 [label="Catch enter"]; + 34 [label="Catch enter"]; + 35 [label="Variable declaration: e: R|kotlin/Exception|"]; subgraph cluster_15 { color=blue - 33 [label="Enter block"]; - 34 [label="Const: Int(2)"]; - 35 [label="Exit block"]; + 36 [label="Enter block"]; + 37 [label="Const: Int(2)"]; + 38 [label="Exit block"]; } - 36 [label="Catch exit"]; + 39 [label="Catch exit"]; } - 37 [label="Try expression exit"]; + 40 [label="Try expression exit"]; } - 38 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 39 [label="Exit block"]; + 41 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 42 [label="Exit block"]; } - 40 [label="Exit function test_2" style="filled" fillcolor=red]; + 43 [label="Exit function test_2" style="filled" fillcolor=red]; } - 24 -> {25}; - 25 -> {26}; - 26 -> {27 32}; + 26 -> {27}; 27 -> {28}; - 28 -> {29}; + 28 -> {29 34}; 29 -> {30}; 30 -> {31}; - 31 -> {37 32}; + 31 -> {32}; 32 -> {33}; - 32 -> {40} [label=onUncaughtException]; - 33 -> {34}; + 33 -> {40 34}; 34 -> {35}; + 34 -> {43} [label=onUncaughtException]; 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; subgraph cluster_16 { color=red - 41 [label="Enter function test_3" style="filled" fillcolor=red]; + 44 [label="Enter function test_3" style="filled" fillcolor=red]; subgraph cluster_17 { color=blue - 42 [label="Enter block"]; + 45 [label="Enter block"]; subgraph cluster_18 { color=blue - 43 [label="Enter while loop"]; + 46 [label="Enter while loop"]; subgraph cluster_19 { color=blue - 44 [label="Enter loop condition"]; - 45 [label="Const: Boolean(true)"]; - 46 [label="Exit loop condition"]; + 47 [label="Enter loop condition"]; + 48 [label="Const: Boolean(true)"]; + 49 [label="Exit loop condition"]; } subgraph cluster_20 { color=blue - 47 [label="Enter loop block"]; + 50 [label="Enter loop block"]; subgraph cluster_21 { color=blue - 48 [label="Enter block"]; + 51 [label="Enter block"]; subgraph cluster_22 { color=blue - 49 [label="Try expression enter"]; + 52 [label="Try expression enter"]; subgraph cluster_23 { color=blue - 50 [label="Try main block enter"]; + 53 [label="Try main block enter"]; subgraph cluster_24 { color=blue - 51 [label="Enter block"]; + 54 [label="Enter block"]; subgraph cluster_25 { color=blue - 52 [label="Enter when"]; + 55 [label="Enter when"]; subgraph cluster_26 { color=blue - 53 [label="Enter when branch condition "]; - 54 [label="Access variable R|/b|"]; - 55 [label="Exit when branch condition"]; + 56 [label="Enter when branch condition "]; + 57 [label="Access variable R|/b|"]; + 58 [label="Exit when branch condition"]; } - 56 [label="Synthetic else branch"]; - 57 [label="Enter when branch result"]; + 59 [label="Synthetic else branch"]; + 60 [label="Enter when branch result"]; subgraph cluster_27 { color=blue - 58 [label="Enter block"]; - 59 [label="Jump: ^test_3 Unit"]; - 60 [label="Stub" style="filled" fillcolor=gray]; - 61 [label="Exit block" style="filled" fillcolor=gray]; + 61 [label="Enter block"]; + 62 [label="Jump: ^test_3 Unit"]; + 63 [label="Stub" style="filled" fillcolor=gray]; + 64 [label="Exit block" style="filled" fillcolor=gray]; } - 62 [label="Exit when branch result" style="filled" fillcolor=gray]; - 63 [label="Exit when"]; + 65 [label="Exit when branch result" style="filled" fillcolor=gray]; + 66 [label="Exit when"]; } - 64 [label="Const: Int(1)"]; - 65 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 67 [label="Const: Int(1)"]; + 68 [label="Variable declaration: lval x: R|kotlin/Int|"]; subgraph cluster_28 { color=blue - 66 [label="Enter when"]; + 69 [label="Enter when"]; subgraph cluster_29 { color=blue - 67 [label="Enter when branch condition "]; - 68 [label="Access variable R|/b|"]; - 69 [label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; - 70 [label="Exit when branch condition"]; + 70 [label="Enter when branch condition "]; + 71 [label="Access variable R|/b|"]; + 72 [label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; + 73 [label="Exit when branch condition"]; } - 71 [label="Synthetic else branch"]; - 72 [label="Enter when branch result"]; + 74 [label="Synthetic else branch"]; + 75 [label="Enter when branch result"]; subgraph cluster_30 { color=blue - 73 [label="Enter block"]; - 74 [label="Jump: break@@@[Boolean(true)] "]; - 75 [label="Stub" style="filled" fillcolor=gray]; - 76 [label="Exit block" style="filled" fillcolor=gray]; + 76 [label="Enter block"]; + 77 [label="Jump: break@@@[Boolean(true)] "]; + 78 [label="Stub" style="filled" fillcolor=gray]; + 79 [label="Exit block" style="filled" fillcolor=gray]; } - 77 [label="Exit when branch result" style="filled" fillcolor=gray]; - 78 [label="Exit when"]; + 80 [label="Exit when branch result" style="filled" fillcolor=gray]; + 81 [label="Exit when"]; } - 79 [label="Exit block"]; + 82 [label="Exit block"]; } - 80 [label="Try main block exit"]; + 83 [label="Try main block exit"]; } subgraph cluster_31 { color=blue - 81 [label="Catch enter"]; + 84 [label="Catch enter"]; + 85 [label="Variable declaration: e: R|kotlin/RuntimeException|"]; subgraph cluster_32 { color=blue - 82 [label="Enter block"]; - 83 [label="Jump: break@@@[Boolean(true)] "]; - 84 [label="Stub" style="filled" fillcolor=gray]; - 85 [label="Exit block" style="filled" fillcolor=gray]; + 86 [label="Enter block"]; + 87 [label="Jump: break@@@[Boolean(true)] "]; + 88 [label="Stub" style="filled" fillcolor=gray]; + 89 [label="Exit block" style="filled" fillcolor=gray]; } - 86 [label="Catch exit" style="filled" fillcolor=gray]; + 90 [label="Catch exit" style="filled" fillcolor=gray]; } subgraph cluster_33 { color=blue - 91 [label="Catch enter"]; + 95 [label="Catch enter"]; + 96 [label="Variable declaration: e: R|kotlin/Exception|"]; subgraph cluster_34 { color=blue - 92 [label="Enter block"]; - 93 [label="Jump: continue@@@[Boolean(true)] "]; - 94 [label="Stub" style="filled" fillcolor=gray]; - 95 [label="Exit block" style="filled" fillcolor=gray]; + 97 [label="Enter block"]; + 98 [label="Jump: continue@@@[Boolean(true)] "]; + 99 [label="Stub" style="filled" fillcolor=gray]; + 100 [label="Exit block" style="filled" fillcolor=gray]; } - 96 [label="Catch exit" style="filled" fillcolor=gray]; + 101 [label="Catch exit" style="filled" fillcolor=gray]; } - 97 [label="Try expression exit"]; + 102 [label="Try expression exit"]; } - 98 [label="Const: Int(2)"]; - 99 [label="Variable declaration: lval y: R|kotlin/Int|"]; - 100 [label="Exit block"]; + 103 [label="Const: Int(2)"]; + 104 [label="Variable declaration: lval y: R|kotlin/Int|"]; + 105 [label="Exit block"]; } - 101 [label="Exit loop block"]; + 106 [label="Exit loop block"]; } - 87 [label="Exit whileloop"]; + 91 [label="Exit whileloop"]; } - 88 [label="Const: Int(3)"]; - 89 [label="Variable declaration: lval z: R|kotlin/Int|"]; - 90 [label="Exit block"]; + 92 [label="Const: Int(3)"]; + 93 [label="Variable declaration: lval z: R|kotlin/Int|"]; + 94 [label="Exit block"]; } - 102 [label="Exit function test_3" style="filled" fillcolor=red]; + 107 [label="Exit function test_3" style="filled" fillcolor=red]; } - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; 44 -> {45}; 45 -> {46}; 46 -> {47}; - 46 -> {87} [style=dotted]; 47 -> {48}; 48 -> {49}; - 49 -> {50 91 81}; + 49 -> {50}; + 49 -> {91} [style=dotted]; 50 -> {51}; 51 -> {52}; - 52 -> {53}; + 52 -> {53 95 84}; 53 -> {54}; 54 -> {55}; - 55 -> {57 56}; - 56 -> {63}; + 55 -> {56}; + 56 -> {57}; 57 -> {58}; - 58 -> {59}; - 59 -> {102}; - 59 -> {60} [style=dotted]; - 60 -> {61} [style=dotted]; - 61 -> {62} [style=dotted]; + 58 -> {60 59}; + 59 -> {66}; + 60 -> {61}; + 61 -> {62}; + 62 -> {107}; 62 -> {63} [style=dotted]; - 63 -> {64}; - 64 -> {65}; - 65 -> {66}; + 63 -> {64} [style=dotted]; + 64 -> {65} [style=dotted]; + 65 -> {66} [style=dotted]; 66 -> {67}; 67 -> {68}; 68 -> {69}; 69 -> {70}; - 70 -> {72 71}; - 71 -> {78}; + 70 -> {71}; + 71 -> {72}; 72 -> {73}; - 73 -> {74}; - 74 -> {87}; - 74 -> {75} [style=dotted]; - 75 -> {76} [style=dotted]; - 76 -> {77} [style=dotted]; + 73 -> {75 74}; + 74 -> {81}; + 75 -> {76}; + 76 -> {77}; + 77 -> {91}; 77 -> {78} [style=dotted]; - 78 -> {79}; - 79 -> {80}; - 80 -> {97 91 81}; + 78 -> {79} [style=dotted]; + 79 -> {80} [style=dotted]; + 80 -> {81} [style=dotted]; 81 -> {82}; - 81 -> {102} [label=onUncaughtException]; 82 -> {83}; - 83 -> {87}; - 83 -> {84} [style=dotted]; - 84 -> {85} [style=dotted]; - 85 -> {86} [style=dotted]; - 86 -> {97} [style=dotted]; - 87 -> {88}; - 88 -> {89}; - 89 -> {90}; - 90 -> {102}; + 83 -> {102 95 84}; + 84 -> {85}; + 84 -> {107} [label=onUncaughtException]; + 85 -> {86}; + 86 -> {87}; + 87 -> {91}; + 87 -> {88} [style=dotted]; + 88 -> {89} [style=dotted]; + 89 -> {90} [style=dotted]; + 90 -> {102} [style=dotted]; 91 -> {92}; - 91 -> {102} [label=onUncaughtException]; 92 -> {93}; - 93 -> {94} [style=dotted]; - 93 -> {43} [color=green style=dashed]; - 94 -> {95} [style=dotted]; - 95 -> {96} [style=dotted]; - 96 -> {97} [style=dotted]; + 93 -> {94}; + 94 -> {107}; + 95 -> {96}; + 95 -> {107} [label=onUncaughtException]; + 96 -> {97}; 97 -> {98}; - 98 -> {99}; - 99 -> {100}; - 100 -> {101}; - 101 -> {44} [color=green style=dashed]; + 98 -> {99} [style=dotted]; + 98 -> {46} [color=green style=dashed]; + 99 -> {100} [style=dotted]; + 100 -> {101} [style=dotted]; + 101 -> {102} [style=dotted]; + 102 -> {103}; + 103 -> {104}; + 104 -> {105}; + 105 -> {106}; + 106 -> {47} [color=green style=dashed]; } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt index dd04a84b24f..5ffba0d9b00 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt @@ -8,18 +8,19 @@ package org.jetbrains.kotlin.fir.analysis.cfa import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.contracts.description.canBeRevisited import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.cfa.util.PathAwarePropertyInitializationInfo import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfo import org.jetbrains.kotlin.fir.analysis.cfa.util.TraverseDirection import org.jetbrains.kotlin.fir.analysis.cfa.util.traverse import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors -import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.utils.isLateInit import org.jetbrains.kotlin.fir.declarations.utils.referredPropertySymbol import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol @@ -37,16 +38,22 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec context: CheckerContext ) { val localData = data.filter { - val symbolFir = (it.key.fir as? FirVariableSymbol<*>)?.fir - symbolFir == null || symbolFir.initializer == null && symbolFir.delegate == null + val symbol = it.key.fir as? FirVariableSymbol<*> + symbol == null || !symbol.isInitialized() } - val localProperties = properties.filterTo(mutableSetOf()) { it.fir.initializer == null && it.fir.delegate == null } + val localProperties = properties.filterNotTo(mutableSetOf()) { it.isInitialized() } val reporterVisitor = PropertyReporter(localData, localProperties, capturedWrites, reporter, context) graph.traverse(TraverseDirection.Forward, reporterVisitor) } + private fun FirVariableSymbol<*>.isInitialized(): Boolean { + return fir.initializer != null + || fir.delegate != null + || this is FirPropertySymbol && fir.isCatchParameter == true + } + private class PropertyReporter( val data: Map, PathAwarePropertyInitializationInfo>, val localProperties: Set, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt index 1b0bf535848..143c39e36d8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.isUnderscore import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirUserTypeRef @@ -22,7 +23,7 @@ object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() { if ( declaration is FirRegularClass || declaration is FirTypeParameter || - declaration is FirProperty || + declaration is FirProperty && declaration.isCatchParameter != true || declaration is FirTypeAlias ) { reportIfUnderscore(declaration, context, reporter) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt index 839ccb30e73..e31149c6dec 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt @@ -5,12 +5,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.defaultValueForParameter import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeOfThrowable import org.jetbrains.kotlin.fir.analysis.checkers.valOrVarKeyword -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors -import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.types.ConeTypeParameterType import org.jetbrains.kotlin.fir.types.coneType @@ -23,7 +24,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() { val catchParameter = catchEntry.parameter val source = catchParameter.source ?: continue - if (catchParameter.defaultValue != null) { + if (catchParameter.source?.defaultValueForParameter != null) { reporter.reportOn(source, FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE, context) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt index 1e0508cab15..7fba7ac178c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt @@ -9,16 +9,15 @@ import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentMapOf import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtNodeTypes -import org.jetbrains.kotlin.fir.FirAnnotationContainer -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.cfa.util.* import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.isIterator -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors -import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.expressions.FirAnnotation @@ -26,14 +25,12 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* -import org.jetbrains.kotlin.fir.resolved -import org.jetbrains.kotlin.fir.resolvedSymbol -import org.jetbrains.kotlin.fir.types.isFunctionalType import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.isFunctionalType object UnusedChecker : FirControlFlowChecker() { override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) { @@ -81,9 +78,13 @@ object UnusedChecker : FirControlFlowChecker() { val variableSource = variable.source.takeIf { it?.elementType != KtNodeTypes.DESTRUCTURING_DECLARATION } when { data == VariableStatus.UNUSED -> { - if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) { - reporter.reportOn(variableSource, FirErrors.UNUSED_VARIABLE, context) - break + when { + (node.fir.initializer as? FirFunctionCall)?.isIterator == true -> {} + node.fir.isCatchParameter == true -> {} + else -> { + reporter.reportOn(variableSource, FirErrors.UNUSED_VARIABLE, context) + break + } } } data.isRedundantInit -> { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 6337cff8383..b5d82aaffb5 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtLightSourceElement import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.descriptors.EffectiveVisibility import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fakeElement @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* @@ -44,6 +46,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.lexer.KtTokens.* +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType @@ -1198,7 +1201,20 @@ class ExpressionsConverter( for ((parameter, block) in catchClauses) { if (parameter == null) continue catches += buildCatch { - this.parameter = parameter.firValueParameter + this.parameter = buildProperty { + source = parameter.source + moduleData = baseModuleData + origin = FirDeclarationOrigin.Source + returnTypeRef = parameter.returnTypeRef + isVar = false + status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local) + isLocal = true + this.name = parameter.name + symbol = FirPropertySymbol(CallableId(name)) + annotations += parameter.annotations + }.also { + it.isCatchParameter = true + } this.block = block } } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt index d40ab4eb492..91520addef1 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt @@ -48,7 +48,7 @@ class ValueParameter( private val isVar: Boolean, private val modifiers: Modifier, val returnTypeRef: FirTypeRef, - private val source: KtSourceElement, + val source: KtSourceElement, private val moduleData: FirModuleData, private val isFromPrimaryConstructor: Boolean, private val additionalAnnotations: List, @@ -60,6 +60,19 @@ class ValueParameter( return isVal || isVar } + val annotations: List by lazy(LazyThreadSafetyMode.NONE) { + buildList { + if (!isFromPrimaryConstructor) + addAll(modifiers.annotations) + else + modifiers.annotations.filterTo(this) { + val useSiteTarget = it.useSiteTarget + useSiteTarget == null || useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER || useSiteTarget == AnnotationUseSiteTarget.RECEIVER || useSiteTarget == AnnotationUseSiteTarget.FILE + } + addAll(additionalAnnotations) + } + } + val firValueParameter: FirValueParameter by lazy(LazyThreadSafetyMode.NONE) { buildValueParameter { source = this@ValueParameter.source @@ -72,13 +85,7 @@ class ValueParameter( isCrossinline = modifiers.hasCrossinline() isNoinline = modifiers.hasNoinline() isVararg = modifiers.hasVararg() - annotations += if (!isFromPrimaryConstructor) - modifiers.annotations - else - modifiers.annotations.filter { - val useSiteTarget = it.useSiteTarget - useSiteTarget == null || useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER || useSiteTarget == AnnotationUseSiteTarget.RECEIVER || useSiteTarget == AnnotationUseSiteTarget.FILE - } + annotations += this@ValueParameter.annotations annotations += additionalAnnotations } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 939a21cad29..b21daa15d8d 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -11,10 +11,7 @@ import com.intellij.util.AstLoadingFilter import org.jetbrains.kotlin.* import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.contracts.FirContractDescription @@ -1985,11 +1982,32 @@ open class RawFirBuilder( tryBlock = expression.tryBlock.toFirBlock() finallyBlock = expression.finallyBlock?.finalExpression?.toFirBlock() for (clause in expression.catchClauses) { - val parameter = clause.catchParameter?.let { - convertValueParameter( - it, - valueParameterDeclaration = ValueParameterDeclaration.CATCH + val parameter = clause.catchParameter?.let { ktParameter -> + val name = convertValueParameterName( + ktParameter.nameAsSafeName, + ktParameter.nameIdentifier?.node?.text, + ValueParameterDeclaration.CATCH ) + + buildProperty { + source = ktParameter.toFirSourceElement() + moduleData = baseModuleData + origin = FirDeclarationOrigin.Source + returnTypeRef = when { + ktParameter.typeReference != null -> ktParameter.typeReference.toFirOrErrorType() + else -> createNoTypeForParameterTypeRef() + } + isVar = false + status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local) + isLocal = true + this.name = name + symbol = FirPropertySymbol(CallableId(name)) + for (annotationEntry in ktParameter.annotationEntries) { + this.annotations += annotationEntry.convert() + } + }.also { + it.isCatchParameter = true + } } ?: continue catches += buildCatch { source = clause.toFirSourceElement() diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/noParameterType/noParameterTypRefInCatch.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/noParameterType/noParameterTypRefInCatch.txt index 66e251058c2..9b72d0c8a41 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/noParameterType/noParameterTypRefInCatch.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/noParameterType/noParameterTypRefInCatch.txt @@ -2,7 +2,7 @@ FILE: noParameterTypRefInCatch.kt public? final? fun foo(): R|kotlin/Unit| { try { } - catch (e: ) { + catch ([IsCatchParameterProperty=true] e: ) { } } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/try.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/try.txt index e12d53e1fb0..615b8a12d4f 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/try.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/try.txt @@ -3,10 +3,10 @@ FILE: try.kt try { throw KotlinNullPointerException#() } - catch (e: RuntimeException) { + catch ([IsCatchParameterProperty=true] e: RuntimeException) { println#(String(Runtime exception)) } - catch (e: Exception) { + catch ([IsCatchParameterProperty=true] e: Exception) { println#(String(Some exception)) } finally { diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index 9f23a752b3d..bf1ef35a67c 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -9,15 +9,18 @@ import com.intellij.testFramework.TestDataPath import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub +import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.renderer.FirRenderer +import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -67,18 +70,18 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { } totalLength += FirRenderer().renderElementAsString(firFile).length counter++ - firFile.accept(object : FirVisitorVoid() { - override fun visitElement(element: FirElement) { - element.acceptChildren(this) + firFile.accept(object : FirVisitor() { + override fun visitElement(element: FirElement, data: FirElement) { + element.acceptChildren(this, element) } - override fun visitErrorExpression(errorExpression: FirErrorExpression) { + override fun visitErrorExpression(errorExpression: FirErrorExpression, data: FirElement) { errorExpressions++ println(errorExpression.render()) errorExpression.psi?.let { println(it) } } - override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) { + override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) { val calleeReference = qualifiedAccess.calleeReference if (calleeReference is FirErrorNamedReference) { errorReferences++ @@ -86,23 +89,25 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { } else { normalReferences++ } - visitStatement(qualifiedAccess) + visitStatement(qualifiedAccess, data) } - override fun visitExpression(expression: FirExpression) { + override fun visitExpression(expression: FirExpression, data: FirElement) { when (expression) { is FirExpressionStub -> { - expressionStubs++ - println(expression.psi?.text) + if (data !is FirProperty || data.isCatchParameter != true) { + expressionStubs++ + println(expression.psi?.text) + } } else -> normalExpressions++ } - expression.acceptChildren(this) + expression.acceptChildren(this, expression) } - override fun visitStatement(statement: FirStatement) { + override fun visitStatement(statement: FirStatement, data: FirElement) { normalStatements++ - statement.acceptChildren(this) + statement.acceptChildren(this, statement) } // override fun visitErrorDeclaration(errorDeclaration: FirErrorDeclaration) { @@ -111,11 +116,11 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { // errorDeclaration.psi?.let { println(it) } // } - override fun visitDeclaration(declaration: FirDeclaration) { + override fun visitDeclaration(declaration: FirDeclaration, data: FirElement) { normalDeclarations++ - declaration.acceptChildren(this) + declaration.acceptChildren(this, declaration) } - }) + }, firFile) ktFile.accept(object : KtTreeVisitor() { override fun visitReferenceExpression(expression: KtReferenceExpression, data: Nothing?): Void? { ktReferences++ diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCatch.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCatch.kt index e6f5e1841ab..41c537f98f1 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCatch.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCatch.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.expressions import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirPureAbstractElement -import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.visitors.* /* @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.visitors.* abstract class FirCatch : FirPureAbstractElement(), FirElement { abstract override val source: KtSourceElement? - abstract val parameter: FirValueParameter + abstract val parameter: FirProperty abstract val block: FirBlock override fun accept(visitor: FirVisitor, data: D): R = visitor.visitCatch(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCatchBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCatchBuilder.kt index 65001c9b5e4..1093ef0539c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCatchBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCatchBuilder.kt @@ -10,7 +10,7 @@ package org.jetbrains.kotlin.fir.expressions.builder import kotlin.contracts.* import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.builder.FirBuilderDsl -import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirCatch import org.jetbrains.kotlin.fir.expressions.impl.FirCatchImpl @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.visitors.* @FirBuilderDsl class FirCatchBuilder { var source: KtSourceElement? = null - lateinit var parameter: FirValueParameter + lateinit var parameter: FirProperty lateinit var block: FirBlock fun build(): FirCatch { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCatchImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCatchImpl.kt index cc2e8f8e322..12c936283b4 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCatchImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCatchImpl.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.expressions.impl import org.jetbrains.kotlin.KtSourceElement -import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirCatch import org.jetbrains.kotlin.fir.visitors.* @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.visitors.* internal class FirCatchImpl( override val source: KtSourceElement?, - override var parameter: FirValueParameter, + override var parameter: FirProperty, override var block: FirBlock, ) : FirCatch() { override fun acceptChildren(visitor: FirVisitor, data: D) { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt index 844a8d615f9..b67b66ba25a 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt @@ -142,3 +142,7 @@ var FirRegularClass.isJavaRecord: Boolean? by FirDeclarationDataRegistry.data(Is private object IsJavaRecordComponentKey : FirDeclarationDataKey() var FirFunction.isJavaRecordComponent: Boolean? by FirDeclarationDataRegistry.data(IsJavaRecordComponentKey) +private object IsCatchParameterProperty : FirDeclarationDataKey() + +var FirProperty.isCatchParameter: Boolean? by FirDeclarationDataRegistry.data(IsCatchParameterProperty) + diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt index c3501c7c777..baef45f38b3 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.renderer import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly open class FirDeclarationRenderer { @@ -32,8 +33,12 @@ open class FirDeclarationRenderer { is FirAnonymousFunction -> (declaration.label?.let { "${it.name}@" } ?: "") + "fun" is FirSimpleFunction -> "fun" is FirProperty -> { - val prefix = if (declaration.isLocal) "l" else "" - prefix + if (declaration.isVal) "val" else "var" + if (declaration.isCatchParameter == true) { + "" + } else { + val prefix = if (declaration.isLocal) "l" else "" + prefix + if (declaration.isVal) "val" else "var" + } } is FirPropertyAccessor -> if (declaration.isGetter) "get" else "set" is FirField -> "field" diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index cc1954e43a0..35cfb8c39a1 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -181,7 +181,9 @@ class FirRenderer( annotationRenderer?.render(callableDeclaration) visitMemberDeclaration(callableDeclaration) val receiverParameter = callableDeclaration.receiverParameter - print(" ") + if (callableDeclaration !is FirProperty || callableDeclaration.isCatchParameter != true) { + print(" ") + } if (receiverParameter != null) { annotationRenderer?.render(receiverParameter, AnnotationUseSiteTarget.RECEIVER) receiverParameter.typeRef.accept(this) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index c49f92d6748..df2cc606094 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeArguments import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeParameterRefs import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeParameters import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeRefField -import org.jetbrains.kotlin.fir.tree.generator.FieldSets.valueParameters import org.jetbrains.kotlin.fir.tree.generator.FieldSets.visibility import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFieldConfigurator import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder @@ -176,7 +175,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild } catchClause.configure { - +field("parameter", valueParameter).withTransform() + +field("parameter", property).withTransform() +field(block).withTransform() needTransformOtherChildren() }