Minor. Small refactoring in QualifiedExpressionResolver
This commit is contained in:
@@ -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)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user