FIR IDE: Add visibility checks to the completion
Visibility checks currently do not work in some cases, for example: - public nested class of private class is seen globally - private_for_this does not work - some other cases I am not yet aware of If `FirVisibilityChecker.isVisible` fix those issues, they will be fixed automatically in the completion
This commit is contained in:
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
object O {
|
object O {
|
||||||
private val zzzz = 0
|
private val zzzz = 0
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
class Some() {
|
class Some() {
|
||||||
public val testPublic = 12
|
public val testPublic = 12
|
||||||
protected val testProtected = 12
|
protected val testProtected = 12
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
class Some() {
|
class Some() {
|
||||||
public val testPublic = 12
|
public val testPublic = 12
|
||||||
protected val testProtected = 12
|
protected val testProtected = 12
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class Base {
|
||||||
|
public val testPublic = 12
|
||||||
|
protected val testProtected = 12
|
||||||
|
private val testPrivate = 12
|
||||||
|
val testPackage = 12
|
||||||
|
|
||||||
|
fun baseClassMember() {
|
||||||
|
class Local {
|
||||||
|
init {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: testPublic, testProtected, testPackage, testPrivate
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class Base {
|
||||||
|
public val testPublic = 12
|
||||||
|
protected val testProtected = 12
|
||||||
|
private val testPrivate = 12
|
||||||
|
val testPackage = 12
|
||||||
|
|
||||||
|
fun baseClassMember() {
|
||||||
|
class Local {
|
||||||
|
fun localClassMemeber() {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: testPublic, testProtected, testPackage, testPrivate
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class BaseClass {
|
||||||
|
companion object {
|
||||||
|
val publicVal = 10
|
||||||
|
fun publicFun() {}
|
||||||
|
|
||||||
|
protected val protectedVal = 30
|
||||||
|
protected fun protectedFun() {}
|
||||||
|
|
||||||
|
private val privateVal = 30
|
||||||
|
private fun privateFun() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
BaseClass.<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: publicVal
|
||||||
|
// EXIST: publicFun
|
||||||
|
|
||||||
|
// ABSENT: protectedVal
|
||||||
|
// ABSENT: protectedFun
|
||||||
|
// ABSENT: privateVal
|
||||||
|
// ABSENT: privateFun
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class BaseClass {
|
||||||
|
companion object {
|
||||||
|
val publicVal = 10
|
||||||
|
fun publicFun() {}
|
||||||
|
|
||||||
|
protected val protectedVal = 30
|
||||||
|
protected fun protectedFun() {}
|
||||||
|
|
||||||
|
private val privateVal = 30
|
||||||
|
private fun privateFun() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Subclass : BaseClass() {
|
||||||
|
fun test() {
|
||||||
|
BaseClass.<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: publicVal
|
||||||
|
// EXIST: publicFun
|
||||||
|
// EXIST: protectedVal
|
||||||
|
// EXIST: protectedFun
|
||||||
|
|
||||||
|
// ABSENT: privateVal
|
||||||
|
// ABSENT: privateFun
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
fun foo(a: java.lang.Thread) {
|
fun foo(a: java.lang.Thread) {
|
||||||
a.na<caret>
|
a.na<caret>
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
class PublicTopLevelClass {
|
||||||
|
class PublicNestedClass
|
||||||
|
protected class ProtectedNestedClass
|
||||||
|
private class PrivateNestedClass
|
||||||
|
|
||||||
|
inner class PublicInnerClass
|
||||||
|
protected inner class ProtectedInnerClass
|
||||||
|
private inner class PrivateInnerClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PrivateTopLevelClass
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun usage(): P<caret> {}
|
||||||
|
|
||||||
|
// EXIST: PublicTopLevelClass, PublicNestedClass, PublicInnerClass
|
||||||
|
// ABSENT: PrivateNestedClass, PrivateInnerClass, ProtectedNestedClass, ProtectedInnerClass, PrivateTopLevelClass
|
||||||
+2
@@ -4,3 +4,5 @@ val String.helloProp1: Int get() = 1
|
|||||||
val String.helloProp2: Int get() = 2
|
val String.helloProp2: Int get() = 2
|
||||||
val Int.helloProp3: Int get() = 3
|
val Int.helloProp3: Int get() = 3
|
||||||
val helloProp4: Int = 4
|
val helloProp4: Int = 4
|
||||||
|
|
||||||
|
private val String.helloPropPrivate get() = 1
|
||||||
+4
-2
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
package first
|
package first
|
||||||
|
|
||||||
fun firstFun() {
|
fun firstFun() {
|
||||||
@@ -5,8 +6,9 @@ fun firstFun() {
|
|||||||
a.hello<caret>
|
a.hello<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { lookupString: "helloProp1", attributes: "bold" }
|
// EXIST: helloProp1
|
||||||
// EXIST: { lookupString: "helloProp2", attributes: "bold" }
|
// EXIST: helloProp2
|
||||||
// ABSENT: helloProp3
|
// ABSENT: helloProp3
|
||||||
// ABSENT: helloProp4
|
// ABSENT: helloProp4
|
||||||
|
// ABSENT: helloPropPrivate
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
Vendored
+2
@@ -6,3 +6,5 @@ fun globalFun2(): Int = 1
|
|||||||
object Some {
|
object Some {
|
||||||
fun globalFun3(): Int = 3
|
fun globalFun3(): Int = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun globalFunPrivate() {}
|
||||||
|
|||||||
+1
@@ -7,3 +7,4 @@ fun testFun() {
|
|||||||
|
|
||||||
// EXIST: globalFun1, globalFun2
|
// EXIST: globalFun1, globalFun2
|
||||||
// ABSENT: globalFun3
|
// ABSENT: globalFun3
|
||||||
|
// ABSENT: globalFunPrivate
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
private class PrivateTopLevelClass {
|
||||||
|
class PublicNestedClass
|
||||||
|
protected class ProtectedNestedClass
|
||||||
|
private class PrivateNestedClass
|
||||||
|
|
||||||
|
inner class PublicInnerClass
|
||||||
|
protected inner class ProtectedInnerClass
|
||||||
|
private inner class PrivateInnerClass
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
fun usage(): P<caret> {}
|
||||||
|
|
||||||
|
// ABSENT: PrivateTopLevelClass
|
||||||
|
|
||||||
|
// ABSENT: PublicNestedClass
|
||||||
|
// ABSENT: ProtectedNestedClass
|
||||||
|
// ABSENT: PrivateNestedClass
|
||||||
|
|
||||||
|
// ABSENT: PublicInnerClass
|
||||||
|
// ABSENT: ProtectedInnerClass
|
||||||
|
// ABSENT: PrivateInnerClass
|
||||||
Vendored
+2
@@ -2,3 +2,5 @@ package first
|
|||||||
|
|
||||||
fun secondFun() {
|
fun secondFun() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun secondFunPrivate() {}
|
||||||
+1
@@ -6,3 +6,4 @@ fun firstFun() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: secondFun
|
// EXIST: secondFun
|
||||||
|
// ABSENT: secondFunPrivate
|
||||||
+20
@@ -2882,6 +2882,26 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassConstructor.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassConstructor() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassMember.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassMember() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassMember.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromOutside.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromOutside() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromOutside.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromSubclass.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromSubclass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromSubclass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("VisibilityPrivateToThis.kt")
|
@TestMetadata("VisibilityPrivateToThis.kt")
|
||||||
public void testVisibilityPrivateToThis() throws Exception {
|
public void testVisibilityPrivateToThis() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
||||||
|
|||||||
+20
@@ -2882,6 +2882,26 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassConstructor.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassConstructor() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassMember.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassMember() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassMember.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromOutside.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromOutside() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromOutside.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromSubclass.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromSubclass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromSubclass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("VisibilityPrivateToThis.kt")
|
@TestMetadata("VisibilityPrivateToThis.kt")
|
||||||
public void testVisibilityPrivateToThis() throws Exception {
|
public void testVisibilityPrivateToThis() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
||||||
|
|||||||
+10
@@ -224,6 +224,11 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
|
|||||||
runTest("idea/idea-completion/testData/basic/multifile/NoGenericFunDuplication/");
|
runTest("idea/idea-completion/testData/basic/multifile/NoGenericFunDuplication/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotImportedClass")
|
||||||
|
public void testNotImportedClass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedClass/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NotImportedExtensionForImplicitReceiver")
|
@TestMetadata("NotImportedExtensionForImplicitReceiver")
|
||||||
public void testNotImportedExtensionForImplicitReceiver() throws Exception {
|
public void testNotImportedExtensionForImplicitReceiver() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedExtensionForImplicitReceiver/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedExtensionForImplicitReceiver/");
|
||||||
@@ -269,6 +274,11 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
|
|||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedJavaClass/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedJavaClass/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotImportedNestedClassFromPrivateClass")
|
||||||
|
public void testNotImportedNestedClassFromPrivateClass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedNestedClassFromPrivateClass/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NotImportedObject")
|
@TestMetadata("NotImportedObject")
|
||||||
public void testNotImportedObject() throws Exception {
|
public void testNotImportedObject() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedObject/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedObject/");
|
||||||
|
|||||||
+66
-27
@@ -21,10 +21,9 @@ import org.jetbrains.kotlin.idea.frontend.api.analyseInFakeAnalysisSession
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.isExtension
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.isExtension
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
@@ -86,6 +85,18 @@ private fun interface ExtensionApplicabilityChecker {
|
|||||||
fun isApplicable(symbol: KtCallableSymbol): Boolean
|
fun isApplicable(symbol: KtCallableSymbol): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun interface CompletionVisibilityChecker {
|
||||||
|
fun isVisible(symbol: KtSymbolWithVisibility): Boolean
|
||||||
|
|
||||||
|
fun isVisible(symbol: KtCallableSymbol): Boolean {
|
||||||
|
return symbol !is KtSymbolWithVisibility || isVisible(symbol as KtSymbolWithVisibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isVisible(symbol: KtClassifierSymbol): Boolean {
|
||||||
|
return symbol !is KtSymbolWithVisibility || isVisible(symbol as KtSymbolWithVisibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently, this class is responsible for collecting all possible completion variants.
|
* Currently, this class is responsible for collecting all possible completion variants.
|
||||||
*
|
*
|
||||||
@@ -138,6 +149,7 @@ private class KotlinCommonCompletionProvider(
|
|||||||
val explicitReceiver = nameExpression.getReceiverExpression()
|
val explicitReceiver = nameExpression.getReceiverExpression()
|
||||||
|
|
||||||
analyseInFakeAnalysisSession(originalFile, nameExpression) {
|
analyseInFakeAnalysisSession(originalFile, nameExpression) {
|
||||||
|
val fileSymbol = originalFile.getFileSymbol()
|
||||||
val expectedType = nameExpression.getExpectedType()
|
val expectedType = nameExpression.getExpectedType()
|
||||||
|
|
||||||
val scopesContext = originalFile.getScopeContextForPosition(nameExpression)
|
val scopesContext = originalFile.getScopeContextForPosition(nameExpression)
|
||||||
@@ -146,16 +158,24 @@ private class KotlinCommonCompletionProvider(
|
|||||||
it.checkExtensionIsSuitable(originalFile, nameExpression, explicitReceiver)
|
it.checkExtensionIsSuitable(originalFile, nameExpression, explicitReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val visibilityChecker = CompletionVisibilityChecker {
|
||||||
|
parameters.invocationCount > 1 || isVisible(it, fileSymbol, explicitReceiver, parameters.position)
|
||||||
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
nameExpression.parent is KtUserType -> collectTypesCompletion(result, scopesContext.scopes, expectedType)
|
nameExpression.parent is KtUserType -> collectTypesCompletion(result, scopesContext.scopes, expectedType, visibilityChecker)
|
||||||
explicitReceiver != null -> collectDotCompletion(
|
explicitReceiver != null -> {
|
||||||
result,
|
collectDotCompletion(
|
||||||
scopesContext.scopes,
|
result,
|
||||||
explicitReceiver,
|
scopesContext.scopes,
|
||||||
expectedType,
|
explicitReceiver,
|
||||||
extensionChecker
|
expectedType,
|
||||||
)
|
extensionChecker,
|
||||||
else -> collectDefaultCompletion(result, scopesContext, expectedType, extensionChecker)
|
visibilityChecker,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> collectDefaultCompletion(result, scopesContext, expectedType, extensionChecker, visibilityChecker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,12 +184,19 @@ private class KotlinCommonCompletionProvider(
|
|||||||
result: CompletionResultSet,
|
result: CompletionResultSet,
|
||||||
implicitScopes: KtScope,
|
implicitScopes: KtScope,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker,
|
||||||
) {
|
) {
|
||||||
val classesFromScopes = implicitScopes.getClassifierSymbols(scopeNameFilter)
|
val classesFromScopes = implicitScopes
|
||||||
|
.getClassifierSymbols(scopeNameFilter)
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
|
|
||||||
classesFromScopes.forEach { addSymbolToCompletion(result, expectedType, it) }
|
classesFromScopes.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
val kotlinClassesFromIndices = indexHelper.getKotlinClasses(scopeNameFilter, psiFilter = { it !is KtEnumEntry })
|
val kotlinClassesFromIndices = indexHelper.getKotlinClasses(scopeNameFilter, psiFilter = { it !is KtEnumEntry })
|
||||||
kotlinClassesFromIndices.forEach { addSymbolToCompletion(result, expectedType, it.getSymbol()) }
|
kotlinClassesFromIndices.asSequence()
|
||||||
|
.map { it.getSymbol() as KtClassifierSymbol }
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectDotCompletion(
|
private fun KtAnalysisSession.collectDotCompletion(
|
||||||
@@ -178,19 +205,19 @@ private class KotlinCommonCompletionProvider(
|
|||||||
explicitReceiver: KtExpression,
|
explicitReceiver: KtExpression,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
extensionChecker: ExtensionApplicabilityChecker,
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker,
|
||||||
) {
|
) {
|
||||||
val typeOfPossibleReceiver = explicitReceiver.getKtType()
|
val typeOfPossibleReceiver = explicitReceiver.getKtType()
|
||||||
val possibleReceiverScope = typeOfPossibleReceiver.getTypeScope() ?: return
|
val possibleReceiverScope = typeOfPossibleReceiver.getTypeScope() ?: return
|
||||||
|
|
||||||
val nonExtensionMembers = possibleReceiverScope.collectNonExtensions()
|
val nonExtensionMembers = possibleReceiverScope.collectNonExtensions(visibilityChecker)
|
||||||
val extensionNonMembers = implicitScopes.collectSuitableExtensions(extensionChecker)
|
val extensionNonMembers = implicitScopes.collectSuitableExtensions(extensionChecker, visibilityChecker)
|
||||||
|
|
||||||
nonExtensionMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
nonExtensionMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
extensionNonMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
extensionNonMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker)
|
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker, visibilityChecker)
|
||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectDefaultCompletion(
|
private fun KtAnalysisSession.collectDefaultCompletion(
|
||||||
@@ -198,11 +225,12 @@ private class KotlinCommonCompletionProvider(
|
|||||||
implicitScopesContext: KtScopeContext,
|
implicitScopesContext: KtScopeContext,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
extensionChecker: ExtensionApplicabilityChecker,
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker,
|
||||||
) {
|
) {
|
||||||
val (implicitScopes, implicitReceiversTypes) = implicitScopesContext
|
val (implicitScopes, implicitReceiversTypes) = implicitScopesContext
|
||||||
|
|
||||||
val availableNonExtensions = implicitScopes.collectNonExtensions()
|
val availableNonExtensions = implicitScopes.collectNonExtensions(visibilityChecker)
|
||||||
val extensionsWhichCanBeCalled = implicitScopes.collectSuitableExtensions(extensionChecker)
|
val extensionsWhichCanBeCalled = implicitScopes.collectSuitableExtensions(extensionChecker, visibilityChecker)
|
||||||
|
|
||||||
availableNonExtensions.forEach { addSymbolToCompletion(result, expectedType, it) }
|
availableNonExtensions.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(result, expectedType, it) }
|
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
@@ -210,33 +238,44 @@ private class KotlinCommonCompletionProvider(
|
|||||||
if (shouldCompleteTopLevelCallablesFromIndex) {
|
if (shouldCompleteTopLevelCallablesFromIndex) {
|
||||||
val topLevelCallables = indexHelper.getTopLevelCallables(scopeNameFilter)
|
val topLevelCallables = indexHelper.getTopLevelCallables(scopeNameFilter)
|
||||||
topLevelCallables.asSequence()
|
topLevelCallables.asSequence()
|
||||||
.map { it.getSymbol() }
|
.map { it.getSymbol() as KtCallableSymbol }
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker)
|
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker)
|
||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
collectTypesCompletion(result, implicitScopes, expectedType)
|
collectTypesCompletion(result, implicitScopes, expectedType, visibilityChecker)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
||||||
receiverTypes: List<KtType>,
|
receiverTypes: List<KtType>,
|
||||||
extensionChecker: ExtensionApplicabilityChecker,
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker,
|
||||||
): Sequence<KtCallableSymbol> {
|
): Sequence<KtCallableSymbol> {
|
||||||
val implicitReceiverNames = findAllNamesOfTypes(receiverTypes)
|
val implicitReceiverNames = findAllNamesOfTypes(receiverTypes)
|
||||||
val topLevelExtensions = indexHelper.getTopLevelExtensions(scopeNameFilter, implicitReceiverNames)
|
val topLevelExtensions = indexHelper.getTopLevelExtensions(scopeNameFilter, implicitReceiverNames)
|
||||||
|
|
||||||
return topLevelExtensions.asSequence()
|
return topLevelExtensions.asSequence()
|
||||||
.map { it.getSymbol() as KtCallableSymbol }
|
.map { it.getSymbol() as KtCallableSymbol }
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
.filter { extensionChecker.isApplicable(it) }
|
.filter { extensionChecker.isApplicable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtScope.collectNonExtensions(): Sequence<KtCallableSymbol> =
|
private fun KtScope.collectNonExtensions(visibilityChecker: CompletionVisibilityChecker) =
|
||||||
getCallableSymbols(scopeNameFilter).filterNot { it.isExtension }
|
getCallableSymbols(scopeNameFilter)
|
||||||
|
.filterNot { it.isExtension }
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
|
|
||||||
private fun KtScope.collectSuitableExtensions(extensionChecker: ExtensionApplicabilityChecker): Sequence<KtCallableSymbol> =
|
private fun KtCompositeScope.collectSuitableExtensions(
|
||||||
getCallableSymbols(scopeNameFilter).filter { it.isExtension && extensionChecker.isApplicable(it) }
|
hasSuitableExtensionReceiver: ExtensionApplicabilityChecker,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker,
|
||||||
|
): Sequence<KtCallableSymbol> =
|
||||||
|
getCallableSymbols(scopeNameFilter)
|
||||||
|
.filter { it.isExtension }
|
||||||
|
.filter { visibilityChecker.isVisible(it) }
|
||||||
|
.filter { hasSuitableExtensionReceiver.isApplicable(it) }
|
||||||
|
|
||||||
private fun KtAnalysisSession.findAllNamesOfTypes(implicitReceiversTypes: List<KtType>) =
|
private fun KtAnalysisSession.findAllNamesOfTypes(implicitReceiversTypes: List<KtType>) =
|
||||||
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
||||||
|
|||||||
+20
@@ -2882,6 +2882,26 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
|
|||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityInSubclassForce.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassConstructor.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassConstructor() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfClassMembersFromLocalClassMember.kt")
|
||||||
|
public void testVisibilityOfClassMembersFromLocalClassMember() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfClassMembersFromLocalClassMember.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromOutside.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromOutside() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromOutside.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VisibilityOfCompanionObjectMembersFromSubclass.kt")
|
||||||
|
public void testVisibilityOfCompanionObjectMembersFromSubclass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityOfCompanionObjectMembersFromSubclass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("VisibilityPrivateToThis.kt")
|
@TestMetadata("VisibilityPrivateToThis.kt")
|
||||||
public void testVisibilityPrivateToThis() throws Exception {
|
public void testVisibilityPrivateToThis() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
runTest("idea/idea-completion/testData/basic/common/visibility/VisibilityPrivateToThis.kt");
|
||||||
|
|||||||
+10
@@ -224,6 +224,11 @@ public class HighLevelMultiFileJvmBasicCompletionTestGenerated extends AbstractH
|
|||||||
runTest("idea/idea-completion/testData/basic/multifile/NoGenericFunDuplication/");
|
runTest("idea/idea-completion/testData/basic/multifile/NoGenericFunDuplication/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotImportedClass")
|
||||||
|
public void testNotImportedClass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedClass/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NotImportedExtensionForImplicitReceiver")
|
@TestMetadata("NotImportedExtensionForImplicitReceiver")
|
||||||
public void testNotImportedExtensionForImplicitReceiver() throws Exception {
|
public void testNotImportedExtensionForImplicitReceiver() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedExtensionForImplicitReceiver/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedExtensionForImplicitReceiver/");
|
||||||
@@ -269,6 +274,11 @@ public class HighLevelMultiFileJvmBasicCompletionTestGenerated extends AbstractH
|
|||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedJavaClass/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedJavaClass/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotImportedNestedClassFromPrivateClass")
|
||||||
|
public void testNotImportedNestedClassFromPrivateClass() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedNestedClassFromPrivateClass/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NotImportedObject")
|
@TestMetadata("NotImportedObject")
|
||||||
public void testNotImportedObject() throws Exception {
|
public void testNotImportedObject() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/multifile/NotImportedObject/");
|
runTest("idea/idea-completion/testData/basic/multifile/NotImportedObject/");
|
||||||
|
|||||||
Reference in New Issue
Block a user