Completion of non-imported extensions in debugger for runtime receiver type

This commit is contained in:
Valentin Kipyatkov
2015-10-28 19:27:22 +03:00
parent c9048266c8
commit 0ee2b512ff
11 changed files with 57 additions and 15 deletions
@@ -240,9 +240,15 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
if (completionKind != CompletionKind.KEYWORDS_ONLY) {
completeNonImported()
flushToResultSet()
if (position.getContainingFile() is KtCodeFragment) {
flushToResultSet()
collector.addDescriptorElements(getRuntimeReceiverTypeReferenceVariants(), withReceiverCast = true)
val variants = getRuntimeReceiverTypeReferenceVariants()
if (variants != null) {
collector.addDescriptorElements(variants.imported, withReceiverCast = true)
collector.addDescriptorElements(variants.notImportedExtensions, withReceiverCast = true, notImported = true)
flushToResultSet()
}
}
}
}
@@ -324,18 +324,19 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
return this
}
protected fun getRuntimeReceiverTypeReferenceVariants(): Collection<DeclarationDescriptor> {
val explicitReceiver = callTypeAndReceiver.receiver as? KtExpression ?: return emptyList()
val type = bindingContext.getType(explicitReceiver) ?: return emptyList()
if (!TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, type)) return emptyList()
val evaluator = file.getCopyableUserData(KtCodeFragment.RUNTIME_TYPE_EVALUATOR) ?: return emptyList()
protected fun getRuntimeReceiverTypeReferenceVariants(): ReferenceVariants? {
val explicitReceiver = callTypeAndReceiver.receiver as? KtExpression ?: return null
val type = bindingContext.getType(explicitReceiver) ?: return null
if (!TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, type)) return null
val evaluator = file.getCopyableUserData(KtCodeFragment.RUNTIME_TYPE_EVALUATOR) ?: return null
val runtimeType = evaluator(explicitReceiver)
if (runtimeType == null || runtimeType == type) return emptyList()
if (runtimeType == null || runtimeType == type) return null
val (variants, notImportedExtensions/*TODO: use them*/) = collectReferenceVariants(descriptorKindFilter!!, runtimeType)
return variants.filter { descriptor ->
referenceVariants!!.imported.none { compareDescriptors(project, it, descriptor) }
}
val (variants, notImportedExtensions) = collectReferenceVariants(descriptorKindFilter!!, runtimeType)
val normalVariants = referenceVariants!!.imported + referenceVariants!!.notImportedExtensions
val filteredVariants = variants.filter { descriptor -> normalVariants.none { compareDescriptors(project, it, descriptor) } }
val filteredNotImportedExtensions = notImportedExtensions.filter { descriptor -> normalVariants.none { compareDescriptors(project, it, descriptor) } }
return ReferenceVariants(filteredVariants, filteredNotImportedExtensions)
}
protected fun shouldCompleteTopLevelCallablesFromIndex(): Boolean {
@@ -85,10 +85,12 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
}
if (position.getContainingFile() is KtCodeFragment) {
getRuntimeReceiverTypeReferenceVariants().forEach {
collector.addElements(filter(it).map { it.withReceiverCast() })
val variants = getRuntimeReceiverTypeReferenceVariants()
if (variants != null) {
variants.imported.forEach { collector.addElements(filter(it).map { it.withReceiverCast() }) }
variants.notImportedExtensions.forEach { collector.addElements(filter(it).map { it.withReceiverCast() }, notImported = true) }
flushToResultSet()
}
flushToResultSet()
}
}
@@ -0,0 +1,8 @@
fun foo(o: Any) {
<caret>val a = 1
}
// INVOCATION_COUNT: 1
// EXIST: read, write
// RUNTIME_TYPE: java.util.concurrent.locks.ReentrantReadWriteLock
@@ -0,0 +1,8 @@
fun foo(o: Any) {
<caret>val a = 1
}
// INVOCATION_COUNT: 1
// ELEMENT: read
// RUNTIME_TYPE: java.util.concurrent.locks.ReentrantReadWriteLock
@@ -0,0 +1 @@
(o as ReentrantReadWriteLock).read { <caret> }
@@ -0,0 +1,2 @@
import kotlin.concurrent.read
import java.util.concurrent.locks.ReentrantReadWriteLock
@@ -0,0 +1 @@
o.<caret>
@@ -64,4 +64,10 @@ public class CodeFragmentCompletionHandlerTestGenerated extends AbstractCodeFrag
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/runtimeCast/InsertImport.kt");
doTest(fileName);
}
@TestMetadata("NotImportedExtension.kt")
public void testNotImportedExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/runtimeCast/NotImportedExtension.kt");
doTest(fileName);
}
}
@@ -115,6 +115,12 @@ public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCom
doTest(fileName);
}
@TestMetadata("notImportedExtension.kt")
public void testNotImportedExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/runtimeType/notImportedExtension.kt");
doTest(fileName);
}
@TestMetadata("runtimeCast.kt")
public void testRuntimeCast() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt");