KT-758 Show completion of namespaces in import statement
This commit is contained in:
@@ -8,8 +8,10 @@ import com.intellij.psi.PsiElement;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetImportDirective;
|
||||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -42,12 +44,14 @@ public final class TipsManager {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<DeclarationDescriptor> getReferenceVariants(JetSimpleNameExpression expression, BindingContext context) {
|
public static Collection<DeclarationDescriptor> getReferenceVariants(JetSimpleNameExpression expression, BindingContext context) {
|
||||||
PsiElement parent = expression.getParent();
|
PsiElement parent = expression.getParent();
|
||||||
if (parent instanceof JetQualifiedExpression) {
|
|
||||||
|
if (parent instanceof JetQualifiedExpression && !(parent.getParent() instanceof JetImportDirective)) {
|
||||||
|
// Process as call expression
|
||||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
|
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
|
||||||
JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
|
JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
|
||||||
|
|
||||||
final JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
|
|
||||||
final JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression);
|
final JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression);
|
||||||
|
final JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
|
||||||
|
|
||||||
if (expressionType != null && resolutionScope != null) {
|
if (expressionType != null && resolutionScope != null) {
|
||||||
return includeExternalCallableExtensions(
|
return includeExternalCallableExtensions(
|
||||||
@@ -58,7 +62,12 @@ public final class TipsManager {
|
|||||||
else {
|
else {
|
||||||
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
if (resolutionScope != null) {
|
if (resolutionScope != null) {
|
||||||
return excludeNotCallableExtensions(resolutionScope.getAllDescriptors(), resolutionScope);
|
if (parent instanceof JetImportDirective) {
|
||||||
|
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return excludeNotCallableExtensions(resolutionScope.getAllDescriptors(), resolutionScope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +89,16 @@ public final class TipsManager {
|
|||||||
|
|
||||||
return Lists.newArrayList(descriptorsSet);
|
return Lists.newArrayList(descriptorsSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Collection<DeclarationDescriptor> excludeNonPackageDescriptors(
|
||||||
|
@NotNull Collection<DeclarationDescriptor> descriptors) {
|
||||||
|
return Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(DeclarationDescriptor declarationDescriptor) {
|
||||||
|
return declarationDescriptor instanceof NamespaceDescriptor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static Collection<DeclarationDescriptor> includeExternalCallableExtensions(
|
private static Collection<DeclarationDescriptor> includeExternalCallableExtensions(
|
||||||
@NotNull Collection<DeclarationDescriptor> descriptors,
|
@NotNull Collection<DeclarationDescriptor> descriptors,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class StandardConfiguration implements Configuration {
|
|||||||
@Override
|
@Override
|
||||||
public void addDefaultImports(@NotNull BindingTrace trace, @NotNull WritableScope rootScope) {
|
public void addDefaultImports(@NotNull BindingTrace trace, @NotNull WritableScope rootScope) {
|
||||||
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, "std.*");
|
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, "std.*");
|
||||||
new ImportsResolver.ImportResolver(trace, true).processImportReference(importDirective, rootScope, rootScope);
|
new ImportsResolver.ImportResolver(trace, true).processImportReference(importDirective, rootScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class ImportsResolver {
|
|||||||
|
|
||||||
List<JetImportDirective> importDirectives = file.getImportDirectives();
|
List<JetImportDirective> importDirectives = file.getImportDirectives();
|
||||||
for (JetImportDirective importDirective : importDirectives) {
|
for (JetImportDirective importDirective : importDirectives) {
|
||||||
importResolver.processImportReference(importDirective, namespaceScope, JetScope.EMPTY);
|
importResolver.processImportReference(importDirective, namespaceScope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ public class ImportsResolver {
|
|||||||
this.firstPhase = firstPhase;
|
this.firstPhase = firstPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processImportReference(JetImportDirective importDirective, WritableScope namespaceScope, JetScope outerScope) {
|
public void processImportReference(JetImportDirective importDirective, WritableScope namespaceScope) {
|
||||||
if (importDirective.isAbsoluteInRootNamespace()) {
|
if (importDirective.isAbsoluteInRootNamespace()) {
|
||||||
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
|
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
|
||||||
return;
|
return;
|
||||||
@@ -73,8 +73,17 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert importedReference instanceof JetSimpleNameExpression;
|
assert importedReference instanceof JetSimpleNameExpression;
|
||||||
JetScope scope = importDirective.isAllUnder() ? namespaceScope : outerScope;
|
|
||||||
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope);
|
if (importDirective.isAllUnder()) {
|
||||||
|
// Example: import java.*
|
||||||
|
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, namespaceScope);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Example: import IDENTIFIER
|
||||||
|
// Should be unresolved error
|
||||||
|
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, JetScope.EMPTY);
|
||||||
|
trace.record(BindingContext.RESOLUTION_SCOPE, importedReference, namespaceScope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
|
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
|
||||||
if (importDirective.isAllUnder()) {
|
if (importDirective.isAllUnder()) {
|
||||||
@@ -88,9 +97,7 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
JetType type = ((VariableDescriptor) descriptor).getOutType();
|
JetType type = ((VariableDescriptor) descriptor).getOutType();
|
||||||
if (type != null) {
|
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, type.getMemberScope()));
|
||||||
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, type.getMemberScope()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof ClassDescriptor) {
|
else if (descriptor instanceof ClassDescriptor) {
|
||||||
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, ((ClassDescriptor) descriptor).getDefaultType().getMemberScope()));
|
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, ((ClassDescriptor) descriptor).getDefaultType().getMemberScope()));
|
||||||
@@ -159,12 +166,13 @@ public class ImportsResolver {
|
|||||||
return lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope());
|
return lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope());
|
||||||
}
|
}
|
||||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||||
return lookupObjectMembers(selector, lastReference, (ClassDescriptor) declarationDescriptor);
|
return lookupObjectMembers(selector, (ClassDescriptor) declarationDescriptor);
|
||||||
}
|
}
|
||||||
if (declarationDescriptor instanceof VariableDescriptor) {
|
if (declarationDescriptor instanceof VariableDescriptor) {
|
||||||
return lookupVariableMembers(selector, (VariableDescriptor) declarationDescriptor);
|
return lookupVariableMembers(selector, (VariableDescriptor) declarationDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +214,8 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<DeclarationDescriptor> lookupObjectMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull JetSimpleNameExpression classReference, @NotNull ClassDescriptor classDescriptor) {
|
private Collection<DeclarationDescriptor> lookupObjectMembers(@NotNull JetSimpleNameExpression memberReference,
|
||||||
|
@NotNull ClassDescriptor classDescriptor) {
|
||||||
if (firstPhase) return Collections.emptyList();
|
if (firstPhase) return Collections.emptyList();
|
||||||
JetType classObjectType = classDescriptor.getClassObjectType();
|
JetType classObjectType = classDescriptor.getClassObjectType();
|
||||||
assert classObjectType != null;
|
assert classObjectType != null;
|
||||||
@@ -230,6 +239,7 @@ public class ImportsResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope) {
|
private Collection<DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope) {
|
||||||
|
|
||||||
List<DeclarationDescriptor> descriptors = Lists.newArrayList();
|
List<DeclarationDescriptor> descriptors = Lists.newArrayList();
|
||||||
String referencedName = referenceExpression.getReferencedName();
|
String referencedName = referenceExpression.getReferencedName();
|
||||||
if (referencedName != null) {
|
if (referencedName != null) {
|
||||||
@@ -242,11 +252,10 @@ public class ImportsResolver {
|
|||||||
descriptors.addAll(outerScope.getFunctions(referencedName));
|
descriptors.addAll(outerScope.getFunctions(referencedName));
|
||||||
|
|
||||||
descriptors.addAll(outerScope.getProperties(referencedName));
|
descriptors.addAll(outerScope.getProperties(referencedName));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!firstPhase) {
|
if (!firstPhase) {
|
||||||
if (descriptors.size() == 1) {
|
if (descriptors.size() == 1) {
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
|
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.get(0));
|
||||||
}
|
}
|
||||||
else if (descriptors.size() > 1) {
|
else if (descriptors.size() > 1) {
|
||||||
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
|
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
|
||||||
@@ -254,6 +263,11 @@ public class ImportsResolver {
|
|||||||
else {
|
else {
|
||||||
trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
|
trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it's not an ambiguous case - store resolution scope
|
||||||
|
if (descriptors.size() <= 1 && outerScope != JetScope.EMPTY) {
|
||||||
|
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, outerScope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package Test
|
||||||
|
|
||||||
|
import <caret>
|
||||||
|
|
||||||
|
// EXIST: java, javax, reflect
|
||||||
|
// ABSENT: Array, Integer
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package Test
|
||||||
|
|
||||||
|
import java.util.<caret>
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: AbstractList, Date, Random, concurrent
|
||||||
Reference in New Issue
Block a user