Partial body resolve filter: more correct lambda resolve for return

This commit is contained in:
Valentin Kipyatkov
2014-11-20 13:10:33 +03:00
parent 59cc441fc5
commit 4503adb7fc
4 changed files with 37 additions and 18 deletions
@@ -83,7 +83,8 @@ class PartialBodyResolveFilter(
val smartCastPlaces = potentialSmartCastPlaces(statement) val smartCastPlaces = potentialSmartCastPlaces(statement)
if (!smartCastPlaces.isEmpty()) { if (!smartCastPlaces.isEmpty()) {
addStatementToResolve(statement) addStatementToResolve(statement)
statementsToResolve.addStatementsForPlaces(smartCastPlaces.values().flatMap { it }) //TODO: do we really need correct resolve for ALL smart cast places?
addStatementsToResolveForPlaces(smartCastPlaces.values().flatMap { it })
} }
else if (statement is JetDeclaration) { else if (statement is JetDeclaration) {
addStatementToResolve(statement) addStatementToResolve(statement)
@@ -94,25 +95,25 @@ class PartialBodyResolveFilter(
addStatementsToResolve(parent) addStatementsToResolve(parent)
} }
private fun addStatementToResolve(statement: JetExpression) { private fun addStatementToResolve(statement: JetExpression): Boolean {
assert(statement.getParent() is JetBlockExpression) assert(statement.getParent() is JetBlockExpression)
if (statementsToResolve.add(statement)) { if (!statementsToResolve.add(statement)) return false
// search for code blocks inside statement and make sure its values will be resolved // search for code blocks inside statement and make sure its values will be resolved
statement.accept(object : JetVisitorVoid(){ statement.accept(object : JetVisitorVoid(){
override fun visitBlockExpression(expression: JetBlockExpression) { override fun visitBlockExpression(expression: JetBlockExpression) {
if (isValueNeeded(expression)) { if (isValueNeeded(expression)) {
val value = expression.lastStatement() val value = expression.lastStatement()
if (value != null) { if (value != null) {
addStatementsToResolve(value) addStatementsToResolve(value)
}
} }
} }
}
override fun visitJetElement(element: JetElement) { override fun visitJetElement(element: JetElement) {
element.acceptChildren(this) element.acceptChildren(this)
} }
}) })
} return true
} }
/** /**
@@ -351,11 +352,11 @@ class PartialBodyResolveFilter(
private fun JetElement.noControlFlowInside() = this is JetFunction || this is JetClass || this is JetClassBody private fun JetElement.noControlFlowInside() = this is JetFunction || this is JetClass || this is JetClassBody
private fun MutableSet<JetExpression>.addStatementsForPlaces(places: Collection<JetExpression>) { private fun addStatementsToResolveForPlaces(places: Collection<JetExpression>) {
for (place in places) { for (place in places) {
var parent: PsiElement = place var parent: PsiElement = place
while (true) { while (true) {
if (parent.isStatement() && !add(parent as JetExpression)) break if (parent.isStatement() && !addStatementToResolve(parent as JetExpression)) break
parent = parent.getParent() parent = parent.getParent()
} }
} }
@@ -0,0 +1,3 @@
Resolve target: value-parameter val p: kotlin.String? smart-cast to kotlin.String
Skipped statements:
println()
@@ -0,0 +1,9 @@
fun foo(p: String?): () -> String {
if (p == null) {
return {
println()
"a"
}
}
<caret>p.size
}
@@ -264,6 +264,12 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ReturnLambda.kt")
public void testReturnLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/ReturnLambda.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt") @TestMetadata("Simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/Simple.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/Simple.kt");