diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt new file mode 100644 index 00000000000..7fd0e842ef1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt @@ -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? = null, + visitReceivers: Boolean = true, + visitShortNames: Boolean = true + ): Map { + 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() + + public val result: Map = 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 \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt index 57c444fd4b5..b90abf5050c 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt @@ -29,14 +29,13 @@ public object ShortenReferences { public fun process(elements: Iterable) { 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() - - public val result: Map = 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) : JetTreeVisitorVoid() { private val resolveSession : ResolveSessionForBodies get() = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(file) @@ -223,14 +195,14 @@ public object ShortenReferences { val isUsageInImport = qualifiedExpression.getParentByType(javaClass()) != 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?