Caching of partial body resolve

This commit is contained in:
Valentin Kipyatkov
2015-07-13 16:21:37 +03:00
parent 077c8a82c7
commit 53e751be1f
4 changed files with 203 additions and 46 deletions
@@ -46,41 +46,26 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
public abstract class ElementResolver protected constructor(
public val resolveSession: ResolveSession
) {
public open fun getElementAdditionalResolve(jetElement: JetElement): BindingContext {
return performElementAdditionalResolve(jetElement, jetElement, BodyResolveMode.FULL)
public open fun getElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
return performElementAdditionalResolve(resolveElement, resolveElement, bodyResolveMode)
}
public open fun hasElementAdditionalResolveCached(jetElement: JetElement): Boolean = false
protected open fun probablyNothingCallableNames(): ProbablyNothingCallableNames
= throw UnsupportedOperationException("Cannot use partial body resolve with no Nothing-functions index");
public fun resolveToElement(jetElement: JetElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
@suppress("NAME_SHADOWING")
var jetElement = jetElement
public fun resolveToElement(element: JetElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
var contextElement = element
val elementOfAdditionalResolve = findElementOfAdditionalResolve(jetElement)
val elementOfAdditionalResolve = findElementOfAdditionalResolve(contextElement)
if (elementOfAdditionalResolve != null) {
if (elementOfAdditionalResolve !is JetParameter) {
if (bodyResolveMode != BodyResolveMode.FULL && !hasElementAdditionalResolveCached(elementOfAdditionalResolve)) {
return performElementAdditionalResolve(elementOfAdditionalResolve, jetElement, bodyResolveMode)
}
return getElementAdditionalResolve(elementOfAdditionalResolve)
}
val klass = elementOfAdditionalResolve.getParentOfType<JetClass>(true)
if (klass != null && elementOfAdditionalResolve.getParent() == klass.getPrimaryConstructorParameterList()) {
return getElementAdditionalResolve(klass)
}
// Parameters for function literal could be met inside other parameters. We can't make resolveToDescriptors for internal elements.
jetElement = elementOfAdditionalResolve
if (elementOfAdditionalResolve is JetParameter) {
contextElement = elementOfAdditionalResolve
}
else if (elementOfAdditionalResolve != null) {
return getElementAdditionalResolve(elementOfAdditionalResolve, contextElement, bodyResolveMode)
}
val declaration = jetElement.getParentOfType<JetDeclaration>(false)
val declaration = contextElement.getParentOfType<JetDeclaration>(false)
if (declaration != null && declaration !is JetClassInitializer) {
// Activate descriptor resolution
resolveSession.resolveToDescriptor(declaration)
@@ -89,8 +74,8 @@ public abstract class ElementResolver protected constructor(
return resolveSession.getBindingContext()
}
private fun findElementOfAdditionalResolve(element: JetElement): JetElement? {
var elementOfAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes(
protected fun findElementOfAdditionalResolve(element: JetElement): JetElement? {
val elementOfAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes(
element,
javaClass<JetNamedFunction>(),
javaClass<JetClassInitializer>(),
@@ -104,13 +89,22 @@ public abstract class ElementResolver protected constructor(
javaClass<JetTypeParameter>(),
javaClass<JetTypeConstraint>(),
javaClass<JetPackageDirective>(),
javaClass<JetCodeFragment>()) as JetElement?
javaClass<JetCodeFragment>()) as JetElement? ?: return null
if (elementOfAdditionalResolve is JetPackageDirective) {
return element
when (elementOfAdditionalResolve) {
is JetPackageDirective -> return element
is JetParameter -> {
val klass = elementOfAdditionalResolve.getParentOfType<JetClass>(strict = true)
if (klass != null && elementOfAdditionalResolve.getParent() == klass.getPrimaryConstructorParameterList()) {
return klass
}
return elementOfAdditionalResolve
}
else -> return elementOfAdditionalResolve
}
return elementOfAdditionalResolve
}
protected fun performElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.JetNodeTypes
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.StatementFilter
import org.jetbrains.kotlin.utils.addToStdlib.swap
import org.jetbrains.kotlin.util.isProbablyNothing
@@ -538,6 +539,10 @@ class PartialBodyResolveFilter(
}
companion object {
public fun findResolveElement(element: JetElement, declaration: JetDeclaration): JetExpression? {
return element.parentsWithSelf.takeWhile { it != declaration }.firstOrNull { it.isStatement() } as JetExpression?
}
private fun JetElement.blocks(): Collection<JetBlockExpression> {
val result = ArrayList<JetBlockExpression>(1)
this.accept(object : JetVisitorVoid() {