Extension callables index and its use in completion
This commit is contained in:
@@ -98,7 +98,7 @@ public class JetProperty extends JetTypeParameterListOwnerStub<KotlinPropertyStu
|
||||
public JetTypeReference getReceiverTypeReference() {
|
||||
KotlinPropertyStub stub = getStub();
|
||||
if (stub != null) {
|
||||
if (!stub.hasReceiverTypeRef()) {
|
||||
if (!stub.isExtension()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
@@ -134,7 +134,7 @@ public class JetProperty extends JetTypeParameterListOwnerStub<KotlinPropertyStu
|
||||
}
|
||||
else {
|
||||
List<JetTypeReference> typeReferences = getStubOrPsiChildrenAsList(JetStubElementTypes.TYPE_REFERENCE);
|
||||
int returnTypeRefPositionInPsi = stub.hasReceiverTypeRef() ? 1 : 0;
|
||||
int returnTypeRefPositionInPsi = stub.isExtension() ? 1 : 0;
|
||||
if (typeReferences.size() <= returnTypeRefPositionInPsi) {
|
||||
LOG.error("Invalid stub structure built for property:\n" + getText());
|
||||
return null;
|
||||
|
||||
@@ -56,13 +56,10 @@ public trait KotlinAnnotationEntryStub : StubElement<JetAnnotationEntry> {
|
||||
public fun hasValueArguments(): Boolean
|
||||
}
|
||||
|
||||
public trait KotlinFunctionStub : KotlinStubWithFqName<JetNamedFunction> {
|
||||
public fun isTopLevel(): Boolean
|
||||
public fun isExtension(): Boolean
|
||||
public trait KotlinFunctionStub : KotlinCallableStubBase<JetNamedFunction> {
|
||||
public fun hasBlockBody(): Boolean
|
||||
public fun hasBody(): Boolean
|
||||
public fun hasTypeParameterListBeforeFunctionName(): Boolean
|
||||
public fun isProbablyNothingType(): Boolean
|
||||
}
|
||||
|
||||
public trait KotlinImportDirectiveStub : StubElement<JetImportDirective> {
|
||||
@@ -92,14 +89,17 @@ public trait KotlinPropertyAccessorStub : StubElement<JetPropertyAccessor> {
|
||||
public fun hasBlockBody(): Boolean
|
||||
}
|
||||
|
||||
public trait KotlinPropertyStub : KotlinStubWithFqName<JetProperty> {
|
||||
public trait KotlinPropertyStub : KotlinCallableStubBase<JetProperty> {
|
||||
public fun isVar(): Boolean
|
||||
public fun isTopLevel(): Boolean
|
||||
public fun hasDelegate(): Boolean
|
||||
public fun hasDelegateExpression(): Boolean
|
||||
public fun hasInitializer(): Boolean
|
||||
public fun hasReceiverTypeRef(): Boolean
|
||||
public fun hasReturnTypeRef(): Boolean
|
||||
}
|
||||
|
||||
public trait KotlinCallableStubBase<TDeclaration: JetCallableDeclaration> : KotlinStubWithFqName<TDeclaration> {
|
||||
public fun isTopLevel(): Boolean
|
||||
public fun isExtension(): Boolean
|
||||
public fun isProbablyNothingType(): Boolean
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class JetPropertyElementType extends JetStubElementType<KotlinPropertyStu
|
||||
dataStream.writeBoolean(stub.hasDelegate());
|
||||
dataStream.writeBoolean(stub.hasDelegateExpression());
|
||||
dataStream.writeBoolean(stub.hasInitializer());
|
||||
dataStream.writeBoolean(stub.hasReceiverTypeRef());
|
||||
dataStream.writeBoolean(stub.isExtension());
|
||||
dataStream.writeBoolean(stub.hasReturnTypeRef());
|
||||
dataStream.writeBoolean(stub.isProbablyNothingType());
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class KotlinPropertyStubImpl(
|
||||
private val hasDelegate: Boolean,
|
||||
private val hasDelegateExpression: Boolean,
|
||||
private val hasInitializer: Boolean,
|
||||
private val hasReceiverTypeRef: Boolean,
|
||||
private val isExtension: Boolean,
|
||||
private val hasReturnTypeRef: Boolean,
|
||||
private val isProbablyNothingType: Boolean,
|
||||
private val fqName: FqName?
|
||||
@@ -53,7 +53,7 @@ public class KotlinPropertyStubImpl(
|
||||
override fun hasDelegate() = hasDelegate
|
||||
override fun hasDelegateExpression() = hasDelegateExpression
|
||||
override fun hasInitializer() = hasInitializer
|
||||
override fun hasReceiverTypeRef() = hasReceiverTypeRef
|
||||
override fun isExtension() = isExtension
|
||||
override fun hasReturnTypeRef() = hasReturnTypeRef
|
||||
override fun getName() = StringRef.toString(name)
|
||||
override fun isProbablyNothingType() = isProbablyNothingType
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ private class CallableClsStubBuilder(
|
||||
hasDelegate = false,
|
||||
hasDelegateExpression = false,
|
||||
hasInitializer = false,
|
||||
hasReceiverTypeRef = callableProto.hasReceiverType(),
|
||||
isExtension = callableProto.hasReceiverType(),
|
||||
hasReturnTypeRef = true,
|
||||
fqName = c.containerFqName.child(callableName),
|
||||
isProbablyNothingType = isProbablyNothing(callableProto)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.stubindex
|
||||
|
||||
import com.intellij.psi.stubs.IndexSink
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinCallableStubBase
|
||||
|
||||
fun indexTopLevelExtension<TDeclaration : JetCallableDeclaration>(stub: KotlinCallableStubBase<TDeclaration>, sink: IndexSink) {
|
||||
if (stub.isExtension()) {
|
||||
val declaration = stub.getPsi()
|
||||
declaration.getReceiverTypeReference()!!.getTypeElement()?.index(declaration, sink)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <TDeclaration : JetCallableDeclaration> JetTypeElement.index(declaration: TDeclaration, sink: IndexSink) {
|
||||
fun occurrence(typeName: String) {
|
||||
val name = declaration.getName() ?: return
|
||||
sink.occurrence(JetTopLevelExtensionsByReceiverTypeIndex.INSTANCE.getKey(),
|
||||
JetTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name))
|
||||
}
|
||||
|
||||
when (this) {
|
||||
is JetUserType -> {
|
||||
//TODO: aliases
|
||||
var typeName = getReferencedName() ?: return
|
||||
|
||||
if (declaration is JetNamedFunction) {
|
||||
val typeParameter = declaration.getTypeParameters().firstOrNull { it.getName() == typeName }
|
||||
if (typeParameter != null) {
|
||||
val bound = typeParameter.getExtendsBound()
|
||||
if (bound != null) {
|
||||
bound.getTypeElement()?.index(declaration, sink)
|
||||
return
|
||||
}
|
||||
typeName = "Any"
|
||||
}
|
||||
}
|
||||
|
||||
occurrence(typeName)
|
||||
}
|
||||
|
||||
is JetNullableType -> getInnerType()?.index(declaration, sink)
|
||||
|
||||
is JetFunctionType -> {
|
||||
val typeName = (if (getReceiverTypeReference() != null) "ExtensionFunction" else "Function") + getParameters().size()
|
||||
occurrence(typeName)
|
||||
}
|
||||
|
||||
else -> occurrence("Any")
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.stubindex
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import com.intellij.psi.stubs.StubIndexKey
|
||||
import org.jetbrains.kotlin.psi.JetCallableDeclaration
|
||||
|
||||
public class JetTopLevelExtensionsByReceiverTypeIndex private() : StringStubIndexExtension<JetCallableDeclaration>() {
|
||||
|
||||
override fun getKey() = KEY
|
||||
|
||||
override fun get(s: String, project: Project, scope: GlobalSearchScope)
|
||||
= super.get(s, project, JetSourceFilterScope.kotlinSourcesAndLibraries(scope, project))
|
||||
|
||||
companion object {
|
||||
private val KEY = KotlinIndexUtil.createIndexKey<String, JetCallableDeclaration>(javaClass<JetTopLevelExtensionsByReceiverTypeIndex>())
|
||||
|
||||
public val INSTANCE: JetTopLevelExtensionsByReceiverTypeIndex = JetTopLevelExtensionsByReceiverTypeIndex()
|
||||
|
||||
public fun buildKey(receiverTypeName: String, callableName: String): String = receiverTypeName + "\n" + callableName
|
||||
|
||||
public fun receiverTypeNameFromKey(key: String): String = key.substringBefore('\n', "")
|
||||
|
||||
public fun callableNameFromKey(key: String): String = key.substringAfter('\n', "")
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -17,10 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.stubindex;
|
||||
|
||||
import com.intellij.psi.stubs.IndexSink;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.stubs.*;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.StubIndexService;
|
||||
@@ -95,6 +92,7 @@ public class StubIndexServiceImpl implements StubIndexService {
|
||||
if (fqName != null) {
|
||||
sink.occurrence(JetTopLevelFunctionFqnNameIndex.getInstance().getKey(), fqName.asString());
|
||||
sink.occurrence(JetTopLevelFunctionByPackageIndex.getInstance().getKey(), fqName.parent().asString());
|
||||
StubindexPackage.indexTopLevelExtension(stub, sink);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,6 +114,7 @@ public class StubIndexServiceImpl implements StubIndexService {
|
||||
if (fqName != null) {
|
||||
sink.occurrence(JetTopLevelPropertyFqnNameIndex.getInstance().getKey(), fqName.asString());
|
||||
sink.occurrence(JetTopLevelPropertyByPackageIndex.getInstance().getKey(), fqName.parent().asString());
|
||||
StubindexPackage.indexTopLevelExtension(stub, sink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,6 +428,7 @@
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetSuperClassIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetTopLevelFunctionFqnNameIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetTopLevelPropertyFqnNameIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetTopLevelExtensionsByReceiverTypeIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetAnnotationsIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetProbablyNothingFunctionShortNameIndex"/>
|
||||
<stubIndex implementation="org.jetbrains.kotlin.idea.stubindex.JetProbablyNothingPropertyShortNameIndex"/>
|
||||
|
||||
@@ -16,28 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
|
||||
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver.LookupMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import java.util.HashSet
|
||||
import java.util.LinkedHashSet
|
||||
|
||||
public class KotlinIndicesHelper(
|
||||
private val project: Project,
|
||||
@@ -78,74 +81,95 @@ public class KotlinIndicesHelper(
|
||||
}
|
||||
|
||||
public fun getCallableTopLevelExtensions(nameFilter: (String) -> Boolean, expression: JetSimpleNameExpression): Collection<CallableDescriptor> {
|
||||
val receiverValues = receiverValues(expression)
|
||||
if (receiverValues.isEmpty()) return emptyList()
|
||||
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
|
||||
|
||||
val functionsIndex = JetTopLevelFunctionFqnNameIndex.getInstance()
|
||||
val propertiesIndex = JetTopLevelPropertyFqnNameIndex.getInstance()
|
||||
val receiverTypeNames = possibleReceiverTypeNames(receiverValues.map { it.first }, dataFlowInfo)
|
||||
|
||||
val functionFqNames = functionsIndex.getAllKeys(project).sequence().map { FqName(it) }
|
||||
val propertyFqNames = propertiesIndex.getAllKeys(project).sequence().map { FqName(it) }
|
||||
val index = JetTopLevelExtensionsByReceiverTypeIndex.INSTANCE
|
||||
|
||||
val result = HashSet<CallableDescriptor>()
|
||||
result.fqNamesToSuitableExtensions(functionFqNames, nameFilter, functionsIndex, expression, bindingContext, dataFlowInfo)
|
||||
result.fqNamesToSuitableExtensions(propertyFqNames, nameFilter, propertiesIndex, expression, bindingContext, dataFlowInfo)
|
||||
val declarations = index.getAllKeys(project)
|
||||
.sequence()
|
||||
.filter {
|
||||
JetTopLevelExtensionsByReceiverTypeIndex.receiverTypeNameFromKey(it) in receiverTypeNames
|
||||
&& nameFilter(JetTopLevelExtensionsByReceiverTypeIndex.callableNameFromKey(it))
|
||||
}
|
||||
.flatMap { index.get(it, project, scope).sequence() }
|
||||
|
||||
return findSuitableExtensions(declarations, receiverValues, dataFlowInfo, bindingContext)
|
||||
}
|
||||
|
||||
private fun possibleReceiverTypeNames(receiverValues: Collection<ReceiverValue>, dataFlowInfo: DataFlowInfo): Set<String> {
|
||||
val result = LinkedHashSet<String>()
|
||||
for (receiverValue in receiverValues) {
|
||||
for (type in SmartCastUtils.getSmartCastVariants(receiverValue, bindingContext, dataFlowInfo)) {
|
||||
result.addTypeNames(type)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun MutableCollection<CallableDescriptor>.fqNamesToSuitableExtensions(
|
||||
fqNames: Sequence<FqName>,
|
||||
nameFilter: (String) -> Boolean,
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>,
|
||||
expression: JetSimpleNameExpression,
|
||||
bindingContext: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo) {
|
||||
val matchingNames = fqNames.filter { nameFilter(it.shortName().asString()) }
|
||||
|
||||
private fun receiverValues(expression: JetSimpleNameExpression): Collection<Pair<ReceiverValue, CallType>> {
|
||||
val receiverPair = ReferenceVariantsHelper.getExplicitReceiverData(expression)
|
||||
if (receiverPair != null) {
|
||||
val (receiverExpression, callType) = receiverPair
|
||||
|
||||
val expressionType = bindingContext[BindingContext.EXPRESSION_TYPE, receiverExpression]
|
||||
if (expressionType == null || expressionType.isError()) return
|
||||
if (expressionType == null || expressionType.isError()) return emptyList()
|
||||
|
||||
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
||||
|
||||
matchingNames.flatMapTo(this) {
|
||||
findSuitableExtensions(it, index, receiverValue, dataFlowInfo, callType, bindingContext)
|
||||
}
|
||||
return listOf(receiverValue to callType)
|
||||
}
|
||||
else {
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, expression] ?: return
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, expression] ?: return emptyList()
|
||||
|
||||
for (receiver in resolutionScope.getImplicitReceiversWithInstance()) {
|
||||
matchingNames.flatMapTo(this) {
|
||||
findSuitableExtensions(it, index, receiver.getValue(), dataFlowInfo, CallType.NORMAL, bindingContext)
|
||||
}
|
||||
}
|
||||
return resolutionScope.getImplicitReceiversWithInstance().map { it.getValue() to CallType.NORMAL }
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableCollection<String>.addTypeNames(type: JetType) {
|
||||
val constructor = type.getConstructor()
|
||||
addIfNotNull(constructor.getDeclarationDescriptor()?.getName()?.asString())
|
||||
constructor.getSupertypes().forEach { addTypeNames(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that function or property with the given qualified name can be resolved in given scope and called on given receiver
|
||||
*/
|
||||
private fun findSuitableExtensions(callableFQN: FqName,
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>,
|
||||
receiverValue: ReceiverValue,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
callType: CallType,
|
||||
bindingContext: BindingContext): Sequence<CallableDescriptor> {
|
||||
val extensions = index.get(callableFQN.asString(), project, scope).filter { it.getReceiverTypeReference() != null }
|
||||
val descriptors = if (extensions.any { it.getContainingJetFile().isCompiled() } ) { //TODO: it's temporary while resolveToDescriptor does not work for compiled declarations
|
||||
analyzeImportReference(callableFQN)
|
||||
.filterIsInstance<CallableDescriptor>()
|
||||
.filter { it.getExtensionReceiverParameter() != null }
|
||||
private fun findSuitableExtensions(
|
||||
declarations: Sequence<JetCallableDeclaration>,
|
||||
receiverValues: Collection<Pair<ReceiverValue, CallType>>,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
bindingContext: BindingContext
|
||||
): Collection<CallableDescriptor> {
|
||||
val result = LinkedHashSet<CallableDescriptor>()
|
||||
|
||||
fun processDescriptor(descriptor: CallableDescriptor) {
|
||||
if (visibilityFilter(descriptor)) {
|
||||
for ((receiverValue, callType) in receiverValues) {
|
||||
result.addAll(descriptor.substituteExtensionIfCallable(receiverValue, callType, bindingContext, dataFlowInfo))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
extensions.map { resolutionFacade.resolveToDescriptor(it) as CallableDescriptor }
|
||||
|
||||
for (declaration in declarations) {
|
||||
if (declaration.getContainingJetFile().isCompiled()) {
|
||||
//TODO: it's temporary while resolveToDescriptor does not work for compiled declarations
|
||||
for (descriptor in analyzeImportReference(declaration.getFqName()!!)) {
|
||||
if (descriptor is CallableDescriptor && descriptor.getExtensionReceiverParameter() != null) {
|
||||
processDescriptor(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
processDescriptor(resolutionFacade.resolveToDescriptor(declaration) as CallableDescriptor)
|
||||
}
|
||||
}
|
||||
return descriptors.sequence()
|
||||
.filter(visibilityFilter)
|
||||
.flatMap { it.substituteExtensionIfCallable(receiverValue, callType, bindingContext, dataFlowInfo).sequence() }
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
|
||||
|
||||
+4
-1
@@ -1,6 +1,6 @@
|
||||
package second
|
||||
|
||||
fun String.helloFun() {
|
||||
fun String?.helloFun() {
|
||||
}
|
||||
|
||||
fun String.helloWithParams(i : Int) : String {
|
||||
@@ -10,5 +10,8 @@ fun String.helloWithParams(i : Int) : String {
|
||||
fun String.helloFunPreventAutoInsert() {
|
||||
}
|
||||
|
||||
fun <T: CharSequence> T.helloFunGeneric() {
|
||||
}
|
||||
|
||||
fun Int.helloFake() {
|
||||
}
|
||||
+2
-1
@@ -8,5 +8,6 @@ fun firstFun() {
|
||||
// EXIST: helloFun
|
||||
// EXIST: helloFunPreventAutoInsert
|
||||
// EXIST: helloWithParams
|
||||
// EXIST: helloFunGeneric
|
||||
// ABSENT: helloFake
|
||||
// NUMBER: 3
|
||||
// NUMBER: 4
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package second
|
||||
|
||||
fun (() -> Unit)?.helloFun1() {
|
||||
}
|
||||
|
||||
fun Function0<Unit>.helloFun2() {
|
||||
}
|
||||
|
||||
fun ExtensionFunction0<String, Unit>.helloFun3() {
|
||||
}
|
||||
|
||||
fun Function1<String, Unit>.helloFun4() {
|
||||
}
|
||||
|
||||
fun Any.helloAny() {
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package first
|
||||
|
||||
fun firstFun(p: () -> Unit) {
|
||||
p.hello<caret>
|
||||
}
|
||||
|
||||
// EXIST: helloFun1
|
||||
// EXIST: helloFun2
|
||||
// EXIST: helloAny
|
||||
// ABSENT: helloFun3
|
||||
// ABSENT: helloFun4
|
||||
// NUMBER: 3
|
||||
+6
-1
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.completion;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.InnerTestClasses;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.JetTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
@@ -144,6 +143,12 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NotImportedExtensionFunction2")
|
||||
public void testNotImportedExtensionFunction2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/multifile/NotImportedExtensionFunction2/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NotImportedExtensionProperty")
|
||||
public void testNotImportedExtensionProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/multifile/NotImportedExtensionProperty/");
|
||||
|
||||
Reference in New Issue
Block a user