Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
硅谷海盗
kotlin
提交
18bde2c5
K
kotlin
项目概览
硅谷海盗
/
kotlin
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kotlin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
18bde2c5
编写于
2月 06, 2021
作者:
D
Dmitriy Novozhilov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[FIR] Reimplement when exhaustiveness checker to fir it's logic with FE 1.0
上级
2a1c9283
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
305 addition
and
209 deletion
+305
-209
compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt
...ustiveness/positive/exhaustiveness_sealedSubClass.fir.txt
+2
-2
compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt
.../exhaustiveness/positive/exhaustiveness_sealedSubClass.kt
+2
-2
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt
.../analysis/checkers/expression/FirExhaustiveWhenChecker.kt
+5
-5
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt
...otlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt
+2
-1
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt
...kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt
+13
-0
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
...rg/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
+2
-1
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt
.../resolve/transformers/FirWhenExhaustivenessTransformer.kt
+228
-156
compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt
.../jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt
+49
-7
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt
...testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt
+1
-1
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt
...testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt
+0
-34
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt
...ler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt
+1
-0
未找到文件。
compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt
浏览文件 @
18bde2c5
...
...
@@ -107,10 +107,10 @@ FILE: exhaustiveness_sealedSubClass.kt
}
}
.<Unresolved name: plus>#(Int(0))
lval d: R|
ERROR CLASS: Unresolved name: plus
| = when (R|<local>/e|) {
lval d: R|
kotlin/Int
| = when (R|<local>/e|) {
($subj$ is R|C|) -> {
Int(1)
}
}
.
<Unresolved name: plus>#
(Int(0))
.
R|kotlin/Int.plus|
(Int(0))
}
compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt
浏览文件 @
18bde2c5
...
...
@@ -48,7 +48,7 @@ fun test_2(e: A) {
is
D
->
2
}.<!
UNRESOLVED_REFERENCE
{
LT
}!><!
UNRESOLVED_REFERENCE
{
PSI
}!>
plus
<!>(
0
)<!>
val
d
=
<!
NO_ELSE_IN_WHEN
!>
when
<!>
(
e
)
{
val
d
=
when
(
e
)
{
is
C
->
1
}.
<!
UNRESOLVED_REFERENCE
{
LT
}!><!
UNRESOLVED_REFERENCE
{
PSI
}!>
plus
<!>(
0
)<!>
}.
plus
(
0
)
}
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt
浏览文件 @
18bde2c5
...
...
@@ -11,19 +11,19 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import
org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import
org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import
org.jetbrains.kotlin.fir.expressions.ExhaustivenessStatus
import
org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import
org.jetbrains.kotlin.fir.expressions.isExhaustive
object
FirExhaustiveWhenChecker
:
FirWhenExpressionChecker
()
{
override
fun
check
(
expression
:
FirWhenExpression
,
context
:
CheckerContext
,
reporter
:
DiagnosticReporter
)
{
// TODO: add reporting of proper missing clauses, see class WhenMissingCase
if
(
expression
.
usedAsExpression
&&
!
expression
.
isExhaustive
)
{
val
factory
=
if
(
expression
.
source
?.
isIfExpression
==
true
)
{
FirErrors
.
INVALID_IF_AS_EXPRESSION
if
(
expression
.
source
?.
isIfExpression
==
true
)
{
reporter
.
reportOn
(
expression
.
source
,
FirErrors
.
INVALID_IF_AS_EXPRESSION
,
context
)
}
else
{
FirErrors
.
NO_ELSE_IN_WHEN
val
missingCases
=
(
expression
.
exhaustivenessStatus
as
ExhaustivenessStatus
.
NotExhaustive
).
reasons
reporter
.
reportOn
(
expression
.
source
,
FirErrors
.
NO_ELSE_IN_WHEN
,
missingCases
,
context
)
}
reporter
.
reportOn
(
expression
.
source
,
factory
,
context
)
}
}
...
...
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt
浏览文件 @
18bde2c5
...
...
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMB
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.WHEN_MISSING_CASES
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS
import
org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_WITH_BODY
...
...
@@ -504,7 +505,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
//)
// When expressions
map
.
put
(
NO_ELSE_IN_WHEN
,
"''when'' expression must be exhaustive
"
)
map
.
put
(
NO_ELSE_IN_WHEN
,
"''when'' expression must be exhaustive
, add necessary {0}"
,
WHEN_MISSING_CASES
)
map
.
put
(
INVALID_IF_AS_EXPRESSION
,
"'if' must have both main and 'else' branches if used as an expression"
)
// Extended checkers group
...
...
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt
浏览文件 @
18bde2c5
...
...
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import
org.jetbrains.kotlin.fir.FirElement
import
org.jetbrains.kotlin.fir.FirRenderer
import
org.jetbrains.kotlin.fir.declarations.*
import
org.jetbrains.kotlin.fir.expressions.WhenMissingCase
import
org.jetbrains.kotlin.fir.render
import
org.jetbrains.kotlin.fir.renderWithType
import
org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
...
...
@@ -88,4 +89,16 @@ object FirDiagnosticRenderers {
SYMBOL
.
render
(
symbol
)
}
}
private
const
val
WHEN_MISSING_LIMIT
=
7
val
WHEN_MISSING_CASES
=
Renderer
{
missingCases
:
List
<
WhenMissingCase
>
->
if
(
missingCases
.
firstOrNull
()
==
WhenMissingCase
.
Unknown
)
{
"'else' branch"
}
else
{
val
list
=
missingCases
.
joinToString
(
", "
,
limit
=
WHEN_MISSING_LIMIT
)
{
"'$it'"
}
val
branches
=
if
(
missingCases
.
size
>
1
)
"branches"
else
"branch"
"$list $branches or 'else' branch instead"
}
}
}
compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
浏览文件 @
18bde2c5
...
...
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import
org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import
org.jetbrains.kotlin.fir.declarations.FirClass
import
org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import
org.jetbrains.kotlin.fir.expressions.WhenMissingCase
import
org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import
org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import
org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
...
...
@@ -231,7 +232,7 @@ object FirErrors {
// TODO: val UNEXPECTED_SAFE_CALL by ...
// When expressions
val
NO_ELSE_IN_WHEN
by
error
0
<
FirSourceElement
,
KtWhenExpression
>(
SourceElementPositioningStrategies
.
WHEN_EXPRESSION
)
val
NO_ELSE_IN_WHEN
by
error
1
<
FirSourceElement
,
KtWhenExpression
,
List
<
WhenMissingCase
>
>(
SourceElementPositioningStrategies
.
WHEN_EXPRESSION
)
val
INVALID_IF_AS_EXPRESSION
by
error0
<
FirSourceElement
,
KtIfExpression
>(
SourceElementPositioningStrategies
.
IF_EXPRESSION
)
// Extended checkers group
...
...
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt
浏览文件 @
18bde2c5
此差异已折叠。
点击以展开。
compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt
浏览文件 @
18bde2c5
...
...
@@ -5,19 +5,61 @@
package
org.jetbrains.kotlin.fir.expressions
import
org.jetbrains.kotlin.fir.symbols.CallableId
import
org.jetbrains.kotlin.name.ClassId
sealed
class
ExhaustivenessStatus
{
object
Exhaustive
:
ExhaustivenessStatus
()
class
NotExhaustive
(
val
reasons
:
List
<
WhenMissingCase
>)
:
ExhaustivenessStatus
()
class
NotExhaustive
(
val
reasons
:
List
<
WhenMissingCase
>)
:
ExhaustivenessStatus
()
{
companion
object
{
val
NO_ELSE_BRANCH
=
NotExhaustive
(
listOf
(
WhenMissingCase
.
Unknown
))
}
}
}
sealed
class
WhenMissingCase
{
object
Unknown
:
WhenMissingCase
()
object
NullIsMissing
:
WhenMissingCase
()
class
BooleanIsMissing
(
val
value
:
Boolean
)
:
WhenMissingCase
()
class
IsTypeCheckIsMissing
(
val
classId
:
ClassId
)
:
WhenMissingCase
()
class
EnumCheckIsMissing
(
val
classId
:
ClassId
)
:
WhenMissingCase
()
sealed
class
WhenMissingCase
()
{
abstract
val
branchConditionText
:
String
object
Unknown
:
WhenMissingCase
()
{
override
fun
toString
():
String
=
"unknown"
override
val
branchConditionText
:
String
=
"else"
}
object
NullIsMissing
:
WhenMissingCase
()
{
override
val
branchConditionText
:
String
=
"null"
}
sealed
class
BooleanIsMissing
(
val
value
:
Boolean
)
:
WhenMissingCase
()
{
object
True
:
BooleanIsMissing
(
true
)
object
False
:
BooleanIsMissing
(
false
)
override
val
branchConditionText
:
String
=
value
.
toString
()
}
class
IsTypeCheckIsMissing
(
val
classId
:
ClassId
,
val
isSingleton
:
Boolean
)
:
WhenMissingCase
()
{
override
val
branchConditionText
:
String
=
run
{
val
fqName
=
classId
.
asSingleFqName
().
toString
()
if
(
isSingleton
)
fqName
else
"is $fqName"
}
override
fun
toString
():
String
{
val
name
=
classId
.
shortClassName
.
identifier
return
if
(
isSingleton
)
name
else
"is $name"
}
}
class
EnumCheckIsMissing
(
val
callableId
:
CallableId
)
:
WhenMissingCase
()
{
override
val
branchConditionText
:
String
=
callableId
.
asFqNameForDebugInfo
().
toString
()
override
fun
toString
():
String
{
return
callableId
.
callableName
.
identifier
}
}
override
fun
toString
():
String
{
return
branchConditionText
}
}
val
FirWhenExpression
.
isExhaustive
:
Boolean
...
...
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt
浏览文件 @
18bde2c5
...
...
@@ -18,6 +18,6 @@ fun test2(x: Stmt): String =
}
fun
test3
(
x
:
Expr
):
String
=
<!
NO_ELSE_IN_WHEN
!>
when
<!>
(
x
)
{
when
(
x
)
{
is
Stmt
->
"stmt"
}
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt
已删除
100644 → 0
浏览文件 @
2a1c9283
sealed
class
Base
{
sealed
class
A
:
Base
()
{
object
A1
:
A
()
sealed
class
A2
:
A
()
}
sealed
class
B
:
Base
()
{
sealed
class
B1
:
B
()
object
B2
:
B
()
}
fun
foo
()
=
when
(
this
)
{
is
A
->
1
is
B
.
B1
->
2
B
.
B2
->
3
// No else required
}
fun
bar
()
=
<!
NO_ELSE_IN_WHEN
!>
when
<!>
(
this
)
{
is
A
->
1
is
B
.
B1
->
2
}
fun
baz
()
=
when
(
this
)
{
is
A
->
1
B
.
B2
->
3
// No else required (no possible B1 instances)
}
fun
negated
()
=
when
(
this
)
{
!
is
A
->
1
A
.
A1
->
2
is
A
.
A2
->
3
}
}
compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt
浏览文件 @
18bde2c5
// FIR_IDENTICAL
sealed
class
Base
{
sealed
class
A
:
Base
()
{
object
A1
:
A
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录