Fixed one of the cases with lambda's returning Nothing

This commit is contained in:
Valentin Kipyatkov
2014-11-21 18:46:18 +03:00
parent c5afc219b9
commit 32a13502c5
4 changed files with 46 additions and 9 deletions
@@ -392,5 +392,10 @@ public fun Call.isSafeCall(): Boolean {
public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS
public fun JetTypeReference?.isProbablyNothing(): Boolean public fun JetTypeReference?.isProbablyNothing(): Boolean {
= (this?.getTypeElement() as? JetUserType)?.getReferencedName() == "Nothing" val userType = this?.getTypeElement() as? JetUserType ?: return false
return userType.isProbablyNothing()
}
public fun JetUserType?.isProbablyNothing(): Boolean
= this?.getReferencedName() == "Nothing"
@@ -25,10 +25,10 @@ import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.jet.JetNodeTypes import org.jetbrains.jet.JetNodeTypes
import org.jetbrains.jet.lang.psi.psiUtil.isProbablyNothing
import org.jetbrains.jet.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.jet.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import org.jetbrains.jet.lang.resolve.PartialBodyResolveProvider import org.jetbrains.jet.lang.resolve.PartialBodyResolveProvider
import org.jetbrains.jet.lang.psi.psiUtil.isProbablyNothing
//TODO: do resolve anonymous object's body //TODO: do resolve anonymous object's body
@@ -41,7 +41,7 @@ class PartialBodyResolveFilter(
private val statementMarks = StatementMarks() private val statementMarks = StatementMarks()
private val nothingFunctionNames = HashSet(probablyNothingCallableNames.functionNames()) private val nothingFunctionNames = HashSet(probablyNothingCallableNames.functionNames())
private val nothingPropertyNames = probablyNothingCallableNames.propertyNames() private val nothingVariableNames = HashSet(probablyNothingCallableNames.propertyNames())
override val filter: ((JetElement) -> Boolean)? = { it is JetExpression && statementMarks.statementMark(it) != MarkLevel.SKIP } override val filter: ((JetElement) -> Boolean)? = { it is JetExpression && statementMarks.statementMark(it) != MarkLevel.SKIP }
@@ -51,11 +51,21 @@ class PartialBodyResolveFilter(
"Should never be invoked on local declaration otherwise we may miss some local declarations with type Nothing") "Should never be invoked on local declaration otherwise we may miss some local declarations with type Nothing")
declaration.accept(object : JetVisitorVoid() { declaration.accept(object : JetVisitorVoid() {
override fun visitNamedFunction(function: JetNamedFunction) { override fun visitDeclaration(declaration: JetDeclaration) {
super.visitNamedFunction(function) super.visitDeclaration(declaration)
if (function.getTypeReference().isProbablyNothing()) { if (declaration is JetCallableDeclaration) {
nothingFunctionNames.add(function.getName()) if (declaration.getTypeReference().containsProbablyNothing()) {
val name = declaration.getName()
if (name != null) {
if (declaration is JetNamedFunction) {
nothingFunctionNames.add(name)
}
else {
nothingVariableNames.add(name)
}
}
}
} }
} }
@@ -338,7 +348,7 @@ class PartialBodyResolveFilter(
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) { override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) {
val name = expression.getReferencedName() val name = expression.getReferencedName()
if (name in nothingPropertyNames) { if (name in nothingVariableNames) {
result.add(expression) result.add(expression)
} }
} }
@@ -495,6 +505,22 @@ class PartialBodyResolveFilter(
= getLastChild()?.siblings(forward = false)?.firstIsInstanceOrNull<JetExpression>() = getLastChild()?.siblings(forward = false)?.firstIsInstanceOrNull<JetExpression>()
private fun PsiElement.isStatement() = this is JetExpression && getParent() is JetBlockExpression private fun PsiElement.isStatement() = this is JetExpression && getParent() is JetBlockExpression
private fun JetTypeReference?.containsProbablyNothing(): Boolean {
var result = false
this?.getTypeElement()?.accept(object : JetVisitorVoid() {
override fun visitJetElement(element: JetElement) {
element.acceptChildren(this)
}
override fun visitUserType(type: JetUserType) {
if (type.isProbablyNothing()) {
result = true
}
}
})
return result
}
} }
private inner class StatementMarks { private inner class StatementMarks {
@@ -276,6 +276,12 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("LambdaReturnsNothing2.kt")
public void testLambdaReturnsNothing2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LambdaReturnsNothing2.kt");
doTest(fileName);
}
@TestMetadata("LocalClass.kt") @TestMetadata("LocalClass.kt")
public void testLocalClass() throws Exception { public void testLocalClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LocalClass.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LocalClass.kt");