Refactor: Extract ImportDirectiveProcessor from QualifiedExpressionResolver
J2K code
This commit is contained in:
@@ -33,7 +33,7 @@ class AllUnderImportsScope : JetScope {
|
||||
if (descriptor is PackageViewDescriptor) {
|
||||
scopes.add(NoSubpackagesInPackageScope(descriptor))
|
||||
}
|
||||
else if (descriptor is ClassDescriptor && QualifiedExpressionResolver.canAllUnderImportFromClass(descriptor)) {
|
||||
else if (descriptor is ClassDescriptor && ImportDirectiveProcessor.canAllUnderImportFromClass(descriptor)) {
|
||||
scopes.add(descriptor.getStaticScope())
|
||||
scopes.add(descriptor.getUnsubstitutedInnerClassesScope())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
public class ImportDirectiveProcessor(
|
||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver
|
||||
) {
|
||||
public fun processImportReference(
|
||||
importDirective: JetImportDirective,
|
||||
scope: JetScope,
|
||||
scopeToCheckVisibility: JetScope,
|
||||
trace: BindingTrace,
|
||||
lookupMode: QualifiedExpressionResolver.LookupMode
|
||||
): JetScope {
|
||||
if (importDirective.isAbsoluteInRootPackage()) {
|
||||
trace.report(Errors.UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")) // TODO
|
||||
return JetScope.Empty
|
||||
}
|
||||
val importedReference = importDirective.getImportedReference() ?: return JetScope.Empty
|
||||
|
||||
val descriptors: Collection<DeclarationDescriptor>
|
||||
if (importedReference is JetQualifiedExpression) {
|
||||
//store result only when we find all descriptors, not only classes on the second phase
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression(
|
||||
importedReference, scope, scopeToCheckVisibility, trace, lookupMode, lookupMode == QualifiedExpressionResolver.LookupMode.EVERYTHING
|
||||
)
|
||||
}
|
||||
else {
|
||||
assert(importedReference is JetSimpleNameExpression)
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference(
|
||||
importedReference as JetSimpleNameExpression, scope, scopeToCheckVisibility, trace, lookupMode, true, lookupMode == QualifiedExpressionResolver.LookupMode.EVERYTHING
|
||||
)
|
||||
}
|
||||
|
||||
val referenceExpression = JetPsiUtil.getLastReference(importedReference)
|
||||
if (importDirective.isAllUnder()) {
|
||||
if (!canAllUnderImportFrom(descriptors) && referenceExpression != null) {
|
||||
val toReportOn = descriptors.filterIsInstance<ClassDescriptor>().iterator().next()
|
||||
trace.report(Errors.CANNOT_IMPORT_ON_DEMAND_FROM_SINGLETON.on(referenceExpression, toReportOn))
|
||||
}
|
||||
|
||||
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace, lookupMode)) {
|
||||
return JetScope.Empty
|
||||
}
|
||||
|
||||
val importsScope = AllUnderImportsScope()
|
||||
for (descriptor in descriptors) {
|
||||
importsScope.addAllUnderImport(descriptor)
|
||||
}
|
||||
return importsScope
|
||||
}
|
||||
else {
|
||||
val aliasName = JetPsiUtil.getAliasName(importDirective)
|
||||
if (aliasName == null) return JetScope.Empty
|
||||
return SingleImportScope(aliasName, descriptors)
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public fun canAllUnderImportFrom(descriptors: Collection<DeclarationDescriptor>): Boolean {
|
||||
if (descriptors.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
for (descriptor in descriptors) {
|
||||
if (descriptor !is ClassDescriptor) {
|
||||
return true
|
||||
}
|
||||
if (canAllUnderImportFromClass(descriptor)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public fun canAllUnderImportFromClass(descriptor: ClassDescriptor): Boolean {
|
||||
return !descriptor.getKind().isSingleton()
|
||||
}
|
||||
|
||||
platformStatic public fun canImportMembersFrom(descriptors: Collection<DeclarationDescriptor>, reference: JetSimpleNameExpression, trace: BindingTrace, lookupMode: QualifiedExpressionResolver.LookupMode): Boolean {
|
||||
if (lookupMode == QualifiedExpressionResolver.LookupMode.ONLY_CLASSES_AND_PACKAGES) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (descriptors.size() == 1) {
|
||||
return canImportMembersFrom(descriptors.iterator().next(), reference, trace, lookupMode)
|
||||
}
|
||||
|
||||
val temporaryTrace = TemporaryBindingTrace.create(trace, "trace to find out if members can be imported from", reference)
|
||||
var canImport = false
|
||||
for (descriptor in descriptors) {
|
||||
canImport = canImport or canImportMembersFrom(descriptor, reference, temporaryTrace, lookupMode)
|
||||
}
|
||||
if (!canImport) {
|
||||
temporaryTrace.commit()
|
||||
}
|
||||
return canImport
|
||||
}
|
||||
|
||||
private fun canImportMembersFrom(descriptor: DeclarationDescriptor, reference: JetSimpleNameExpression, trace: BindingTrace, lookupMode: QualifiedExpressionResolver.LookupMode): Boolean {
|
||||
assert(lookupMode == QualifiedExpressionResolver.LookupMode.EVERYTHING)
|
||||
if (descriptor is PackageViewDescriptor) {
|
||||
return true
|
||||
}
|
||||
if (descriptor is ClassDescriptor) {
|
||||
return true
|
||||
}
|
||||
trace.report(Errors.CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor))
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-123
@@ -21,7 +21,6 @@ import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.Mutable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -43,6 +42,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
|
||||
public class QualifiedExpressionResolver {
|
||||
private SymbolUsageValidator symbolUsageValidator;
|
||||
private final ImportDirectiveProcessor importDirectiveProcessor = new ImportDirectiveProcessor(this);
|
||||
|
||||
/**
|
||||
* @deprecated Instance of this class should be obtained from the Injector
|
||||
@@ -71,25 +71,6 @@ public class QualifiedExpressionResolver {
|
||||
EVERYTHING
|
||||
}
|
||||
|
||||
public static boolean canAllUnderImportFrom(@NotNull Collection<DeclarationDescriptor> descriptors) {
|
||||
if (descriptors.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
return true;
|
||||
}
|
||||
if (canAllUnderImportFromClass((ClassDescriptor) descriptor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean canAllUnderImportFromClass(@NotNull ClassDescriptor descriptor) {
|
||||
return !descriptor.getKind().isSingleton();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetScope processImportReference(
|
||||
@NotNull JetImportDirective importDirective,
|
||||
@@ -98,94 +79,7 @@ public class QualifiedExpressionResolver {
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull LookupMode lookupMode
|
||||
) {
|
||||
if (importDirective.isAbsoluteInRootPackage()) {
|
||||
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
|
||||
return JetScope.Empty.INSTANCE$;
|
||||
}
|
||||
JetExpression importedReference = importDirective.getImportedReference();
|
||||
if (importedReference == null) {
|
||||
return JetScope.Empty.INSTANCE$;
|
||||
}
|
||||
|
||||
Collection<DeclarationDescriptor> descriptors;
|
||||
if (importedReference instanceof JetQualifiedExpression) {
|
||||
//store result only when we find all descriptors, not only classes on the second phase
|
||||
descriptors = lookupDescriptorsForQualifiedExpression(
|
||||
(JetQualifiedExpression) importedReference, scope, scopeToCheckVisibility, trace,
|
||||
lookupMode, lookupMode == LookupMode.EVERYTHING);
|
||||
}
|
||||
else {
|
||||
assert importedReference instanceof JetSimpleNameExpression;
|
||||
descriptors = lookupDescriptorsForSimpleNameReference(
|
||||
(JetSimpleNameExpression) importedReference, scope, scopeToCheckVisibility, trace,
|
||||
lookupMode, true, lookupMode == LookupMode.EVERYTHING);
|
||||
}
|
||||
|
||||
JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference);
|
||||
if (importDirective.isAllUnder()) {
|
||||
if (!canAllUnderImportFrom(descriptors) && referenceExpression != null) {
|
||||
ClassDescriptor toReportOn = KotlinPackage.filterIsInstance(descriptors, ClassDescriptor.class).iterator().next();
|
||||
trace.report(CANNOT_IMPORT_ON_DEMAND_FROM_SINGLETON.on(referenceExpression, toReportOn));
|
||||
}
|
||||
|
||||
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace, lookupMode)) {
|
||||
return JetScope.Empty.INSTANCE$;
|
||||
}
|
||||
|
||||
AllUnderImportsScope importsScope = new AllUnderImportsScope();
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
importsScope.addAllUnderImport(descriptor);
|
||||
}
|
||||
return importsScope;
|
||||
}
|
||||
else {
|
||||
Name aliasName = JetPsiUtil.getAliasName(importDirective);
|
||||
if (aliasName == null) return JetScope.Empty.INSTANCE$;
|
||||
return new SingleImportScope(aliasName, descriptors);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canImportMembersFrom(
|
||||
@NotNull Collection<DeclarationDescriptor> descriptors,
|
||||
@NotNull JetSimpleNameExpression reference,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull LookupMode lookupMode
|
||||
) {
|
||||
if (lookupMode == LookupMode.ONLY_CLASSES_AND_PACKAGES) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (descriptors.size() == 1) {
|
||||
return canImportMembersFrom(descriptors.iterator().next(), reference, trace, lookupMode);
|
||||
}
|
||||
|
||||
TemporaryBindingTrace temporaryTrace =
|
||||
TemporaryBindingTrace.create(trace, "trace to find out if members can be imported from", reference);
|
||||
boolean canImport = false;
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, lookupMode);
|
||||
}
|
||||
if (!canImport) {
|
||||
temporaryTrace.commit();
|
||||
}
|
||||
return canImport;
|
||||
}
|
||||
|
||||
private static boolean canImportMembersFrom(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@NotNull JetSimpleNameExpression reference,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull LookupMode lookupMode
|
||||
) {
|
||||
assert lookupMode == LookupMode.EVERYTHING;
|
||||
if (descriptor instanceof PackageViewDescriptor) {
|
||||
return true;
|
||||
}
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
return true;
|
||||
}
|
||||
trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor));
|
||||
return false;
|
||||
return importDirectiveProcessor.processImportReference(importDirective, scope, scopeToCheckVisibility, trace, lookupMode);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -211,27 +105,29 @@ public class QualifiedExpressionResolver {
|
||||
JetScope filteredScope = filterOutPackagesIfNeeded(outerScope, onlyClassifiers);
|
||||
|
||||
if (qualifier == null) {
|
||||
return lookupDescriptorsForSimpleNameReference(referenceExpression, filteredScope, outerScope, trace, LookupMode.ONLY_CLASSES_AND_PACKAGES,
|
||||
return lookupDescriptorsForSimpleNameReference(referenceExpression, filteredScope, outerScope, trace,
|
||||
LookupMode.ONLY_CLASSES_AND_PACKAGES,
|
||||
false, true);
|
||||
}
|
||||
Collection<DeclarationDescriptor> declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace, false);
|
||||
return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, filteredScope, LookupMode.ONLY_CLASSES_AND_PACKAGES, true);
|
||||
return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, filteredScope,
|
||||
LookupMode.ONLY_CLASSES_AND_PACKAGES, true);
|
||||
}
|
||||
|
||||
private static JetScope filterOutPackagesIfNeeded(final JetScope outerScope, boolean noPackages) {
|
||||
return !noPackages ? outerScope : new AbstractScopeAdapter() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JetScope getWorkerScope() {
|
||||
return outerScope;
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
protected JetScope getWorkerScope() {
|
||||
return outerScope;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PackageViewDescriptor getPackage(@NotNull Name name) {
|
||||
return null;
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public PackageViewDescriptor getPackage(@NotNull Name name) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -265,7 +161,8 @@ public class QualifiedExpressionResolver {
|
||||
|
||||
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
|
||||
JetSimpleNameExpression lastReference = JetPsiUtil.getLastReference(receiverExpression);
|
||||
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, lookupMode)) {
|
||||
if (lastReference == null || !ImportDirectiveProcessor.canImportMembersFrom(declarationDescriptors, lastReference, trace,
|
||||
lookupMode)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -454,7 +351,7 @@ public class QualifiedExpressionResolver {
|
||||
if (descriptor instanceof ClassifierDescriptor) {
|
||||
symbolUsageValidator.validateTypeUsage((ClassifierDescriptor) descriptor, trace, referenceExpression);
|
||||
}
|
||||
|
||||
|
||||
if (descriptor instanceof DeclarationDescriptorWithVisibility) {
|
||||
checkVisibility((DeclarationDescriptorWithVisibility) descriptor, trace, referenceExpression, scopeToCheckVisibility);
|
||||
}
|
||||
@@ -518,7 +415,9 @@ public class QualifiedExpressionResolver {
|
||||
) {
|
||||
if (!Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, scopeToCheckVisibility.getContainingDeclaration())) {
|
||||
Visibility visibility = descriptor.getVisibility();
|
||||
if (PsiTreeUtil.getParentOfType(referenceExpression, JetImportDirective.class) != null && !visibility.mustCheckInImports()) return;
|
||||
if (PsiTreeUtil.getParentOfType(referenceExpression, JetImportDirective.class) != null && !visibility.mustCheckInImports()) {
|
||||
return;
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
trace.report(INVISIBLE_REFERENCE.on(referenceExpression, descriptor, visibility, descriptor.getContainingDeclaration()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user