Minor. Small refactoring in QualifiedExpressionResolver

This commit is contained in:
Stanislav Erokhin
2015-09-17 12:50:17 +03:00
parent b51edf9004
commit 2373cc3ede
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
@@ -32,6 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.getClassifier import org.jetbrains.kotlin.resolve.scopes.utils.getClassifier
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.check
public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator) { public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator) {
@@ -41,8 +41,10 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
module: ModuleDescriptor, module: ModuleDescriptor,
trace: BindingTrace trace: BindingTrace
) { ) {
for (nameExpression in packageDirective.packageNames) { val packageNames = packageDirective.packageNames
storageResult(trace, nameExpression, listOf(module.getPackage(packageDirective.getFqName(nameExpression))), null) for ((index, nameExpression) in packageNames.withIndex()) {
storageResult(trace, nameExpression, listOf(module.getPackage(packageDirective.getFqName(nameExpression))),
shouldBeVisibleFrom = null, inImport = false, isQualifier = index != packageNames.lastIndex)
} }
} }
@@ -54,7 +56,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
if (userType.qualifier == null && !userType.startWithPackage) { // optimization for non-qualified types if (userType.qualifier == null && !userType.startWithPackage) { // optimization for non-qualified types
return userType.referenceExpression?.let { return userType.referenceExpression?.let {
val classifier = scope.getClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it)) val classifier = scope.getClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it))
storageResult(trace, it, listOfNotNull(classifier), scope.ownerDescriptor) storageResult(trace, it, listOfNotNull(classifier), scope.ownerDescriptor, inImport = false, isQualifier = false)
classifier classifier
} }
} }
@@ -62,7 +64,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
val module = scope.ownerDescriptor.module val module = scope.ownerDescriptor.module
val (qualifierPartList, hasError) = userType.asQualifierPartList() val (qualifierPartList, hasError) = userType.asQualifierPartList()
if (hasError) { if (hasError) {
resolveToPackageOrClass(qualifierPartList, module, trace, scope.ownerDescriptor) resolveToPackageOrClass(qualifierPartList, module, trace, scope.ownerDescriptor, scope, inImport = false)
return null return null
} }
assert(qualifierPartList.size() >= 1) { assert(qualifierPartList.size() >= 1) {
@@ -70,15 +72,8 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
} }
val qualifier = resolveToPackageOrClass( val qualifier = resolveToPackageOrClass(
qualifierPartList.subList(0, qualifierPartList.size() - 1), module, trace, scope.ownerDescriptor, qualifierPartList.subList(0, qualifierPartList.size() - 1), module,
firstPartResolver = { trace, scope.ownerDescriptor, scope.check { !userType.startWithPackage }, inImport = false
if (userType.startWithPackage) {
null
}
else {
scope.getClassifier(it.name, it.location)
}
}
) ?: return null ) ?: return null
val lastPart = qualifierPartList.last() val lastPart = qualifierPartList.last()
@@ -87,7 +82,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getClassifier(lastPart.name, lastPart.location) is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getClassifier(lastPart.name, lastPart.location)
else -> null else -> null
} }
storageResult(trace, lastPart.expression, listOfNotNull(classifier), scope.ownerDescriptor) storageResult(trace, lastPart.expression, listOfNotNull(classifier), scope.ownerDescriptor, inImport = false, isQualifier = false)
return classifier return classifier
} }
@@ -129,7 +124,8 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
val lastPart = path.lastOrNull() ?: return JetScope.Empty val lastPart = path.lastOrNull() ?: return JetScope.Empty
if (importDirective.isAllUnder) { if (importDirective.isAllUnder) {
val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom) ?: return JetScope.Empty val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom,
scopeForFirstPart = null, inImport = true) ?: return JetScope.Empty
if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) { if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) {
trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star
} }
@@ -140,11 +136,12 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
else { else {
val aliasName = JetPsiUtil.getAliasName(importDirective) val aliasName = JetPsiUtil.getAliasName(importDirective)
if (aliasName == null) { // import kotlin. if (aliasName == null) { // import kotlin.
resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom) resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom, scopeForFirstPart = null, inImport = true)
return JetScope.Empty return JetScope.Empty
} }
val packageOrClassDescriptor = resolveToPackageOrClass(path.subList(0, path.size() - 1), moduleDescriptor, trace, shouldBeVisibleFrom) val packageOrClassDescriptor = resolveToPackageOrClass(path.subList(0, path.size() - 1), moduleDescriptor,
trace, shouldBeVisibleFrom, scopeForFirstPart = null, inImport = true)
?: return JetScope.Empty ?: return JetScope.Empty
val descriptors = SmartList<DeclarationDescriptor>() val descriptors = SmartList<DeclarationDescriptor>()
@@ -170,7 +167,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor") else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
} }
if (descriptors.isNotEmpty()) { if (descriptors.isNotEmpty()) {
storageResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom) storageResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom, inImport = true, isQualifier = false)
} }
else { else {
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart) tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
@@ -213,7 +210,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor") else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
} }
storageResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null) storageResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, inImport = true, isQualifier = false)
} }
private fun JetExpression.asQualifierPartList(trace: BindingTrace): List<QualifierPart> { private fun JetExpression.asQualifierPartList(trace: BindingTrace): List<QualifierPart> {
@@ -253,16 +250,23 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
trace: BindingTrace, trace: BindingTrace,
shouldBeVisibleFrom: DeclarationDescriptor, shouldBeVisibleFrom: DeclarationDescriptor,
firstPartResolver: (QualifierPart) -> DeclarationDescriptor? = { null } scopeForFirstPart: LexicalScope?,
inImport: Boolean
): DeclarationDescriptor? { ): DeclarationDescriptor? {
if (path.isEmpty()) { if (path.isEmpty()) {
return moduleDescriptor.getPackage(FqName.ROOT) return moduleDescriptor.getPackage(FqName.ROOT)
} }
val (currentDescriptor, currentIndex) = firstPartResolver(path.first())?.let { val firstDescriptor = scopeForFirstPart?.let {
storageResult(trace, path.first().expression, listOf(it), shouldBeVisibleFrom) val firstPart = path.first()
Pair(it, 1) it.getClassifier(firstPart.name, firstPart.location)?.apply {
} ?: moduleDescriptor.quickResolveToPackage(path, trace) storageResult(trace, firstPart.expression, listOf(this), shouldBeVisibleFrom, inImport)
}
}
val (currentDescriptor, currentIndex) = firstDescriptor?.let { Pair(it, 1) } ?: moduleDescriptor.quickResolveToPackage(path, trace, inImport)
return path.subList(currentIndex, path.size()).fold<QualifierPart, DeclarationDescriptor?>(currentDescriptor) { return path.subList(currentIndex, path.size()).fold<QualifierPart, DeclarationDescriptor?>(currentDescriptor) {
descriptor, qualifierPart -> descriptor, qualifierPart ->
// report unresolved reference only for first unresolved qualifier // report unresolved reference only for first unresolved qualifier
@@ -286,14 +290,15 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
} }
else -> null else -> null
} }
storageResult(trace, qualifierPart.expression, listOfNotNull(nextDescriptor), shouldBeVisibleFrom) storageResult(trace, qualifierPart.expression, listOfNotNull(nextDescriptor), shouldBeVisibleFrom, inImport)
nextDescriptor nextDescriptor
} }
} }
private fun ModuleDescriptor.quickResolveToPackage( private fun ModuleDescriptor.quickResolveToPackage(
path: List<QualifierPart>, path: List<QualifierPart>,
trace: BindingTrace trace: BindingTrace,
inImport: Boolean
): Pair<PackageViewDescriptor, Int> { ): Pair<PackageViewDescriptor, Int> {
val possiblePackagePrefixSize = path.indexOfFirst { it.typeArguments != null }.let { if (it == -1) path.size() else it + 1 } val possiblePackagePrefixSize = path.indexOfFirst { it.typeArguments != null }.let { if (it == -1) path.size() else it + 1 }
var fqName = path.subList(0, possiblePackagePrefixSize).fold(FqName.ROOT) { fqName, qualifierPart -> var fqName = path.subList(0, possiblePackagePrefixSize).fold(FqName.ROOT) { fqName, qualifierPart ->
@@ -303,7 +308,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
while (!fqName.isRoot) { while (!fqName.isRoot) {
val packageDescriptor = getPackage(fqName) val packageDescriptor = getPackage(fqName)
if (!packageDescriptor.isEmpty()) { if (!packageDescriptor.isEmpty()) {
recordPackageViews(path.subList(0, prefixSize), packageDescriptor, trace) recordPackageViews(path.subList(0, prefixSize), packageDescriptor, trace, inImport)
return Pair(packageDescriptor, prefixSize) return Pair(packageDescriptor, prefixSize)
} }
fqName = fqName.parent() fqName = fqName.parent()
@@ -315,10 +320,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
private fun recordPackageViews( private fun recordPackageViews(
path: List<QualifierPart>, path: List<QualifierPart>,
packageView: PackageViewDescriptor, packageView: PackageViewDescriptor,
trace: BindingTrace trace: BindingTrace,
inImport: Boolean
) { ) {
path.foldRight(packageView) { qualifierPart, currentView -> path.foldRight(packageView) { qualifierPart, currentView ->
storageResult(trace, qualifierPart.expression, listOfNotNull(currentView), null) storageResult(trace, qualifierPart.expression, listOfNotNull(currentView), shouldBeVisibleFrom = null, inImport = inImport)
val parentView = currentView.containingDeclaration val parentView = currentView.containingDeclaration
assert(parentView != null) { assert(parentView != null) {
"Containing Declaration must be not null for package with fqName: ${currentView.fqName}, " + "Containing Declaration must be not null for package with fqName: ${currentView.fqName}, " +
@@ -332,7 +338,9 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
trace: BindingTrace, trace: BindingTrace,
referenceExpression: JetSimpleNameExpression, referenceExpression: JetSimpleNameExpression,
descriptors: Collection<DeclarationDescriptor>, descriptors: Collection<DeclarationDescriptor>,
shouldBeVisibleFrom: DeclarationDescriptor? shouldBeVisibleFrom: DeclarationDescriptor?,
inImport: Boolean,
isQualifier: Boolean = true
) { ) {
if (descriptors.isEmpty()) { if (descriptors.isEmpty()) {
trace.report(Errors.UNRESOLVED_REFERENCE.on(referenceExpression, referenceExpression)) trace.report(Errors.UNRESOLVED_REFERENCE.on(referenceExpression, referenceExpression))
@@ -348,10 +356,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
symbolUsageValidator.validateTypeUsage(descriptor, trace, referenceExpression) symbolUsageValidator.validateTypeUsage(descriptor, trace, referenceExpression)
} }
if (descriptor is DeclarationDescriptorWithVisibility && shouldBeVisibleFrom != null) { if (descriptor is DeclarationDescriptorWithVisibility && shouldBeVisibleFrom != null) {
checkVisibility(descriptor, trace, referenceExpression, shouldBeVisibleFrom) checkVisibility(descriptor, trace, referenceExpression, shouldBeVisibleFrom, inImport)
}
if (isQualifier) {
storageQualifier(trace, referenceExpression, descriptor)
} }
storageQualifier(trace, referenceExpression, descriptor)
} }
} }
@@ -366,9 +375,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
descriptor: DeclarationDescriptorWithVisibility, descriptor: DeclarationDescriptorWithVisibility,
trace: BindingTrace, trace: BindingTrace,
referenceExpression: JetSimpleNameExpression, referenceExpression: JetSimpleNameExpression,
shouldBeVisibleFrom: DeclarationDescriptor) { shouldBeVisibleFrom: DeclarationDescriptor,
inImport: Boolean
) {
val visibility = descriptor.visibility val visibility = descriptor.visibility
if (PsiTreeUtil.getParentOfType(referenceExpression, JetImportDirective::class.java) != null && !visibility.mustCheckInImports()) { if (inImport && !visibility.mustCheckInImports()) {
return return
} }
if (!Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, shouldBeVisibleFrom)) { if (!Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, shouldBeVisibleFrom)) {