Fixed completion for package, import directive and user type.

This commit is contained in:
Stanislav Erokhin
2015-09-12 20:52:18 +03:00
parent 81934b75c2
commit b51edf9004
6 changed files with 90 additions and 16 deletions
@@ -91,7 +91,7 @@ public fun JetElement.getQualifiedElementSelector(): JetElement? {
public fun JetSimpleNameExpression.getReceiverExpression(): JetExpression? { public fun JetSimpleNameExpression.getReceiverExpression(): JetExpression? {
val parent = getParent() val parent = getParent()
when { when {
parent is JetQualifiedExpression && !isImportDirectiveExpression() -> { parent is JetQualifiedExpression -> {
val receiverExpression = parent.getReceiverExpression() val receiverExpression = parent.getReceiverExpression()
// Name expression can't be receiver for itself // Name expression can't be receiver for itself
if (receiverExpression != this) { if (receiverExpression != this) {
@@ -342,12 +342,12 @@ public fun JetModifierListOwner.isPrivate(): Boolean = hasModifier(JetTokens.PRI
public fun JetSimpleNameExpression.isImportDirectiveExpression(): Boolean { public fun JetSimpleNameExpression.isImportDirectiveExpression(): Boolean {
val parent = getParent() val parent = getParent()
if (parent == null) { return parent is JetImportDirective || parent?.getParent() is JetImportDirective
return false }
}
else { public fun JetSimpleNameExpression.isPackageDirectiveExpression(): Boolean {
return parent is JetImportDirective || parent.getParent() is JetImportDirective val parent = getParent()
} return parent is JetPackageDirective || parent?.getParent() is JetPackageDirective
} }
public fun JetExpression.isFunctionLiteralOutsideParentheses(): Boolean { public fun JetExpression.isFunctionLiteralOutsideParentheses(): Boolean {
@@ -28,9 +28,13 @@ import org.jetbrains.kotlin.idea.util.ShadowedDeclarationsFilter
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
@@ -102,18 +106,20 @@ public class ReferenceVariantsHelper(
explicitReceiverData: ExplicitReceiverData?, explicitReceiverData: ExplicitReceiverData?,
useRuntimeReceiverType: Boolean useRuntimeReceiverType: Boolean
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
val parent = expression.getParent() if (expression.isImportDirectiveExpression()) {
return getVariantsForImportOrPackageDirective(explicitReceiverData, kindFilter, nameFilter)
}
if (expression.isPackageDirectiveExpression()) {
val packageKindFilter = kindFilter restrictedToKinds DescriptorKindFilter.PACKAGES_MASK
return getVariantsForImportOrPackageDirective(explicitReceiverData, packageKindFilter, nameFilter)
}
if (expression.getParent() is JetUserType) {
return getVariantsForUserType(explicitReceiverData, expression, kindFilter, nameFilter)
}
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf() val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
val containingDeclaration = resolutionScope.getContainingDeclaration() val containingDeclaration = resolutionScope.getContainingDeclaration()
if (parent is JetImportDirective || parent is JetPackageDirective) {
return resolutionScope.getDescriptorsFiltered(kindFilter.restrictedToKinds(DescriptorKindFilter.PACKAGES_MASK), nameFilter)
}
if (parent is JetUserType) {
return resolutionScope.getDescriptorsFiltered(kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK), nameFilter)
}
val descriptors = LinkedHashSet<DeclarationDescriptor>() val descriptors = LinkedHashSet<DeclarationDescriptor>()
val dataFlowInfo = context.getDataFlowInfo(expression) val dataFlowInfo = context.getDataFlowInfo(expression)
@@ -163,6 +169,40 @@ public class ReferenceVariantsHelper(
return descriptors return descriptors
} }
private fun getVariantsForUserType(
explicitReceiverData: ExplicitReceiverData?,
expression: JetSimpleNameExpression,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
val accurateKindFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK)
if (explicitReceiverData != null) {
val qualifier = context[BindingContext.QUALIFIER, explicitReceiverData.expression] ?: return emptyList()
return qualifier.scope.getDescriptorsFiltered(accurateKindFilter, nameFilter)
}
else {
val lexicalScope = expression.getParentOfType<JetTypeReference>(strict = true)?.let {
context[BindingContext.TYPE_RESOLUTION_SCOPE, it]
} ?: return emptyList()
return lexicalScope.getDescriptorsFiltered(accurateKindFilter, nameFilter)
}
}
private fun getVariantsForImportOrPackageDirective(
explicitReceiverData: ExplicitReceiverData?,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
if (explicitReceiverData != null) {
val qualifier = context[BindingContext.QUALIFIER, explicitReceiverData.expression] ?: return emptyList()
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
}
else {
val rootPackage = resolutionFacade.moduleDescriptor.getPackage(FqName.ROOT)
return rootPackage.memberScope.getDescriptorsFiltered(kindFilter, nameFilter)
}
}
private fun MutableSet<DeclarationDescriptor>.processAll( private fun MutableSet<DeclarationDescriptor>.processAll(
implicitReceiverTypes: Collection<JetType>, implicitReceiverTypes: Collection<JetType>,
receiverTypes: Collection<JetType>, receiverTypes: Collection<JetType>,
@@ -304,6 +344,8 @@ public class ReferenceVariantsHelper(
is JetUnaryExpression -> CallType.UNARY is JetUnaryExpression -> CallType.UNARY
is JetUserType -> CallType.NORMAL
else -> return null else -> return null
} }
return ExplicitReceiverData(receiverExpression, callType) return ExplicitReceiverData(receiverExpression, callType)
@@ -0,0 +1,3 @@
package <caret>
// EXIST: java, kotlin
@@ -0,0 +1,5 @@
package java.<caret>
// EXIST: util, lang
// EXIST_JAVA_ONLY: awt
@@ -253,6 +253,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InEmptyPackage.kt")
public void testInEmptyPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InEmptyPackage.kt");
doTest(fileName);
}
@TestMetadata("InExpressionNoPrefix.kt") @TestMetadata("InExpressionNoPrefix.kt")
public void testInExpressionNoPrefix() throws Exception { public void testInExpressionNoPrefix() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt");
@@ -355,6 +361,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InPackage.kt")
public void testInPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InPackage.kt");
doTest(fileName);
}
@TestMetadata("InParametersTypes.kt") @TestMetadata("InParametersTypes.kt")
public void testInParametersTypes() throws Exception { public void testInParametersTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt");
@@ -253,6 +253,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InEmptyPackage.kt")
public void testInEmptyPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InEmptyPackage.kt");
doTest(fileName);
}
@TestMetadata("InExpressionNoPrefix.kt") @TestMetadata("InExpressionNoPrefix.kt")
public void testInExpressionNoPrefix() throws Exception { public void testInExpressionNoPrefix() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt");
@@ -355,6 +361,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InPackage.kt")
public void testInPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InPackage.kt");
doTest(fileName);
}
@TestMetadata("InParametersTypes.kt") @TestMetadata("InParametersTypes.kt")
public void testInParametersTypes() throws Exception { public void testInParametersTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt");