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? {
val parent = getParent()
when {
parent is JetQualifiedExpression && !isImportDirectiveExpression() -> {
parent is JetQualifiedExpression -> {
val receiverExpression = parent.getReceiverExpression()
// Name expression can't be receiver for itself
if (receiverExpression != this) {
@@ -342,12 +342,12 @@ public fun JetModifierListOwner.isPrivate(): Boolean = hasModifier(JetTokens.PRI
public fun JetSimpleNameExpression.isImportDirectiveExpression(): Boolean {
val parent = getParent()
if (parent == null) {
return false
}
else {
return parent is JetImportDirective || parent.getParent() is JetImportDirective
}
return parent is JetImportDirective || parent?.getParent() is JetImportDirective
}
public fun JetSimpleNameExpression.isPackageDirectiveExpression(): Boolean {
val parent = getParent()
return parent is JetPackageDirective || parent?.getParent() is JetPackageDirective
}
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.substituteExtensionIfCallable
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
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.isImportDirectiveExpression
import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
@@ -102,18 +106,20 @@ public class ReferenceVariantsHelper(
explicitReceiverData: ExplicitReceiverData?,
useRuntimeReceiverType: Boolean
): 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 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 dataFlowInfo = context.getDataFlowInfo(expression)
@@ -163,6 +169,40 @@ public class ReferenceVariantsHelper(
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(
implicitReceiverTypes: Collection<JetType>,
receiverTypes: Collection<JetType>,
@@ -304,6 +344,8 @@ public class ReferenceVariantsHelper(
is JetUnaryExpression -> CallType.UNARY
is JetUserType -> CallType.NORMAL
else -> return null
}
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);
}
@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")
public void testInExpressionNoPrefix() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt");
@@ -355,6 +361,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
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")
public void testInParametersTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt");
@@ -253,6 +253,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
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")
public void testInExpressionNoPrefix() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InExpressionNoPrefix.kt");
@@ -355,6 +361,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
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")
public void testInParametersTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InParametersTypes.kt");