Completion: bold immediate members for extensions too
This commit is contained in:
@@ -52,49 +52,44 @@ public object TipsManager{
|
|||||||
kindFilter: DescriptorKindFilter,
|
kindFilter: DescriptorKindFilter,
|
||||||
nameFilter: (Name) -> Boolean
|
nameFilter: (Name) -> Boolean
|
||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
val receiverExpression = expression.getReceiverExpression()
|
|
||||||
val parent = expression.getParent()
|
val parent = expression.getParent()
|
||||||
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
|
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
|
||||||
|
|
||||||
if (receiverExpression != null) {
|
|
||||||
val inPositionForCompletionWithReceiver = parent is JetCallExpression
|
|
||||||
|| parent is JetQualifiedExpression
|
|
||||||
|| parent is JetBinaryExpression
|
|
||||||
if (inPositionForCompletionWithReceiver) {
|
|
||||||
val isInfixCall = parent is JetBinaryExpression
|
|
||||||
fun filterIfInfix(descriptor: DeclarationDescriptor)
|
|
||||||
= if (isInfixCall) descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size == 1 else true
|
|
||||||
|
|
||||||
// Process as call expression
|
|
||||||
val descriptors = HashSet<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
|
||||||
if (qualifier != null) {
|
|
||||||
// It's impossible to add extension function for package or class (if it's class object, expression type is not null)
|
|
||||||
qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors, ::filterIfInfix)
|
|
||||||
}
|
|
||||||
|
|
||||||
val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression]
|
|
||||||
if (expressionType != null && !expressionType.isError()) {
|
|
||||||
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
|
||||||
val dataFlowInfo = context.getDataFlowInfo(expression)
|
|
||||||
|
|
||||||
val mask = kindFilter.withoutKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK).exclude(DescriptorKindExclude.Extensions)
|
|
||||||
for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) {
|
|
||||||
variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors, ::filterIfInfix)
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptors.addCallableExtensions(resolutionScope, receiverValue, context, dataFlowInfo, isInfixCall, kindFilter, nameFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return descriptors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent is JetImportDirective || parent is JetPackageDirective) {
|
if (parent is JetImportDirective || parent is JetPackageDirective) {
|
||||||
val restrictedFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.PACKAGES_MASK) ?: return listOf()
|
val restrictedFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.PACKAGES_MASK) ?: return listOf()
|
||||||
return resolutionScope.getDescriptorsFiltered(restrictedFilter, nameFilter)
|
return resolutionScope.getDescriptorsFiltered(restrictedFilter, nameFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val receiverExpression = getReferenceVariantsReceiver(expression)
|
||||||
|
if (receiverExpression != null) {
|
||||||
|
val isInfixCall = parent is JetBinaryExpression
|
||||||
|
fun filterIfInfix(descriptor: DeclarationDescriptor)
|
||||||
|
= if (isInfixCall) descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size == 1 else true
|
||||||
|
|
||||||
|
// Process as call expression
|
||||||
|
val descriptors = HashSet<DeclarationDescriptor>()
|
||||||
|
|
||||||
|
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
||||||
|
if (qualifier != null) {
|
||||||
|
// It's impossible to add extension function for package or class (if it's class object, expression type is not null)
|
||||||
|
qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors, ::filterIfInfix)
|
||||||
|
}
|
||||||
|
|
||||||
|
val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression]
|
||||||
|
if (expressionType != null && !expressionType.isError()) {
|
||||||
|
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
||||||
|
val dataFlowInfo = context.getDataFlowInfo(expression)
|
||||||
|
|
||||||
|
val mask = kindFilter.withoutKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK).exclude(DescriptorKindExclude.Extensions)
|
||||||
|
for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) {
|
||||||
|
variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors, ::filterIfInfix)
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptors.addCallableExtensions(resolutionScope, receiverValue, context, dataFlowInfo, isInfixCall, kindFilter, nameFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptors
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
val descriptorsSet = HashSet<DeclarationDescriptor>()
|
val descriptorsSet = HashSet<DeclarationDescriptor>()
|
||||||
|
|
||||||
@@ -117,6 +112,29 @@ public object TipsManager{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun getReferenceVariantsReceivers(expression: JetSimpleNameExpression, context: BindingContext): Collection<ReceiverValue> {
|
||||||
|
val receiverExpression = getReferenceVariantsReceiver(expression)
|
||||||
|
if (receiverExpression != null) {
|
||||||
|
val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression] ?: return listOf()
|
||||||
|
return listOf(ExpressionReceiver(receiverExpression, expressionType))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
|
||||||
|
return resolutionScope.getImplicitReceiversHierarchy().map { it.getValue() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getReferenceVariantsReceiver(expression: JetSimpleNameExpression): JetExpression? {
|
||||||
|
val parent = expression.getParent()
|
||||||
|
val inPositionForCompletionWithReceiver = parent is JetCallExpression
|
||||||
|
|| parent is JetQualifiedExpression
|
||||||
|
|| parent is JetBinaryExpression
|
||||||
|
return if (inPositionForCompletionWithReceiver)
|
||||||
|
expression.getReceiverExpression()
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
private fun MutableCollection<DeclarationDescriptor>.addCallableExtensions(
|
private fun MutableCollection<DeclarationDescriptor>.addCallableExtensions(
|
||||||
resolutionScope: JetScope,
|
resolutionScope: JetScope,
|
||||||
receiver: ReceiverValue,
|
receiver: ReceiverValue,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class AllClassesCompletion(val parameters: CompletionParameters,
|
|||||||
else -> ClassKind.CLASS
|
else -> ClassKind.CLASS
|
||||||
}
|
}
|
||||||
if (kindFilter(kind)) {
|
if (kindFilter(kind)) {
|
||||||
collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass))
|
collector.addElementWithAutoInsertionSuppressed(LookupElementFactory.DEFAULT.createLookupElementForJavaClass(psiClass))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
|
||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptorKindExclude
|
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptorKindExclude
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils
|
||||||
|
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
|
||||||
|
|
||||||
class CompletionSessionConfiguration(
|
class CompletionSessionConfiguration(
|
||||||
val completeNonImportedDeclarations: Boolean,
|
val completeNonImportedDeclarations: Boolean,
|
||||||
@@ -62,7 +63,22 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
|
|||||||
|
|
||||||
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
|
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
|
||||||
|
|
||||||
protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolveSession)
|
protected val boldImmediateLookupElementFactory: LookupElementFactory = run {
|
||||||
|
if (jetReference != null) {
|
||||||
|
val expression = jetReference.expression
|
||||||
|
val receivers = TipsManager.getReferenceVariantsReceivers(expression, bindingContext!!)
|
||||||
|
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
|
||||||
|
val receiverTypes = receivers.flatMap {
|
||||||
|
SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, dataFlowInfo)
|
||||||
|
}
|
||||||
|
BoldImmediateLookupElementFactory(receiverTypes)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LookupElementFactory.DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolveSession, boldImmediateLookupElementFactory)
|
||||||
|
|
||||||
protected val project: Project = position.getProject()
|
protected val project: Project = position.getProject()
|
||||||
|
|
||||||
@@ -209,7 +225,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
|
|
||||||
override fun doComplete() {
|
override fun doComplete() {
|
||||||
if (jetReference != null) {
|
if (jetReference != null) {
|
||||||
val completion = SmartCompletion(jetReference.expression, resolveSession, { isVisibleDescriptor(it) }, parameters.getOriginalFile() as JetFile)
|
val completion = SmartCompletion(jetReference.expression, resolveSession, { isVisibleDescriptor(it) }, parameters.getOriginalFile() as JetFile, boldImmediateLookupElementFactory)
|
||||||
val result = completion.execute()
|
val result = completion.execute()
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
collector.addElements(result.additionalItems)
|
collector.addElements(result.additionalItems)
|
||||||
|
|||||||
+60
-35
@@ -33,18 +33,17 @@ import com.intellij.psi.PsiClass
|
|||||||
import org.jetbrains.jet.asJava.KotlinLightClass
|
import org.jetbrains.jet.asJava.KotlinLightClass
|
||||||
import org.jetbrains.jet.lang.resolve.java.JavaResolverUtils
|
import org.jetbrains.jet.lang.resolve.java.JavaResolverUtils
|
||||||
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement
|
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||||
|
import org.jetbrains.jet.lang.types.JetType
|
||||||
|
|
||||||
public object KotlinLookupElementFactory {
|
public open class LookupElementFactory protected() {
|
||||||
public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, boldImmediateMembers: Boolean): LookupElement {
|
public open fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement {
|
||||||
val _descriptor = if (descriptor is CallableMemberDescriptor)
|
val _descriptor = if (descriptor is CallableMemberDescriptor)
|
||||||
DescriptorUtils.unwrapFakeOverride(descriptor)
|
DescriptorUtils.unwrapFakeOverride(descriptor)
|
||||||
else
|
else
|
||||||
descriptor
|
descriptor
|
||||||
val bold = boldImmediateMembers
|
return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor))
|
||||||
&& descriptor is CallableMemberDescriptor
|
|
||||||
&& descriptor.getContainingDeclaration() is ClassifierDescriptor
|
|
||||||
&& descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION
|
|
||||||
return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor), bold)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createLookupElementForJavaClass(psiClass: PsiClass): LookupElement {
|
public fun createLookupElementForJavaClass(psiClass: PsiClass): LookupElement {
|
||||||
@@ -54,8 +53,7 @@ public object KotlinLookupElementFactory {
|
|||||||
private fun createLookupElement(
|
private fun createLookupElement(
|
||||||
analyzer: KotlinCodeAnalyzer,
|
analyzer: KotlinCodeAnalyzer,
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptor,
|
||||||
declaration: PsiElement?,
|
declaration: PsiElement?
|
||||||
bold: Boolean
|
|
||||||
): LookupElement {
|
): LookupElement {
|
||||||
if (descriptor is ClassifierDescriptor &&
|
if (descriptor is ClassifierDescriptor &&
|
||||||
declaration is PsiClass &&
|
declaration is PsiClass &&
|
||||||
@@ -104,10 +102,6 @@ public object KotlinLookupElementFactory {
|
|||||||
element = element.withStrikeoutness(true)
|
element = element.withStrikeoutness(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bold) {
|
|
||||||
element = element.withBoldness(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val insertHandler = getDefaultInsertHandler(descriptor)
|
val insertHandler = getDefaultInsertHandler(descriptor)
|
||||||
element = element.withInsertHandler(insertHandler)
|
element = element.withInsertHandler(insertHandler)
|
||||||
|
|
||||||
@@ -118,34 +112,65 @@ public object KotlinLookupElementFactory {
|
|||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
|
class object {
|
||||||
return when (descriptor) {
|
public val DEFAULT: LookupElementFactory = LookupElementFactory()
|
||||||
is FunctionDescriptor -> {
|
|
||||||
val parameters = descriptor.getValueParameters()
|
|
||||||
when (parameters.size) {
|
|
||||||
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
|
|
||||||
|
|
||||||
1 -> {
|
public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
|
||||||
val parameterType = parameters.single().getType()
|
return when (descriptor) {
|
||||||
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
|
is FunctionDescriptor -> {
|
||||||
val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
val parameters = descriptor.getValueParameters()
|
||||||
if (parameterCount <= 1) {
|
when (parameters.size) {
|
||||||
// otherwise additional item with lambda template is to be added
|
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
|
||||||
return KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false))
|
|
||||||
|
1 -> {
|
||||||
|
val parameterType = parameters.single().getType()
|
||||||
|
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
|
||||||
|
val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
||||||
|
if (parameterCount <= 1) {
|
||||||
|
// otherwise additional item with lambda template is to be added
|
||||||
|
return KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
||||||
}
|
}
|
||||||
KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
|
||||||
|
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is PropertyDescriptor -> KotlinPropertyInsertHandler
|
||||||
|
|
||||||
|
is ClassDescriptor -> KotlinClassInsertHandler
|
||||||
|
|
||||||
|
else -> BaseDeclarationInsertHandler()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
is PropertyDescriptor -> KotlinPropertyInsertHandler
|
}
|
||||||
|
}
|
||||||
is ClassDescriptor -> KotlinClassInsertHandler
|
|
||||||
|
public class BoldImmediateLookupElementFactory(private val receiverTypes: Collection<JetType>) : LookupElementFactory() {
|
||||||
else -> BaseDeclarationInsertHandler()
|
override fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement {
|
||||||
|
val element = super.createLookupElement(analyzer, descriptor)
|
||||||
|
|
||||||
|
if (descriptor !is CallableMemberDescriptor) return element
|
||||||
|
val receiverParameter = descriptor.getExtensionReceiverParameter()
|
||||||
|
val bold = if (receiverParameter != null) {
|
||||||
|
receiverTypes.any { it == receiverParameter.getType() }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
descriptor.getContainingDeclaration() is ClassifierDescriptor && descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (bold) {
|
||||||
|
object : LookupElementDecorator<LookupElement>(element) {
|
||||||
|
override fun renderElement(presentation: LookupElementPresentation) {
|
||||||
|
super.renderElement(presentation)
|
||||||
|
presentation.setItemTextBold(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
element
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,8 @@ import com.intellij.codeInsight.completion.CompletionParameters
|
|||||||
class LookupElementsCollector(
|
class LookupElementsCollector(
|
||||||
private val prefixMatcher: PrefixMatcher,
|
private val prefixMatcher: PrefixMatcher,
|
||||||
private val completionParameters: CompletionParameters,
|
private val completionParameters: CompletionParameters,
|
||||||
private val resolveSession: ResolveSessionForBodies
|
private val resolveSession: ResolveSessionForBodies,
|
||||||
|
private val boldImmediateLookupElementFactory: LookupElementFactory
|
||||||
) {
|
) {
|
||||||
private val elements = ArrayList<LookupElement>()
|
private val elements = ArrayList<LookupElement>()
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ class LookupElementsCollector(
|
|||||||
|
|
||||||
public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean) {
|
public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean) {
|
||||||
run {
|
run {
|
||||||
val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, true)
|
val lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolveSession, descriptor)
|
||||||
if (suppressAutoInsertion) {
|
if (suppressAutoInsertion) {
|
||||||
addElementWithAutoInsertionSuppressed(lookupElement)
|
addElementWithAutoInsertionSuppressed(lookupElement)
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ class LookupElementsCollector(
|
|||||||
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
|
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
|
||||||
val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
||||||
if (parameterCount > 1) {
|
if (parameterCount > 1) {
|
||||||
val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, true)
|
val lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolveSession, descriptor)
|
||||||
addElement(object : LookupElementDecorator<LookupElement>(lookupElement) {
|
addElement(object : LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
override fun renderElement(presentation: LookupElementPresentation) {
|
override fun renderElement(presentation: LookupElementPresentation) {
|
||||||
super.renderElement(presentation)
|
super.renderElement(presentation)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ object PackageDirectiveCompletion {
|
|||||||
|
|
||||||
val variants = TipsManager.getPackageReferenceVariants(ref.expression, bindingContext, prefixMatcher.asNameFilter())
|
val variants = TipsManager.getPackageReferenceVariants(ref.expression, bindingContext, prefixMatcher.asNameFilter())
|
||||||
for (variant in variants) {
|
for (variant in variants) {
|
||||||
val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, variant, false)
|
val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(resolveSession, variant)
|
||||||
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
||||||
result.addElement(lookupElement)
|
result.addElement(lookupElement)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
|||||||
import org.jetbrains.jet.renderer.DescriptorRenderer
|
import org.jetbrains.jet.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
|
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
|
||||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor
|
|
||||||
|
|
||||||
class SmartCompletion(val expression: JetSimpleNameExpression,
|
class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||||
val resolveSession: ResolveSessionForBodies,
|
val resolveSession: ResolveSessionForBodies,
|
||||||
val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
||||||
val originalFile: JetFile) {
|
val originalFile: JetFile,
|
||||||
|
val boldImmediateLookupElementFactory: LookupElementFactory) {
|
||||||
private val bindingContext = resolveSession.resolveToElement(expression)
|
private val bindingContext = resolveSession.resolveToElement(expression)
|
||||||
private val project = expression.getProject()
|
private val project = expression.getProject()
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
|||||||
else -> ExpectedInfoClassification.NOT_MATCHES
|
else -> ExpectedInfoClassification.NOT_MATCHES
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.addLookupElements(expectedInfos, classifier, { createLookupElement(descriptor, resolveSession, bindingContext, true) })
|
result.addLookupElements(expectedInfos, classifier, { boldImmediateLookupElementFactory.createLookupElement(descriptor, resolveSession, bindingContext) })
|
||||||
|
|
||||||
if (receiver == null) {
|
if (receiver == null) {
|
||||||
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
|
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
|
||||||
@@ -237,7 +237,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
|||||||
val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.type) }
|
val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.type) }
|
||||||
if (matchedExpectedInfos.isEmpty()) return null
|
if (matchedExpectedInfos.isEmpty()) return null
|
||||||
|
|
||||||
var lookupElement = createLookupElement(descriptor, resolveSession, bindingContext, true)
|
var lookupElement = boldImmediateLookupElementFactory.createLookupElement(descriptor, resolveSession, bindingContext)
|
||||||
val text = "::" + (if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName())
|
val text = "::" + (if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName())
|
||||||
lookupElement = object: LookupElementDecorator<LookupElement>(lookupElement) {
|
lookupElement = object: LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
override fun getLookupString() = text
|
override fun getLookupString() = text
|
||||||
@@ -296,7 +296,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
|||||||
if (jetType.isError()) return null
|
if (jetType.isError()) return null
|
||||||
val classifier = jetType.getConstructor().getDeclarationDescriptor() ?: return null
|
val classifier = jetType.getConstructor().getDeclarationDescriptor() ?: return null
|
||||||
|
|
||||||
val lookupElement = createLookupElement(classifier, resolveSession, bindingContext, false)
|
val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolveSession, bindingContext)
|
||||||
val lookupString = lookupElement.getLookupString()
|
val lookupString = lookupElement.getLookupString()
|
||||||
|
|
||||||
val typeArgs = jetType.getArguments()
|
val typeArgs = jetType.getArguments()
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.jet.plugin.util.makeNotNullable
|
|||||||
import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode
|
import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode
|
||||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.isExtension
|
import org.jetbrains.jet.lang.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.jet.plugin.completion.LookupElementFactory
|
||||||
|
|
||||||
// adds java static members, enum members and members from class object
|
// adds java static members, enum members and members from class object
|
||||||
class StaticMembers(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) {
|
class StaticMembers(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) {
|
||||||
@@ -105,7 +106,7 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createLookupElement(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): LookupElement {
|
private fun createLookupElement(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): LookupElement {
|
||||||
val lookupElement = createLookupElement(memberDescriptor, resolveSession, bindingContext, false)
|
val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(memberDescriptor, resolveSession, bindingContext)
|
||||||
val qualifierPresentation = classDescriptor.getName().asString()
|
val qualifierPresentation = classDescriptor.getName().asString()
|
||||||
val qualifierText = qualifiedNameForSourceCode(classDescriptor)
|
val qualifierText = qualifiedNameForSourceCode(classDescriptor)
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
|||||||
}
|
}
|
||||||
if (allConstructors.isNotEmpty() && visibleConstructors.isEmpty()) return
|
if (allConstructors.isNotEmpty() && visibleConstructors.isEmpty()) return
|
||||||
|
|
||||||
var lookupElement = createLookupElement(classifier, resolveSession, bindingContext, false)
|
var lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolveSession, bindingContext)
|
||||||
|
|
||||||
var lookupString = lookupElement.getLookupString()
|
var lookupString = lookupElement.getLookupString()
|
||||||
var allLookupStrings = setOf(lookupString)
|
var allLookupStrings = setOf(lookupString)
|
||||||
@@ -108,7 +108,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
|||||||
|
|
||||||
val baseInsertHandler = when (visibleConstructors.size) {
|
val baseInsertHandler = when (visibleConstructors.size) {
|
||||||
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
|
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
|
||||||
1 -> KotlinLookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler
|
1 -> LookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler
|
||||||
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
|||||||
val samConstructor = scope.getFunctions(`class`.getName())
|
val samConstructor = scope.getFunctions(`class`.getName())
|
||||||
.filterIsInstance(javaClass<SamConstructorDescriptor>())
|
.filterIsInstance(javaClass<SamConstructorDescriptor>())
|
||||||
.singleOrNull() ?: return
|
.singleOrNull() ?: return
|
||||||
val lookupElement = createLookupElement(samConstructor, resolveSession, bindingContext, false)
|
val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(samConstructor, resolveSession, bindingContext)
|
||||||
.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION)
|
.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION)
|
||||||
.addTail(tail)
|
.addTail(tail)
|
||||||
collection.add(lookupElement)
|
collection.add(lookupElement)
|
||||||
|
|||||||
@@ -186,13 +186,12 @@ fun functionType(function: FunctionDescriptor): JetType? {
|
|||||||
function.getReturnType() ?: return null)
|
function.getReturnType() ?: return null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createLookupElement(
|
fun LookupElementFactory.createLookupElement(
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptor,
|
||||||
resolveSession: ResolveSessionForBodies,
|
resolveSession: ResolveSessionForBodies,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext
|
||||||
boldImmediateMembers: Boolean
|
|
||||||
): LookupElement {
|
): LookupElement {
|
||||||
var element = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, boldImmediateMembers)
|
var element = createLookupElement(resolveSession, descriptor)
|
||||||
|
|
||||||
if (descriptor is FunctionDescriptor && descriptor.getValueParameters().isNotEmpty()) {
|
if (descriptor is FunctionDescriptor && descriptor.getValueParameters().isNotEmpty()) {
|
||||||
element = element.keepOldArgumentListOnTab()
|
element = element.keepOldArgumentListOnTab()
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fun String.extFunForString(){}
|
||||||
|
fun Any.extFunForAny(){}
|
||||||
|
fun String?.extFunForStringNullable(){}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun Any.memberExtFunForAny(){}
|
||||||
|
fun String?.memberExtFunForStringNullable(){}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
"".<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { itemText: "extFunForString", attributes: "bold" }
|
||||||
|
// EXIST: { itemText: "extFunForAny", attributes: "" }
|
||||||
|
// EXIST: { itemText: "extFunForStringNullable", attributes: "" }
|
||||||
|
// EXIST: { itemText: "memberExtFunForAny", attributes: "" }
|
||||||
|
// EXIST: { itemText: "memberExtFunForStringNullable", attributes: "" }
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fun String.extFunForString(){}
|
||||||
|
fun Any.extFunForAny(){}
|
||||||
|
fun String?.extFunForStringNullable(){}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun foo(s: String?) {
|
||||||
|
if (s != null) {
|
||||||
|
s.<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { itemText: "extFunForString", attributes: "bold" }
|
||||||
|
// EXIST: { itemText: "extFunForAny", attributes: "" }
|
||||||
|
// EXIST: { itemText: "extFunForStringNullable", attributes: "" }
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun C.extFunForC(){}
|
||||||
|
fun D.extFunForD(){}
|
||||||
|
fun Any.extFunForAny(){}
|
||||||
|
|
||||||
|
open class C {
|
||||||
|
fun foo() {
|
||||||
|
if (this is D) {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class D : C
|
||||||
|
|
||||||
|
// EXIST: { itemText: "extFunForD", attributes: "bold" }
|
||||||
|
// EXIST: { itemText: "extFunForC", attributes: "" }
|
||||||
|
// EXIST: { itemText: "extFunForAny", attributes: "" }
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun C.extFunForC(){}
|
||||||
|
fun T.extFunForT(){}
|
||||||
|
fun Any.extFunForAny(){}
|
||||||
|
|
||||||
|
open class C {
|
||||||
|
fun foo() {
|
||||||
|
if (this is T) {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait T
|
||||||
|
|
||||||
|
// EXIST: { itemText: "extFunForT", attributes: "bold" }
|
||||||
|
// EXIST: { itemText: "extFunForC", attributes: "bold" }
|
||||||
|
// EXIST: { itemText: "extFunForAny", attributes: "" }
|
||||||
@@ -304,6 +304,30 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers1.kt")
|
||||||
|
public void testImmediateExtensionMembers1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers2.kt")
|
||||||
|
public void testImmediateExtensionMembers2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers3.kt")
|
||||||
|
public void testImmediateExtensionMembers3() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers4.kt")
|
||||||
|
public void testImmediateExtensionMembers4() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ImmediateMembers1.kt")
|
@TestMetadata("ImmediateMembers1.kt")
|
||||||
public void testImmediateMembers1() throws Exception {
|
public void testImmediateMembers1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt");
|
||||||
|
|||||||
@@ -304,6 +304,30 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers1.kt")
|
||||||
|
public void testImmediateExtensionMembers1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers2.kt")
|
||||||
|
public void testImmediateExtensionMembers2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers3.kt")
|
||||||
|
public void testImmediateExtensionMembers3() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImmediateExtensionMembers4.kt")
|
||||||
|
public void testImmediateExtensionMembers4() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ImmediateMembers1.kt")
|
@TestMetadata("ImmediateMembers1.kt")
|
||||||
public void testImmediateMembers1() throws Exception {
|
public void testImmediateMembers1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user