Extract reference resolver from ShortenReferences

This commit is contained in:
Alexey Sedunov
2014-03-05 14:28:47 +04:00
parent d9d045cbb2
commit 99b8c47276
2 changed files with 94 additions and 39 deletions
@@ -0,0 +1,89 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.codeInsight
import org.jetbrains.jet.lang.psi.JetReferenceExpression
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import com.intellij.util.containers.HashMap
import org.jetbrains.jet.lang.psi.JetUserType
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
object JetFileReferencesResolver {
fun resolve(
file: JetFile,
elements: Iterable<JetElement>? = null,
visitReceivers: Boolean = true,
visitShortNames: Boolean = true
): Map<JetReferenceExpression, BindingContext> {
val visitor = ResolveAllReferencesVisitor(file, visitReceivers, visitShortNames)
if (elements != null) {
elements.forEach { it.accept(visitor) }
}
else {
file.accept(visitor)
}
return visitor.result
}
private class ResolveAllReferencesVisitor(file: JetFile, val visitReceivers: Boolean, val visitShortNames: Boolean) : JetTreeVisitorVoid() {
private val resolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(file)
private val resolveMap = HashMap<JetReferenceExpression, BindingContext>()
public val result: Map<JetReferenceExpression, BindingContext> = resolveMap
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
override fun visitUserType(userType: JetUserType) {
if (visitReceivers) {
userType.acceptChildren(this)
}
if (visitShortNames || userType.getQualifier() != null) {
val referenceExpression = userType.getReferenceExpression()
if (referenceExpression != null) {
resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
}
}
}
override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) {
if (visitReceivers) {
expression.acceptChildren(this)
}
val referenceExpression = expression.getSelectorExpression()?.referenceExpression()
if (referenceExpression != null) {
resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
}
}
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) {
if (visitShortNames) {
resolveMap[expression] = resolveSession.resolveToElement(expression)
}
}
}
}
fun JetExpression.referenceExpression(): JetReferenceExpression? =
(if (this is JetCallExpression) getCalleeExpression() else this) as? JetReferenceExpression
@@ -29,14 +29,13 @@ public object ShortenReferences {
public fun process(elements: Iterable<JetElement>) {
for ((file, fileElements) in elements.groupBy { element -> element.getContainingFile() as JetFile }) {
// first resolve all qualified references - optimization
val resolveAllVisitor = ResolveAllReferencesVisitor(file)
processElements(fileElements, resolveAllVisitor)
val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, visitShortNames = false)
val shortenTypesVisitor = ShortenTypesVisitor(file, resolveAllVisitor.result)
val shortenTypesVisitor = ShortenTypesVisitor(file, referenceToContext)
processElements(fileElements, shortenTypesVisitor)
shortenTypesVisitor.finish()
processElements(fileElements, ShortenQualifiedExpressionsVisitor(file, resolveAllVisitor.result))
processElements(fileElements, ShortenQualifiedExpressionsVisitor(file, referenceToContext))
}
}
@@ -46,33 +45,6 @@ public object ShortenReferences {
}
}
private class ResolveAllReferencesVisitor(file: JetFile) : JetTreeVisitorVoid() {
private val resolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(file)
private val resolveMap = HashMap<JetReferenceExpression, BindingContext>()
public val result: Map<JetReferenceExpression, BindingContext> = resolveMap
override fun visitUserType(userType: JetUserType) {
userType.acceptChildren(this)
if (userType.getQualifier() != null) {
val referenceExpression = userType.getReferenceExpression()
if (referenceExpression != null) {
resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
}
}
}
override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) {
expression.acceptChildren(this)
val referenceExpression = referenceExpression(expression.getSelectorExpression())
if (referenceExpression != null) {
resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
}
}
}
private class ShortenTypesVisitor(val file: JetFile, val resolveMap: Map<JetReferenceExpression, BindingContext>) : JetTreeVisitorVoid() {
private val resolveSession : ResolveSessionForBodies
get() = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(file)
@@ -223,14 +195,14 @@ public object ShortenReferences {
val isUsageInImport = qualifiedExpression.getParentByType(javaClass<JetImportDirective>()) != null
val isClassOrPackage = targetDescriptor is ClassDescriptor || targetDescriptor is PackageViewDescriptor
val referenceExpression = referenceExpression(qualifiedExpression.getSelectorExpression())!!
val referenceExpression = qualifiedExpression.getSelectorExpression()!!.referenceExpression()!!
val resolveBefore = resolveState(referenceExpression, bindingContext)
val copy = qualifiedExpression.copy()
val selectorExpression = qualifiedExpression.getSelectorExpression()!!
val newExpression = qualifiedExpression.replace(selectorExpression) as JetExpression
val newReferenceExpression = referenceExpression(newExpression)!!
val newReferenceExpression = newExpression.referenceExpression()!!
val newBindingContext = resolveSession.resolveToElement(newReferenceExpression)
val resolveAfter = resolveState(newReferenceExpression, newBindingContext)
@@ -266,12 +238,6 @@ public object ShortenReferences {
}
}
private fun referenceExpression(selectorExpression: JetExpression?): JetReferenceExpression?
= if (selectorExpression is JetCallExpression)
selectorExpression.getCalleeExpression() as? JetReferenceExpression
else
selectorExpression as? JetReferenceExpression
private fun DeclarationDescriptor.asString() = DescriptorRenderer.TEXT.render(this)
//TODO: do we need this "IfNeeded" check?