Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
硅谷海盗
kotlin
提交
891aebf3
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,发现更多精彩内容 >>
提交
891aebf3
编写于
5月 17, 2011
作者:
A
Andrey Breslav
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Basic support for when() expressions
上级
169f45b9
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
389 addition
and
45 deletion
+389
-45
grammar/src/when.grm
grammar/src/when.grm
+1
-1
idea/src/org/jetbrains/jet/JetNodeTypes.java
idea/src/org/jetbrains/jet/JetNodeTypes.java
+9
-9
idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
...c/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
+57
-1
idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
.../org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
+16
-6
idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java
idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java
+16
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenCondition.java
idea/src/org/jetbrains/jet/lang/psi/JetWhenCondition.java
+13
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java
.../src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java
+35
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java
...c/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java
+45
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java
...org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java
+29
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionWithExpression.java
...etbrains/jet/lang/psi/JetWhenConditionWithExpression.java
+25
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java
idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java
+5
-0
idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
+6
-0
idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java
idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java
+96
-19
idea/testData/checker/When.jet
idea/testData/checker/When.jet
+18
-0
idea/testData/psi/NewlinesInParentheses.txt
idea/testData/psi/NewlinesInParentheses.txt
+4
-2
idea/testData/psi/When.txt
idea/testData/psi/When.txt
+4
-2
idea/testData/psi/When_ERR.txt
idea/testData/psi/When_ERR.txt
+10
-5
未找到文件。
grammar/src/when.grm
浏览文件 @
891aebf3
...
...
@@ -16,7 +16,7 @@ whenConditionIf
whenCondition
: expression
:
"."
postfixUnaryExpression typeArguments? valueArguments?
:
("." | "?.")
postfixUnaryExpression typeArguments? valueArguments?
: ("in" | "!in") expression
: ("is" | "!is") isRHS
;
...
...
idea/src/org/jetbrains/jet/JetNodeTypes.java
浏览文件 @
891aebf3
...
...
@@ -111,22 +111,22 @@ public interface JetNodeTypes {
JetNodeType
HASH_QUALIFIED_EXPRESSION
=
new
JetNodeType
(
"HASH_QUALIFIED_EXPRESSION"
,
JetHashQualifiedExpression
.
class
);
JetNodeType
SAFE_ACCESS_EXPRESSION
=
new
JetNodeType
(
"SAFE_ACCESS_EXPRESSION"
,
JetSafeQualifiedExpression
.
class
);
JetNodeType
PREDICATE_EXPRESSION
=
new
JetNodeType
(
"PREDICATE_EXPRESSION"
,
JetPredicateExpression
.
class
);
JetNodeType
DECOMPOSER_PATTERN
=
new
JetNodeType
(
"DECOMPOSER_PATTERN"
);
JetNodeType
TUPLE_PATTERN
=
new
JetNodeType
(
"TUPLE_PATTERN"
);
JetNodeType
DECOMPOSER_PATTERN
=
new
JetNodeType
(
"DECOMPOSER_PATTERN"
,
JetPattern
.
class
);
// TODO
JetNodeType
TUPLE_PATTERN
=
new
JetNodeType
(
"TUPLE_PATTERN"
,
JetPattern
.
class
);
// TODO
JetNodeType
OBJECT_LITERAL
=
new
JetNodeType
(
"OBJECT_LITERAL"
,
JetObjectLiteralExpression
.
class
);
JetNodeType
ROOT_NAMESPACE
=
new
JetNodeType
(
"ROOT_NAMESPACE"
,
JetRootNamespaceExpression
.
class
);
JetNodeType
DECOMPOSER_ARGUMENT_LIST
=
new
JetNodeType
(
"DECOMPOSER_ARGUMENT_LIST"
);
JetNodeType
DECOMPOSER_ARGUMENT
=
new
JetNodeType
(
"DECOMPOSER_ARGUMENT"
);
JetNodeType
TYPE_PATTERN
=
new
JetNodeType
(
"TYPE_PATTERN"
,
JetTypePattern
.
class
);
JetNodeType
EXPRESSION_PATTERN
=
new
JetNodeType
(
"EXPRESSION_PATTERN"
);
JetNodeType
BINDING_PATTERN
=
new
JetNodeType
(
"BINDING_PATTERN"
);
JetNodeType
WILDCARD_PATTERN
=
new
JetNodeType
(
"WILDCARD_PATTERN"
);
JetNodeType
EXPRESSION_PATTERN
=
new
JetNodeType
(
"EXPRESSION_PATTERN"
,
JetPattern
.
class
);
// TODO
JetNodeType
BINDING_PATTERN
=
new
JetNodeType
(
"BINDING_PATTERN"
,
JetPattern
.
class
);
// TODO
JetNodeType
WILDCARD_PATTERN
=
new
JetNodeType
(
"WILDCARD_PATTERN"
,
JetPattern
.
class
);
// TODO
JetNodeType
WHEN
=
new
JetNodeType
(
"WHEN"
,
JetWhenExpression
.
class
);
JetNodeType
WHEN_ENTRY
=
new
JetNodeType
(
"WHEN_ENTRY"
,
JetWhenEntry
.
class
);
JetNodeType
WHEN_CONDITION_IN_RANGE
=
new
JetNodeType
(
"WHEN_CONDITION_IN_RANGE"
);
JetNodeType
WHEN_CONDITION_IS_PATTERN
=
new
JetNodeType
(
"WHEN_CONDITION_IS_PATTERN"
);
JetNodeType
WHEN_CONDITION_CALL
=
new
JetNodeType
(
"WHEN_CONDITION_CALL"
);
JetNodeType
WHEN_CONDITION_EXPRESSION
=
new
JetNodeType
(
"WHEN_CONDITION_EXPRESSION"
);
JetNodeType
WHEN_CONDITION_IN_RANGE
=
new
JetNodeType
(
"WHEN_CONDITION_IN_RANGE"
,
JetWhenConditionInRange
.
class
);
JetNodeType
WHEN_CONDITION_IS_PATTERN
=
new
JetNodeType
(
"WHEN_CONDITION_IS_PATTERN"
,
JetWhenConditionIsPattern
.
class
);
JetNodeType
WHEN_CONDITION_CALL
=
new
JetNodeType
(
"WHEN_CONDITION_CALL"
,
JetWhenConditionCall
.
class
);
JetNodeType
WHEN_CONDITION_EXPRESSION
=
new
JetNodeType
(
"WHEN_CONDITION_EXPRESSION"
,
JetWhenConditionWithExpression
.
class
);
JetNodeType
TUPLE_PATTERN_ENTRY
=
new
JetNodeType
(
"TUPLE_PATTERN_ENTRY"
);
JetNodeType
NULLABLE_TYPE
=
new
JetNodeType
(
"NULLABLE_TYPE"
,
JetNullableType
.
class
);
JetNodeType
TYPE_PROJECTION
=
new
JetNodeType
(
"TYPE_PROJECTION"
,
JetTypeProjection
.
class
);
...
...
idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
浏览文件 @
891aebf3
...
...
@@ -96,7 +96,8 @@ public class JetControlFlowProcessor {
this
.
inCondition
=
inCondition
;
}
private
void
value
(
@NotNull
JetElement
element
,
boolean
preferBlock
,
boolean
inCondition
)
{
private
void
value
(
@Nullable
JetElement
element
,
boolean
preferBlock
,
boolean
inCondition
)
{
if
(
element
==
null
)
return
;
CFPVisitor
visitor
;
if
(
this
.
preferBlock
==
preferBlock
&&
this
.
inCondition
==
inCondition
)
{
visitor
=
this
;
...
...
@@ -609,6 +610,61 @@ public class JetControlFlowProcessor {
builder
.
read
(
expression
);
}
@Override
public
void
visitWhenExpression
(
JetWhenExpression
expression
)
{
// TODO : no more than one else
// TODO : else must be the last
JetExpression
subjectExpression
=
expression
.
getSubjectExpression
();
if
(
subjectExpression
!=
null
)
{
value
(
subjectExpression
,
false
,
inCondition
);
}
Label
nextLabel
=
builder
.
createUnboundLabel
();
for
(
JetWhenEntry
whenEntry
:
expression
.
getEntries
())
{
if
(
whenEntry
.
getSubWhen
()
!=
null
)
throw
new
UnsupportedOperationException
();
// TODO
if
(
whenEntry
.
isElseContinue
())
throw
new
UnsupportedOperationException
();
// TODO
JetWhenCondition
condition
=
whenEntry
.
getCondition
();
if
(
condition
!=
null
)
{
condition
.
accept
(
new
JetVisitor
()
{
@Override
public
void
visitWhenConditionWithExpression
(
JetWhenConditionWithExpression
condition
)
{
value
(
condition
.
getExpression
(),
false
,
inCondition
);
// TODO : inCondition?
}
@Override
public
void
visitWhenConditionCall
(
JetWhenConditionCall
condition
)
{
value
(
condition
.
getCallSuffixExpression
(),
false
,
inCondition
);
// TODO : inCondition?
}
@Override
public
void
visitWhenConditionInRange
(
JetWhenConditionInRange
condition
)
{
value
(
condition
.
getRangeExpression
(),
false
,
inCondition
);
// TODO : inCondition?
value
(
condition
.
getOperationReference
(),
false
,
inCondition
);
// TODO : inCondition?
// TODO : read the call to contains()...
}
@Override
public
void
visitWhenConditionIsPattern
(
JetWhenConditionIsPattern
condition
)
{
super
.
visitWhenConditionIsPattern
(
condition
);
// TODO
}
@Override
public
void
visitJetElement
(
JetElement
elem
)
{
throw
new
UnsupportedOperationException
();
}
});
}
builder
.
nondeterministicJump
(
nextLabel
);
value
(
whenEntry
.
getExpression
(),
true
,
inCondition
);
builder
.
bindLabel
(
nextLabel
);
nextLabel
=
builder
.
createUnboundLabel
();
}
}
@Override
public
void
visitTypeProjection
(
JetTypeProjection
typeProjection
)
{
// TODO : Support Type Arguments. Class object may be initialized at this point");
...
...
idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
浏览文件 @
891aebf3
...
...
@@ -706,7 +706,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenCondition
* : expression
* :
"
." postfixExpression typeArguments? valueArguments?
* :
("." | "?
." postfixExpression typeArguments? valueArguments?
* : ("in" | "!in") expression
* : ("is" | "!is") isRHS
* ;
...
...
@@ -715,7 +715,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder
.
Marker
condition
=
mark
();
myBuilder
.
disableNewlines
();
if
(
at
(
IN_KEYWORD
)
||
at
(
NOT_IN
))
{
PsiBuilder
.
Marker
mark
=
mark
();
advance
();
// IN_KEYWORD or NOT_IN
mark
.
done
(
OPERATION_REFERENCE
);
if
(
atSet
(
WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW
))
{
error
(
"Expecting an element"
);
...
...
@@ -732,13 +735,20 @@ public class JetExpressionParsing extends AbstractJetParsing {
parsePattern
();
}
condition
.
done
(
WHEN_CONDITION_IS_PATTERN
);
}
else
if
(
at
(
DOT
))
{
advance
();
// DOT
}
else
if
(
at
(
DOT
)
||
at
(
SAFE_ACCESS
))
{
advance
();
// DOT or SAFE_ACCESS
PsiBuilder
.
Marker
mark
=
mark
();
parsePostfixExpression
();
myJetParsing
.
parseTypeArgumentList
();
if
(
at
(
LPAR
))
{
parseValueArgumentList
();
if
(
parseCallSuffix
())
{
mark
.
done
(
CALL_EXPRESSION
);
}
else
{
mark
.
drop
();
}
// myJetParsing.parseTypeArgumentList();
// if (at(LPAR)) {
// parseValueArgumentList();
// }
condition
.
done
(
WHEN_CONDITION_CALL
);
}
else
{
if
(
atSet
(
WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW
))
{
...
...
idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java
浏览文件 @
891aebf3
...
...
@@ -349,4 +349,20 @@ public class JetVisitor extends PsiElementVisitor {
public
void
visitIsExpression
(
JetIsExpression
expression
)
{
visitExpression
(
expression
);
}
public
void
visitWhenConditionWithExpression
(
JetWhenConditionWithExpression
condition
)
{
visitJetElement
(
condition
);
}
public
void
visitWhenConditionCall
(
JetWhenConditionCall
condition
)
{
visitJetElement
(
condition
);
}
public
void
visitWhenConditionIsPattern
(
JetWhenConditionIsPattern
condition
)
{
visitJetElement
(
condition
);
}
public
void
visitWhenConditionInRange
(
JetWhenConditionInRange
condition
)
{
visitJetElement
(
condition
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenCondition.java
0 → 100644
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.psi
;
import
com.intellij.lang.ASTNode
;
import
org.jetbrains.annotations.NotNull
;
/**
* @author abreslav
*/
public
abstract
class
JetWhenCondition
extends
JetElement
{
public
JetWhenCondition
(
@NotNull
ASTNode
node
)
{
super
(
node
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java
0 → 100644
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.psi
;
import
com.intellij.lang.ASTNode
;
import
com.intellij.psi.tree.TokenSet
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.jet.lexer.JetTokens
;
/**
* @author abreslav
*/
public
class
JetWhenConditionCall
extends
JetWhenCondition
{
public
JetWhenConditionCall
(
@NotNull
ASTNode
node
)
{
super
(
node
);
}
public
boolean
isSafeCall
()
{
return
getNode
().
findChildByType
(
JetTokens
.
SAFE_ACCESS
)
!=
null
;
}
@NotNull
public
ASTNode
getOperationTokenNode
()
{
return
getNode
().
findChildByType
(
TokenSet
.
create
(
JetTokens
.
SAFE_ACCESS
,
JetTokens
.
DOT
));
}
@Nullable
@IfNotParsed
public
JetExpression
getCallSuffixExpression
()
{
return
findChildByClass
(
JetExpression
.
class
);
}
@Override
public
void
accept
(
@NotNull
JetVisitor
visitor
)
{
visitor
.
visitWhenConditionCall
(
this
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java
0 → 100644
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.psi
;
import
com.intellij.lang.ASTNode
;
import
com.intellij.psi.PsiElement
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.jet.JetNodeTypes
;
import
org.jetbrains.jet.lexer.JetTokens
;
/**
* @author abreslav
*/
public
class
JetWhenConditionInRange
extends
JetWhenCondition
{
public
JetWhenConditionInRange
(
@NotNull
ASTNode
node
)
{
super
(
node
);
}
public
boolean
isNegated
()
{
return
getNode
().
findChildByType
(
JetTokens
.
NOT_IN
)
!=
null
;
}
@Nullable
@IfNotParsed
public
JetExpression
getRangeExpression
()
{
// Copied from JetBinaryExpression
ASTNode
node
=
getOperationReference
().
getNode
().
getTreeNext
();
while
(
node
!=
null
)
{
PsiElement
psi
=
node
.
getPsi
();
if
(
psi
instanceof
JetExpression
)
{
return
(
JetExpression
)
psi
;
}
node
=
node
.
getTreeNext
();
}
return
null
;
}
@Override
public
void
accept
(
@NotNull
JetVisitor
visitor
)
{
visitor
.
visitWhenConditionInRange
(
this
);
}
public
JetSimpleNameExpression
getOperationReference
()
{
return
(
JetSimpleNameExpression
)
findChildByType
(
JetNodeTypes
.
OPERATION_REFERENCE
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java
0 → 100644
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.psi
;
import
com.intellij.lang.ASTNode
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.jet.lexer.JetTokens
;
/**
* @author abreslav
*/
public
class
JetWhenConditionIsPattern
extends
JetWhenCondition
{
public
JetWhenConditionIsPattern
(
@NotNull
ASTNode
node
)
{
super
(
node
);
}
public
boolean
isNegated
()
{
return
getNode
().
findChildByType
(
JetTokens
.
NOT_IS
)
!=
null
;
}
@Nullable
@IfNotParsed
public
JetPattern
getPattern
()
{
return
findChildByClass
(
JetPattern
.
class
);
}
@Override
public
void
accept
(
@NotNull
JetVisitor
visitor
)
{
visitor
.
visitWhenConditionIsPattern
(
this
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionWithExpression.java
0 → 100644
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.psi
;
import
com.intellij.lang.ASTNode
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
/**
* @author abreslav
*/
public
class
JetWhenConditionWithExpression
extends
JetWhenCondition
{
public
JetWhenConditionWithExpression
(
@NotNull
ASTNode
node
)
{
super
(
node
);
}
@Nullable
@IfNotParsed
public
JetExpression
getExpression
()
{
return
findChildByClass
(
JetExpression
.
class
);
}
@Override
public
void
accept
(
@NotNull
JetVisitor
visitor
)
{
visitor
.
visitWhenConditionWithExpression
(
this
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java
浏览文件 @
891aebf3
...
...
@@ -37,4 +37,9 @@ public class JetWhenEntry extends JetElement {
public
void
accept
(
@NotNull
JetVisitor
visitor
)
{
visitor
.
visitWhenEntry
(
this
);
}
@Nullable
public
JetWhenCondition
getCondition
()
{
return
findChildByClass
(
JetWhenCondition
.
class
);
}
}
idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
浏览文件 @
891aebf3
...
...
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import
com.intellij.lang.ASTNode
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.jet.JetNodeTypes
;
import
java.util.List
;
...
...
@@ -19,6 +20,11 @@ public class JetWhenExpression extends JetExpression {
return
findChildrenByType
(
JetNodeTypes
.
WHEN_ENTRY
);
}
@Nullable
@IfNotParsed
public
JetExpression
getSubjectExpression
()
{
return
findChildByClass
(
JetExpression
.
class
);
}
@Override
public
void
accept
(
JetVisitor
visitor
)
{
visitor
.
visitWhenExpression
(
this
);
...
...
idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java
浏览文件 @
891aebf3
package
org.jetbrains.jet.lang.types
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Sets
;
import
com.intellij.lang.ASTNode
;
import
com.intellij.psi.PsiElement
;
import
com.intellij.psi.tree.IElementType
;
...
...
@@ -151,7 +152,7 @@ public class JetTypeInferrer {
public
void
visitQualifiedExpression
(
JetQualifiedExpression
expression
)
{
// . or ?.
JetType
receiverType
=
getType
(
scope
,
expression
.
getReceiverExpression
(),
false
);
checkNullSafety
(
receiverType
,
expression
);
checkNullSafety
(
receiverType
,
expression
.
getOperationTokenNode
()
);
JetExpression
selectorExpression
=
expression
.
getSelectorExpression
();
if
(
selectorExpression
instanceof
JetSimpleNameExpression
)
{
...
...
@@ -191,19 +192,20 @@ public class JetTypeInferrer {
return
wrapForTracing
(
result
[
0
],
reference
[
0
],
argumentList
,
true
);
}
private
void
checkNullSafety
(
JetType
receiverType
,
JetQualifiedExpression
expression
)
{
private
void
checkNullSafety
(
JetType
receiverType
,
ASTNode
operationTokenNode
)
{
if
(
receiverType
!=
null
)
{
boolean
namespaceType
=
receiverType
instanceof
NamespaceType
;
boolean
nullable
=
!
namespaceType
&&
receiverType
.
isNullable
();
if
(
nullable
&&
expression
.
getOperationSign
()
==
JetTokens
.
DOT
)
{
trace
.
getErrorHandler
().
genericError
(
expression
.
getOperationTokenNode
(),
"Only safe calls (?.) are allowed on a nullable receiver of type "
+
receiverType
);
IElementType
operationSign
=
operationTokenNode
.
getElementType
();
if
(
nullable
&&
operationSign
==
JetTokens
.
DOT
)
{
trace
.
getErrorHandler
().
genericError
(
operationTokenNode
,
"Only safe calls (?.) are allowed on a nullable receiver of type "
+
receiverType
);
}
else
if
(!
nullable
&&
expression
.
getOperationSign
()
==
JetTokens
.
SAFE_ACCESS
)
{
else
if
(!
nullable
&&
operationSign
==
JetTokens
.
SAFE_ACCESS
)
{
if
(
namespaceType
)
{
trace
.
getErrorHandler
().
genericError
(
expression
.
getOperationTokenNode
()
,
"Safe calls are not allowed on namespaces"
);
trace
.
getErrorHandler
().
genericError
(
operationTokenNode
,
"Safe calls are not allowed on namespaces"
);
}
else
{
trace
.
getErrorHandler
().
genericWarning
(
expression
.
getOperationTokenNode
()
,
"Unnecessary safe call on a non-null receiver of type "
+
receiverType
);
trace
.
getErrorHandler
().
genericWarning
(
operationTokenNode
,
"Unnecessary safe call on a non-null receiver of type "
+
receiverType
);
}
}
}
...
...
@@ -378,7 +380,10 @@ public class JetTypeInferrer {
}
else
{
JetExpression
resultExpression
=
entry
.
getExpression
();
if
(
resultExpression
!=
null
)
{
result
.
add
(
getType
(
scope
,
resultExpression
,
true
));
JetType
type
=
getType
(
scope
,
resultExpression
,
true
);
if
(
type
!=
null
)
{
result
.
add
(
type
);
}
}
}
}
...
...
@@ -964,11 +969,75 @@ public class JetTypeInferrer {
}
@Override
public
void
visitWhenExpression
(
JetWhenExpression
expression
)
{
public
void
visitWhenExpression
(
final
JetWhenExpression
expression
)
{
// TODO :change scope according to the bound value in the when header
List
<
JetType
>
expressions
=
new
ArrayList
<
JetType
>();
collectAllReturnTypes
(
expression
,
scope
,
expressions
);
result
=
semanticServices
.
getTypeChecker
().
commonSupertype
(
expressions
);
final
JetExpression
subjectExpression
=
expression
.
getSubjectExpression
();
JetType
subjectType
=
null
;
if
(
subjectExpression
!=
null
)
{
subjectType
=
getType
(
scope
,
subjectExpression
,
false
);
}
// TODO : exhaustive patterns
for
(
JetWhenEntry
whenEntry
:
expression
.
getEntries
())
{
final
JetType
finalSubjectType
=
subjectType
;
JetWhenCondition
condition
=
whenEntry
.
getCondition
();
if
(
condition
!=
null
)
{
condition
.
accept
(
new
JetVisitor
()
{
@Override
public
void
visitWhenConditionWithExpression
(
JetWhenConditionWithExpression
condition
)
{
JetExpression
conditionExpression
=
condition
.
getExpression
();
if
(
conditionExpression
!=
null
)
{
JetType
type
=
getType
(
scope
,
conditionExpression
,
false
);
if
(
type
!=
null
&&
finalSubjectType
!=
null
)
{
if
(
TypeUtils
.
intersect
(
semanticServices
.
getTypeChecker
(),
Sets
.
newHashSet
(
finalSubjectType
,
type
))
==
null
)
{
trace
.
getErrorHandler
().
genericError
(
conditionExpression
.
getNode
(),
"This condition can never hold"
);
}
}
}
}
@Override
public
void
visitWhenConditionCall
(
JetWhenConditionCall
condition
)
{
checkNullSafety
(
finalSubjectType
,
condition
.
getOperationTokenNode
());
JetExpression
callSuffixExpression
=
condition
.
getCallSuffixExpression
();
JetScope
compositeScope
=
new
ScopeWithReceiver
(
scope
,
finalSubjectType
);
if
(
callSuffixExpression
!=
null
)
{
JetType
selectorReturnType
=
getType
(
compositeScope
,
callSuffixExpression
,
false
);
ensureBooleanResultWithCustomSubject
(
callSuffixExpression
,
selectorReturnType
,
"This expression"
);
}
}
@Override
public
void
visitWhenConditionInRange
(
JetWhenConditionInRange
condition
)
{
JetExpression
rangeExpression
=
condition
.
getRangeExpression
();
if
(
rangeExpression
!=
null
)
{
checkInExpression
(
condition
.
getOperationReference
(),
subjectExpression
,
rangeExpression
);
}
}
@Override
public
void
visitWhenConditionIsPattern
(
JetWhenConditionIsPattern
condition
)
{
super
.
visitWhenConditionIsPattern
(
condition
);
// TODO
}
@Override
public
void
visitJetElement
(
JetElement
elem
)
{
trace
.
getErrorHandler
().
genericError
(
elem
.
getNode
(),
"Unsupported [JetTypeInferrer] : "
+
elem
);
}
});
}
}
List
<
JetType
>
expressionTypes
=
new
ArrayList
<
JetType
>();
collectAllReturnTypes
(
expression
,
scope
,
expressionTypes
);
if
(!
expressionTypes
.
isEmpty
())
{
result
=
semanticServices
.
getTypeChecker
().
commonSupertype
(
expressionTypes
);
}
else
{
trace
.
getErrorHandler
().
genericError
(
expression
.
getNode
(),
"Entries required for when-expression"
);
// TODO : Scope, and maybe this should not an error
}
}
@Override
...
...
@@ -1226,10 +1295,10 @@ public class JetTypeInferrer {
JetExpression
receiverExpression
=
expression
.
getReceiverExpression
();
JetType
receiverType
=
new
TypeInferrerVisitorWithNamespaces
(
scope
,
false
).
getType
(
receiverExpression
);
if
(
receiverType
!=
null
)
{
checkNullSafety
(
receiverType
,
expression
);
checkNullSafety
(
receiverType
,
expression
.
getOperationTokenNode
()
);
JetType
selectorReturnType
=
getSelectorReturnType
(
receiverType
,
selectorExpression
);
if
(
expression
.
getOperationSign
()
==
JetTokens
.
QUEST
)
{
if
(
selectorReturnType
!=
null
&&
!
isBoolean
(
selectorReturnType
))
{
if
(
selectorReturnType
!=
null
&&
!
isBoolean
(
selectorReturnType
)
&&
selectorExpression
!=
null
)
{
// TODO : more comprehensible error message
trace
.
getErrorHandler
().
typeMismatch
(
selectorExpression
,
semanticServices
.
getStandardLibrary
().
getBooleanType
(),
selectorReturnType
);
}
...
...
@@ -1395,9 +1464,7 @@ public class JetTypeInferrer {
result
=
ErrorUtils
.
createErrorType
(
"No right argument"
);
// TODO
return
;
}
String
name
=
"contains"
;
JetType
containsType
=
getTypeForBinaryCall
(
scope
,
right
,
expression
.
getOperationReference
(),
expression
.
getLeft
(),
name
,
true
);
ensureBooleanResult
(
operationSign
,
name
,
containsType
);
checkInExpression
(
operationSign
,
left
,
right
);
result
=
semanticServices
.
getStandardLibrary
().
getBooleanType
();
}
else
if
(
operationType
==
JetTokens
.
ANDAND
||
operationType
==
JetTokens
.
OROR
)
{
...
...
@@ -1428,6 +1495,12 @@ public class JetTypeInferrer {
}
}
private
void
checkInExpression
(
JetSimpleNameExpression
operationSign
,
JetExpression
left
,
JetExpression
right
)
{
String
name
=
"contains"
;
JetType
containsType
=
getTypeForBinaryCall
(
scope
,
right
,
operationSign
,
left
,
name
,
true
);
ensureBooleanResult
(
operationSign
,
name
,
containsType
);
}
private
void
ensureNonemptyIntersectionOfOperandTypes
(
JetBinaryExpression
expression
)
{
JetSimpleNameExpression
operationSign
=
expression
.
getOperationReference
();
JetExpression
left
=
expression
.
getLeft
();
...
...
@@ -1459,11 +1532,15 @@ public class JetTypeInferrer {
trace
.
getErrorHandler
().
genericError
(
expression
.
getNode
(),
"Assignments are not expressions, and only expressions are allowed in this context"
);
}
private
boolean
ensureBooleanResult
(
JetSimpleNameExpression
operationSign
,
String
name
,
JetType
resultType
)
{
private
boolean
ensureBooleanResult
(
JetExpression
operationSign
,
String
name
,
JetType
resultType
)
{
return
ensureBooleanResultWithCustomSubject
(
operationSign
,
resultType
,
"'"
+
name
+
"'"
);
}
private
boolean
ensureBooleanResultWithCustomSubject
(
JetExpression
operationSign
,
JetType
resultType
,
String
subjectName
)
{
if
(
resultType
!=
null
)
{
// TODO : Relax?
if
(!
isBoolean
(
resultType
))
{
trace
.
getErrorHandler
().
genericError
(
operationSign
.
getNode
(),
"'"
+
name
+
"'
must return Boolean but returns "
+
resultType
);
trace
.
getErrorHandler
().
genericError
(
operationSign
.
getNode
(),
subjectName
+
"
must return Boolean but returns "
+
resultType
);
return
false
;
}
}
...
...
idea/testData/checker/When.jet
0 → 100644
浏览文件 @
891aebf3
fun foo() {
val s = ""
val x = 1
when (x) {
<error>s</error> => 1
1 => 1
1 + <error>a</error> => 1
in 1..<error>a</error> => 1
!in 1..<error>a</error> => 1
.<error>a</error> => 1
.equals(1).<error>a</error> => 1
<warning>?.</warning>equals(1) => 1
}
when (<warning>x</warning>?:null) {
<error>.</error>equals(1) => 1
?.equals(1).equals(2) => 1
}
}
\ No newline at end of file
idea/testData/psi/NewlinesInParentheses.txt
浏览文件 @
891aebf3
...
...
@@ -254,7 +254,8 @@ JetFile: NewlinesInParentheses.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
...
...
@@ -290,7 +291,8 @@ JetFile: NewlinesInParentheses.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
...
...
idea/testData/psi/When.txt
浏览文件 @
891aebf3
...
...
@@ -755,7 +755,8 @@ JetFile: When.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
INTEGER_CONSTANT
...
...
@@ -772,7 +773,8 @@ JetFile: When.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
...
...
idea/testData/psi/When_ERR.txt
浏览文件 @
891aebf3
...
...
@@ -59,7 +59,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
...
...
@@ -70,7 +71,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
...
...
@@ -127,7 +129,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
...
...
@@ -137,7 +140,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
...
...
@@ -147,7 +151,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录