diff --git a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt index 2b358f5105b..4c1e951998f 100644 --- a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt +++ b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt @@ -70,6 +70,7 @@ class PartialBodyResolveFilter( return statement in statementsToResolve } + tailRecursive private fun addStatementsToResolve(element: JetElement) { if (element == body) return val parent = element.getParent() as? JetElement ?: return @@ -89,7 +90,7 @@ class PartialBodyResolveFilter( val smartCastPlaces = potentialSmartCastPlaces(statement) if (!smartCastPlaces.isEmpty()) { statementsToResolve.add(statement) - statementsToResolve.addStatementsForPlaces(statement, smartCastPlaces.values().flatMap { it }) + statementsToResolve.addStatementsForPlaces(smartCastPlaces.values().flatMap { it }) } else if (statement is JetDeclaration) { statementsToResolve.add(statement) @@ -113,22 +114,12 @@ class PartialBodyResolveFilter( val map = HashMap>(0) fun addPlace(name: String, place: JetExpression) { - var list = map[name] - if (list == null) { - list = ArrayList(1) - map[name] = list - } - list!!.add(place) + map.getOrPut(name, { ArrayList(1) }).add(place) } fun addPlaces(name: String, places: Collection) { assert(!places.isEmpty()) - var list = map[name] - if (list == null) { - list = ArrayList(places.size) - map[name] = list - } - list!!.addAll(places) + map.getOrPut(name, { ArrayList(places.size) }).addAll(places) } fun addIfCanBeSmartCasted(expression: JetExpression) { @@ -138,7 +129,7 @@ class PartialBodyResolveFilter( } } - expression.accept(object : ControlFlowVisitor(){ + expression.accept(object : ControlFlowVisitor() { override fun visitPostfixExpression(expression: JetPostfixExpression) { expression.acceptChildren(this) @@ -339,14 +330,11 @@ class PartialBodyResolveFilter( private fun JetElement.noControlFlowInside() = this is JetFunction || this is JetClass || this is JetClassBody - private fun MutableSet.addStatementsForPlaces(thisStatement: JetExpression, places: Collection) { - @PlacesLoop + private fun MutableSet.addStatementsForPlaces(places: Collection) { for (place in places) { var parent: PsiElement = place - while (parent != thisStatement) { - if (parent.isStatement()) { - if (!add(parent as JetExpression)) continue@PlacesLoop - } + while (true) { + if (parent.isStatement() && !add(parent as JetExpression)) break parent = parent.getParent() } } @@ -398,6 +386,6 @@ class PartialBodyResolveFilter( } private fun JetBlockExpression.lastStatement(): JetExpression? - = getLastChild().siblings(forward = false).filterIsInstance().firstOrNull() + = getLastChild()?.siblings(forward = false)?.filterIsInstance()?.firstOrNull() } diff --git a/idea/tests/org/jetbrains/jet/resolve/AbstractPartialBodyResolveTest.kt b/idea/tests/org/jetbrains/jet/resolve/AbstractPartialBodyResolveTest.kt index d96b53a0218..29a5eb2565f 100644 --- a/idea/tests/org/jetbrains/jet/resolve/AbstractPartialBodyResolveTest.kt +++ b/idea/tests/org/jetbrains/jet/resolve/AbstractPartialBodyResolveTest.kt @@ -30,12 +30,12 @@ import java.io.File import org.jetbrains.jet.lang.psi.JetBlockExpression import org.junit.Assert import org.jetbrains.jet.lang.types.JetType -import org.jetbrains.jet.lang.psi.psiUtil.parents import org.jetbrains.jet.renderer.DescriptorRenderer import org.jetbrains.jet.lang.descriptors.VariableDescriptor import org.jetbrains.jet.lang.psi.JetSimpleNameExpression import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression import org.jetbrains.jet.plugin.caches.resolve.getResolutionFacade +import org.jetbrains.jet.lang.psi.psiUtil.parents public abstract class AbstractPartialBodyResolveTest : JetLightCodeInsightFixtureTestCase() { override fun getTestDataPath() = JetTestCaseBuilder.getHomeDirectory() @@ -76,7 +76,13 @@ public abstract class AbstractPartialBodyResolveTest : JetLightCodeInsightFixtur Assert.assertEquals(target2.presentation(type2), target1.presentation(type1)) } - private fun doResolve(refExpression: JetSimpleNameExpression, bindingContext: BindingContext): Triple> { + private data class ResolveData( + val target: DeclarationDescriptor?, + val type: JetType?, + val processedStatements: Collection + ) + + private fun doResolve(refExpression: JetSimpleNameExpression, bindingContext: BindingContext): ResolveData { val target = bindingContext[BindingContext.REFERENCE_TARGET, refExpression] val processedStatements = bindingContext.getSliceContents(BindingContext.PROCESSED) @@ -93,7 +99,7 @@ public abstract class AbstractPartialBodyResolveTest : JetLightCodeInsightFixtur } val type = bindingContext[BindingContext.EXPRESSION_TYPE, expressionWithType] - return Triple(target, type, processedStatements) + return ResolveData(target, type, processedStatements) } private fun DeclarationDescriptor?.presentation(type: JetType?): String {