Smart completion: generic functions are correctly included into the list
#KT-6375 Fixed
This commit is contained in:
+1
@@ -42,6 +42,7 @@ public class LocalVariableDescriptor extends VariableDescriptorImpl {
|
||||
@NotNull
|
||||
@Override
|
||||
public LocalVariableDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
|
||||
if (substitutor.isEmpty()) return this;
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -108,6 +108,7 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
@NotNull
|
||||
@Override
|
||||
public ValueParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
|
||||
if (substitutor.isEmpty()) return this;
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.Flexibility
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor
|
||||
import org.jetbrains.jet.utils.toReadOnlyList
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
|
||||
fun JetType.getContainedTypeParameters(): Collection<TypeParameterDescriptor> {
|
||||
val declarationDescriptor = getConstructor().getDeclarationDescriptor()
|
||||
@@ -59,3 +60,6 @@ public fun JetType.getContainedAndCapturedTypeParameterConstructors(): Collectio
|
||||
return typeParameters.map { it.getTypeConstructor() }.toReadOnlyList()
|
||||
}
|
||||
|
||||
public fun JetType.isSubtypeOf(superType: JetType): Boolean = JetTypeChecker.DEFAULT.isSubtypeOf(this, superType)
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||
import com.intellij.codeInsight.completion.InsertionContext
|
||||
import org.jetbrains.jet.plugin.completion.handlers.CastReceiverInsertHandler
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
|
||||
enum class ItemPriority {
|
||||
MULTIPLE_ARGUMENTS_ITEM
|
||||
@@ -113,3 +114,23 @@ enum class CallableWeight {
|
||||
}
|
||||
|
||||
val CALLABLE_WEIGHT_KEY = Key<CallableWeight>("CALLABLE_WEIGHT_KEY")
|
||||
|
||||
fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): Boolean {
|
||||
if (descriptor1 == descriptor2) return true
|
||||
if (descriptor1 == null || descriptor2 == null) return false
|
||||
if (descriptor1.getOriginal() != descriptor2.getOriginal()) return false
|
||||
if (descriptor1 !is CallableDescriptor) return true
|
||||
descriptor2 as CallableDescriptor
|
||||
|
||||
// optimization:
|
||||
if (descriptor1 == descriptor1.getOriginal() && descriptor2 == descriptor2.getOriginal()) return true
|
||||
|
||||
if (descriptor1.getReturnType() != descriptor2.getReturnType()) return false
|
||||
val parameters1 = descriptor1.getValueParameters()
|
||||
val parameters2 = descriptor2.getValueParameters()
|
||||
if (parameters1.size() != parameters2.size()) return false
|
||||
for (i in parameters1.indices) {
|
||||
if (parameters1[i].getType() != parameters2[i].getType()) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
|
||||
/**
|
||||
* Stores information about resolved descriptor and position of that descriptor.
|
||||
@@ -50,22 +49,7 @@ public class DeclarationDescriptorLookupObject(
|
||||
return false
|
||||
}
|
||||
|
||||
if (lookupObject.descriptor.getOriginal() != descriptor.getOriginal()) return false
|
||||
if (descriptor !is CallableDescriptor) return true
|
||||
// optimization:
|
||||
if (descriptor == (descriptor as CallableDescriptor).getOriginal() && lookupObject.descriptor == lookupObject.descriptor.getOriginal()) return true
|
||||
return substitutionsEqual(descriptor as CallableDescriptor, lookupObject.descriptor as CallableDescriptor)
|
||||
}
|
||||
|
||||
private fun substitutionsEqual(callable1: CallableDescriptor, callable2: CallableDescriptor): Boolean {
|
||||
if (callable1.getReturnType() != callable2.getReturnType()) return false
|
||||
val parameters1 = callable1.getValueParameters()
|
||||
val parameters2 = callable2.getValueParameters()
|
||||
if (parameters1.size() != parameters2.size()) return false
|
||||
for (i in parameters1.indices) {
|
||||
if (parameters1[i].getType() != parameters2[i].getType()) return false
|
||||
}
|
||||
return true
|
||||
return descriptorsEqualWithSubstitution(descriptor, lookupObject.descriptor)
|
||||
}
|
||||
|
||||
class object {
|
||||
|
||||
@@ -40,7 +40,6 @@ import org.jetbrains.jet.lexer.JetTokens
|
||||
import org.jetbrains.jet.lang.psi.JetIfExpression
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.psi.JetContainerNode
|
||||
import org.jetbrains.jet.plugin.completion.smart.isSubtypeOf
|
||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.noErrorsInValueArguments
|
||||
import org.jetbrains.jet.lang.descriptors.Visibilities
|
||||
import org.jetbrains.jet.lang.psi.JetBlockExpression
|
||||
@@ -68,6 +67,7 @@ import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.jet.lang.types.typeUtil.isSubtypeOf
|
||||
|
||||
enum class Tail {
|
||||
COMMA
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.plugin.completion.smart
|
||||
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.utils.addIfNotNull
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl
|
||||
import java.util.LinkedHashMap
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
import org.jetbrains.jet.plugin.util.makeNullable
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
import org.jetbrains.jet.lang.types.typeUtil.isSubtypeOf
|
||||
|
||||
fun CallableDescriptor.fuzzyReturnType(): FuzzyType? {
|
||||
val returnType = getReturnType() ?: return null
|
||||
return FuzzyType(returnType, getTypeParameters())
|
||||
}
|
||||
|
||||
//TODO: replace code in extensionsUtils.kt with use of FuzzyType
|
||||
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType? {
|
||||
val receiverParameter = getExtensionReceiverParameter()
|
||||
return if (receiverParameter != null) FuzzyType(receiverParameter.getType(), getTypeParameters()) else null
|
||||
}
|
||||
|
||||
fun FuzzyType.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
|
||||
fun FuzzyType.makeNullable() = FuzzyType(type.makeNullable(), freeParameters)
|
||||
fun FuzzyType.isNullable() = type.isNullable()
|
||||
|
||||
class FuzzyType(
|
||||
val type: JetType,
|
||||
val freeParameters: Collection<TypeParameterDescriptor>
|
||||
) {
|
||||
private val usedTypeParameters: HashSet<TypeParameterDescriptor>? = if (freeParameters.isNotEmpty()) HashSet() else null
|
||||
|
||||
;{
|
||||
usedTypeParameters?.addUsedTypeParameters(type)
|
||||
}
|
||||
|
||||
private fun MutableSet<TypeParameterDescriptor>.addUsedTypeParameters(type: JetType) {
|
||||
addIfNotNull(type.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor)
|
||||
|
||||
for (argument in type.getArguments()) {
|
||||
addUsedTypeParameters(argument.getType())
|
||||
}
|
||||
}
|
||||
|
||||
public fun matchedSubstitutor(expectedType: JetType): TypeSubstitutor? {
|
||||
if (type.isError()) return null
|
||||
if (usedTypeParameters == null || usedTypeParameters.isEmpty()) {
|
||||
return if (type.isSubtypeOf(expectedType)) TypeSubstitutor.EMPTY else null
|
||||
}
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
val typeVariables = LinkedHashMap<TypeParameterDescriptor, Variance>()
|
||||
for (typeParameter in freeParameters) {
|
||||
if (typeParameter in usedTypeParameters) {
|
||||
typeVariables[typeParameter] = Variance.INVARIANT
|
||||
}
|
||||
}
|
||||
constraintSystem.registerTypeVariables(typeVariables)
|
||||
|
||||
constraintSystem.addSubtypeConstraint(type, expectedType, ConstraintPosition.SPECIAL/*TODO?*/)
|
||||
if (constraintSystem.getStatus().isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, true)) {
|
||||
val substitutor = constraintSystem.getResultingSubstitutor()
|
||||
val substitutedType = substitutor.substitute(type, Variance.INVARIANT/*TODO?*/)
|
||||
return if (substitutedType.isSubtypeOf(expectedType)) substitutor else null
|
||||
}
|
||||
else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.psi.*
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||
import com.intellij.codeInsight.completion.InsertionContext
|
||||
import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
|
||||
object KeywordValues {
|
||||
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>, expressionWithType: JetExpression) {
|
||||
@@ -48,14 +49,15 @@ object KeywordValues {
|
||||
|
||||
if (!skipTrueFalse) {
|
||||
val booleanInfoClassifier = { (info: ExpectedInfo) ->
|
||||
if (info.type == KotlinBuiltIns.getInstance().getBooleanType()) ExpectedInfoClassification.MATCHES else ExpectedInfoClassification.NOT_MATCHES
|
||||
if (info.type == KotlinBuiltIns.getInstance().getBooleanType()) ExpectedInfoClassification.matches(TypeSubstitutor.EMPTY) else ExpectedInfoClassification.notMatches
|
||||
}
|
||||
collection.addLookupElements(expectedInfos, booleanInfoClassifier, { LookupElementBuilder.create("true").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.TRUE) })
|
||||
collection.addLookupElements(expectedInfos, booleanInfoClassifier, { LookupElementBuilder.create("false").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.FALSE) })
|
||||
collection.addLookupElements(null, expectedInfos, booleanInfoClassifier, { LookupElementBuilder.create("true").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.TRUE) })
|
||||
collection.addLookupElements(null, expectedInfos, booleanInfoClassifier, { LookupElementBuilder.create("false").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.FALSE) })
|
||||
}
|
||||
|
||||
collection.addLookupElements(expectedInfos,
|
||||
{ info -> if (info.type.isNullable()) ExpectedInfoClassification.MATCHES else ExpectedInfoClassification.NOT_MATCHES },
|
||||
collection.addLookupElements(null,
|
||||
expectedInfos,
|
||||
{ info -> if (info.type.isNullable()) ExpectedInfoClassification.matches(TypeSubstitutor.EMPTY) else ExpectedInfoClassification.notMatches },
|
||||
{ LookupElementBuilder.create("null").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.NULL) })
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,10 @@ package org.jetbrains.jet.plugin.completion.smart
|
||||
import org.jetbrains.jet.plugin.completion.ExpectedInfo
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
import com.intellij.ui.LayeredIcon
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import org.jetbrains.jet.plugin.completion.Tail
|
||||
import org.jetbrains.jet.plugin.completion.ItemPriority
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
@@ -37,9 +34,11 @@ import java.util.ArrayList
|
||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.jet.plugin.completion.assignPriority
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
|
||||
class MultipleArgumentsItemProvider(val bindingContext: BindingContext,
|
||||
val typesWithAutoCasts: (DeclarationDescriptor) -> Iterable<JetType>) {
|
||||
val smartCastTypes: (VariableDescriptor) -> Collection<JetType>) {
|
||||
|
||||
public fun addToCollection(collection: MutableCollection<LookupElement>,
|
||||
expectedInfos: Collection<ExpectedInfo>,
|
||||
@@ -95,7 +94,7 @@ class MultipleArgumentsItemProvider(val bindingContext: BindingContext,
|
||||
val name = parameter.getName()
|
||||
//TODO: there can be more than one property with such name in scope and we should be able to select one (but we need API for this)
|
||||
val variable = scope.getLocalVariable(name) ?: scope.getProperties(name).singleOrNull() ?: return null
|
||||
return if (typesWithAutoCasts(variable).any { JetTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) })
|
||||
return if (smartCastTypes(variable).any { JetTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) })
|
||||
variable
|
||||
else
|
||||
null
|
||||
|
||||
@@ -28,13 +28,13 @@ import org.jetbrains.jet.plugin.completion.*
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
import org.jetbrains.jet.plugin.util.makeNullable
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.jet.plugin.caches.resolve.resolveToDescriptor
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.jet.lang.types.typeUtil.isSubtypeOf
|
||||
|
||||
trait InheritanceItemsSearcher {
|
||||
fun search(nameFilter: (String) -> Boolean, consumer: (LookupElement) -> Unit)
|
||||
@@ -115,30 +115,40 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||
else
|
||||
filteredExpectedInfos
|
||||
|
||||
val typesWithSmartCasts: (DeclarationDescriptor) -> Iterable<JetType> = TypesWithSmartCasts(bindingContext).calculate(expressionWithType, receiver)
|
||||
val smartCastTypes: (VariableDescriptor) -> Collection<JetType> = TypesWithSmartCasts(bindingContext).calculate(expressionWithType, receiver)
|
||||
|
||||
val itemsToSkip = calcItemsToSkip(expressionWithType)
|
||||
|
||||
val functionExpectedInfos = expectedInfos.filter { KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it.type) }
|
||||
|
||||
fun filterDeclaration(descriptor: DeclarationDescriptor): Collection<LookupElement> {
|
||||
if (descriptor in itemsToSkip) return listOf()
|
||||
|
||||
val result = ArrayList<LookupElement>()
|
||||
if (!itemsToSkip.contains(descriptor)) {
|
||||
val types = typesWithSmartCasts(descriptor)
|
||||
val nonNullTypes = types.map { it.makeNotNullable() }
|
||||
val classifier = { (expectedInfo: ExpectedInfo) ->
|
||||
when {
|
||||
types.any { it.isSubtypeOf(expectedInfo.type) } -> ExpectedInfoClassification.MATCHES
|
||||
nonNullTypes.any { it.isSubtypeOf(expectedInfo.type) } -> ExpectedInfoClassification.MAKE_NOT_NULLABLE
|
||||
else -> ExpectedInfoClassification.NOT_MATCHES
|
||||
val types = descriptor.fuzzyTypes(smartCastTypes)
|
||||
val classifier = { (expectedInfo: ExpectedInfo) ->
|
||||
val substitutor = types.stream().map { it.matchedSubstitutor(expectedInfo.type) }.firstOrNull()
|
||||
if (substitutor != null) {
|
||||
ExpectedInfoClassification.matches(substitutor)
|
||||
}
|
||||
else {
|
||||
val substitutor2 = types.stream().map { it.makeNotNullable().matchedSubstitutor(expectedInfo.type) }.firstOrNull()
|
||||
if (substitutor2 != null) {
|
||||
ExpectedInfoClassification.matchesIfNotNullable(substitutor2)
|
||||
}
|
||||
else {
|
||||
ExpectedInfoClassification.notMatches
|
||||
}
|
||||
}
|
||||
result.addLookupElements(expectedInfos, classifier, { lookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext, true) })
|
||||
|
||||
if (receiver == null) {
|
||||
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
|
||||
}
|
||||
}
|
||||
result.addLookupElements(descriptor, expectedInfos, classifier) { descriptor ->
|
||||
lookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext, true)
|
||||
}
|
||||
|
||||
if (receiver == null) {
|
||||
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -156,7 +166,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||
|
||||
KeywordValues.addToCollection(additionalItems, filteredExpectedInfos/* use filteredExpectedInfos to not include null after == */, expressionWithType)
|
||||
|
||||
MultipleArgumentsItemProvider(bindingContext, typesWithSmartCasts).addToCollection(additionalItems, expectedInfos, expression)
|
||||
MultipleArgumentsItemProvider(bindingContext, smartCastTypes).addToCollection(additionalItems, expectedInfos, expression)
|
||||
}
|
||||
|
||||
val inheritanceSearcher = if (inheritanceSearchers.isNotEmpty())
|
||||
@@ -170,6 +180,37 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||
return Result(::filterDeclaration, additionalItems, inheritanceSearcher)
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.fuzzyTypes(smartCastTypes: (VariableDescriptor) -> Collection<JetType>): Collection<FuzzyType> {
|
||||
if (this is CallableDescriptor) {
|
||||
var returnType = fuzzyReturnType() ?: return listOf()
|
||||
//TODO: maybe we should include them on the second press?
|
||||
if (shouldSkipDeclarationsOfType(returnType)) return listOf()
|
||||
|
||||
if (this is VariableDescriptor) {
|
||||
return smartCastTypes(this).map { FuzzyType(it, listOf()) }
|
||||
}
|
||||
else {
|
||||
return listOf(fuzzyReturnType()!!)
|
||||
}
|
||||
}
|
||||
else if (this is ClassDescriptor && getKind().isSingleton()) {
|
||||
return listOf(FuzzyType(getDefaultType(), listOf()))
|
||||
}
|
||||
else {
|
||||
return listOf()
|
||||
}
|
||||
}
|
||||
|
||||
// skip declarations of type Nothing or of generic parameter type which has no real bounds
|
||||
private fun shouldSkipDeclarationsOfType(type: FuzzyType): Boolean {
|
||||
if (KotlinBuiltIns.getInstance().isNothing(type.type)) return true
|
||||
if (type.freeParameters.isEmpty()) return false
|
||||
val typeParameter = type.type.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor ?: return false
|
||||
if (!type.freeParameters.contains(typeParameter)) return false
|
||||
return KotlinBuiltIns.getInstance().isAnyOrNullableAny(typeParameter.getUpperBoundsAsType())
|
||||
//TODO: check for class object constraint when there will be supported
|
||||
}
|
||||
|
||||
private fun calcExpectedInfos(expression: JetExpression): Collection<ExpectedInfo>? {
|
||||
// if our expression is initializer of implicitly typed variable - take type of variable from original file (+ the same for function)
|
||||
val declaration = implicitlyTypedDeclarationFromInitializer(expression)
|
||||
|
||||
@@ -28,12 +28,12 @@ import com.intellij.codeInsight.completion.InsertionContext
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.plugin.completion.ExpectedInfo
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode
|
||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.jet.plugin.completion.LookupElementFactory
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
|
||||
// adds java static members, enum members and members from class object
|
||||
class StaticMembers(
|
||||
@@ -68,24 +68,19 @@ class StaticMembers(
|
||||
|
||||
val classifier: (ExpectedInfo) -> ExpectedInfoClassification
|
||||
if (descriptor is CallableDescriptor) {
|
||||
val returnType = descriptor.getReturnType() ?: return
|
||||
classifier = {
|
||||
expectedInfo ->
|
||||
when {
|
||||
returnType.isSubtypeOf(expectedInfo.type) -> ExpectedInfoClassification.MATCHES
|
||||
returnType.isNullable() && returnType.makeNotNullable().isSubtypeOf(expectedInfo.type) -> ExpectedInfoClassification.MAKE_NOT_NULLABLE
|
||||
else -> ExpectedInfoClassification.NOT_MATCHES
|
||||
}
|
||||
}
|
||||
val returnType = descriptor.fuzzyReturnType() ?: return
|
||||
classifier = { expectedInfo -> returnType.classifyExpectedInfo(expectedInfo) }
|
||||
}
|
||||
else if (DescriptorUtils.isEnumEntry(descriptor) && !enumEntriesToSkip.contains(descriptor)) {
|
||||
classifier = { ExpectedInfoClassification.MATCHES } /* we do not need to check type of enum entry because it's taken from proper enum */
|
||||
classifier = { ExpectedInfoClassification.matches(TypeSubstitutor.EMPTY) } /* we do not need to check type of enum entry because it's taken from proper enum */
|
||||
}
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
collection.addLookupElements(expectedInfos, classifier, { createLookupElement(descriptor, classDescriptor) })
|
||||
collection.addLookupElements(descriptor, expectedInfos, classifier) {
|
||||
descriptor -> createLookupElement(descriptor, classDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
classDescriptor.getStaticScope().getAllDescriptors().forEach(::processMember)
|
||||
|
||||
@@ -28,27 +28,21 @@ import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.completion.ExpectedInfo
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
|
||||
class ThisItems(val bindingContext: BindingContext) {
|
||||
public fun addToCollection(collection: MutableCollection<LookupElement>, context: JetExpression, expectedInfos: Collection<ExpectedInfo>) {
|
||||
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, context]
|
||||
if (scope == null) return
|
||||
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return
|
||||
|
||||
val receivers: List<ReceiverParameterDescriptor> = scope.getImplicitReceiversHierarchy()
|
||||
for (i in 0..receivers.size - 1) {
|
||||
val receiver = receivers[i]
|
||||
val thisType = receiver.getType()
|
||||
val classifier = { (expectedInfo: ExpectedInfo) ->
|
||||
when {
|
||||
thisType.isSubtypeOf(expectedInfo.type) -> ExpectedInfoClassification.MATCHES
|
||||
thisType.isNullable() && thisType.makeNotNullable().isSubtypeOf(expectedInfo.type) -> ExpectedInfoClassification.MAKE_NOT_NULLABLE
|
||||
else -> ExpectedInfoClassification.NOT_MATCHES
|
||||
}
|
||||
}
|
||||
fun lookupElementFactory(): LookupElement? {
|
||||
val fuzzyType = FuzzyType(thisType, listOf())
|
||||
val classifier = { (expectedInfo: ExpectedInfo) -> fuzzyType.classifyExpectedInfo(expectedInfo) }
|
||||
fun createLookupElement(): LookupElement? {
|
||||
//TODO: use this code when KT-4258 fixed
|
||||
//val expressionText = if (i == 0) "this" else "this@" + (thisQualifierName(receiver, bindingContext) ?: return null)
|
||||
val qualifier = if (i == 0) null else (thisQualifierName(receiver) ?: return null)
|
||||
@@ -57,7 +51,7 @@ class ThisItems(val bindingContext: BindingContext) {
|
||||
.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(thisType))
|
||||
.assignSmartCompletionPriority(SmartCompletionItemPriority.THIS)
|
||||
}
|
||||
collection.addLookupElements(expectedInfos, classifier, ::lookupElementFactory)
|
||||
collection.addLookupElements(null, expectedInfos, classifier) { createLookupElement() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.jetbrains.jet.lang.resolve.resolveTopLevelClass
|
||||
import org.jetbrains.jet.lang.types.TypeProjectionImpl
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import org.jetbrains.jet.lang.types.typeUtil.isSubtypeOf
|
||||
|
||||
class TypeInstantiationItems(
|
||||
val resolutionFacade: ResolutionFacade,
|
||||
|
||||
@@ -17,13 +17,8 @@
|
||||
package org.jetbrains.jet.plugin.completion.smart
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowValue
|
||||
@@ -34,40 +29,23 @@ import org.jetbrains.jet.lang.resolve.calls.smartcasts.Nullability
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||
|
||||
class TypesWithSmartCasts(val bindingContext: BindingContext) {
|
||||
public fun calculate(expression: JetExpression, receiver: JetExpression?): (DeclarationDescriptor) -> Iterable<JetType> {
|
||||
public fun calculate(expression: JetExpression, receiver: JetExpression?): (VariableDescriptor) -> Collection<JetType> {
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
|
||||
val (variableToTypes: Map<VariableDescriptor, Collection<JetType>>, notNullVariables: Set<VariableDescriptor>)
|
||||
= processDataFlowInfo(dataFlowInfo, receiver)
|
||||
val (variableToTypes, notNullVariables) = processDataFlowInfo(dataFlowInfo, receiver)
|
||||
|
||||
fun typesOf(descriptor: DeclarationDescriptor): Iterable<JetType> {
|
||||
if (descriptor is CallableDescriptor) {
|
||||
var returnType = descriptor.getReturnType()
|
||||
if (returnType != null && KotlinBuiltIns.isNothing(returnType!!)) {
|
||||
//TODO: maybe we should include them on the second press?
|
||||
return listOf()
|
||||
}
|
||||
if (descriptor is VariableDescriptor) {
|
||||
if (notNullVariables.contains(descriptor)) {
|
||||
returnType = returnType?.makeNotNullable()
|
||||
}
|
||||
fun typesOf(descriptor: VariableDescriptor): Collection<JetType> {
|
||||
var type = descriptor.getReturnType() ?: return listOf()
|
||||
if (notNullVariables.contains(descriptor)) {
|
||||
type = type.makeNotNullable()
|
||||
}
|
||||
|
||||
val smartCastTypes = variableToTypes[descriptor]
|
||||
if (smartCastTypes != null && !smartCastTypes.isEmpty()) {
|
||||
return smartCastTypes + returnType.toList()
|
||||
}
|
||||
}
|
||||
return returnType.toList()
|
||||
}
|
||||
else if (descriptor is ClassDescriptor && descriptor.getKind().isSingleton()) {
|
||||
return listOf(descriptor.getDefaultType())
|
||||
}
|
||||
else {
|
||||
return listOf()
|
||||
}
|
||||
val smartCastTypes = variableToTypes[descriptor]
|
||||
if (smartCastTypes == null || smartCastTypes.isEmpty()) return type.toList()
|
||||
return smartCastTypes + type.toList()
|
||||
}
|
||||
|
||||
return ::typesOf
|
||||
|
||||
@@ -27,9 +27,7 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.plugin.completion.*
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler
|
||||
@@ -39,6 +37,9 @@ import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
|
||||
class ArtificialElementInsertHandler(
|
||||
val textBeforeCaret: String, val textAfterCaret: String, val shortenRefs: Boolean) : InsertHandler<LookupElement>{
|
||||
@@ -98,36 +99,71 @@ fun LookupElement.addTailAndNameSimilarity(matchedExpectedInfos: Collection<Expe
|
||||
return lookupElement
|
||||
}
|
||||
|
||||
enum class ExpectedInfoClassification {
|
||||
MATCHES
|
||||
MAKE_NOT_NULLABLE
|
||||
NOT_MATCHES
|
||||
class ExpectedInfoClassification private(val substitutor: TypeSubstitutor?, val makeNotNullable: Boolean) {
|
||||
class object {
|
||||
val notMatches = ExpectedInfoClassification(null, false)
|
||||
fun matches(substitutor: TypeSubstitutor) = ExpectedInfoClassification(substitutor, false)
|
||||
fun matchesIfNotNullable(substitutor: TypeSubstitutor) = ExpectedInfoClassification(substitutor, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableCollection<LookupElement>.addLookupElements(expectedInfos: Collection<ExpectedInfo>,
|
||||
infoClassifier: (ExpectedInfo) -> ExpectedInfoClassification,
|
||||
lookupElementFactory: () -> LookupElement?) {
|
||||
val matchedInfos = ArrayList<ExpectedInfo>()
|
||||
val matchedInfosNotNullable = ArrayList<ExpectedInfo>()
|
||||
fun FuzzyType.classifyExpectedInfo(expectedInfo: ExpectedInfo): ExpectedInfoClassification {
|
||||
val substitutor = matchedSubstitutor(expectedInfo.type)
|
||||
if (substitutor != null) {
|
||||
return ExpectedInfoClassification.matches(substitutor)
|
||||
}
|
||||
|
||||
if (isNullable()) {
|
||||
val substitutor2 = makeNotNullable().matchedSubstitutor(expectedInfo.type)
|
||||
if (substitutor2 != null) {
|
||||
return ExpectedInfoClassification.matchesIfNotNullable(substitutor2)
|
||||
}
|
||||
}
|
||||
|
||||
return ExpectedInfoClassification.notMatches
|
||||
}
|
||||
|
||||
fun<TDescriptor: DeclarationDescriptor?> MutableCollection<LookupElement>.addLookupElements(
|
||||
descriptor: TDescriptor,
|
||||
expectedInfos: Collection<ExpectedInfo>,
|
||||
infoClassifier: (ExpectedInfo) -> ExpectedInfoClassification,
|
||||
lookupElementFactory: (TDescriptor) -> LookupElement?
|
||||
) {
|
||||
class DescriptorWrapper(val descriptor: TDescriptor) {
|
||||
override fun equals(other: Any?) = other is DescriptorWrapper && descriptorsEqualWithSubstitution(this.descriptor, other.descriptor)
|
||||
override fun hashCode() = if (this.descriptor != null) this.descriptor.getOriginal().hashCode() else 0
|
||||
}
|
||||
fun TDescriptor.wrap() = DescriptorWrapper(this)
|
||||
fun DescriptorWrapper.unwrap() = this.descriptor
|
||||
|
||||
val matchedInfos = HashMap<DescriptorWrapper, MutableList<ExpectedInfo>>()
|
||||
val makeNullableInfos = HashMap<DescriptorWrapper, MutableList<ExpectedInfo>>()
|
||||
for (info in expectedInfos) {
|
||||
when (infoClassifier(info)) {
|
||||
ExpectedInfoClassification.MATCHES -> matchedInfos.add(info)
|
||||
ExpectedInfoClassification.MAKE_NOT_NULLABLE -> matchedInfosNotNullable.add(info)
|
||||
val classification = infoClassifier(info)
|
||||
if (classification.substitutor != null) {
|
||||
[suppress("UNCHECKED_CAST")]
|
||||
val substitutedDescriptor = descriptor?.substitute(classification.substitutor) as TDescriptor
|
||||
val map = if (classification.makeNotNullable) makeNullableInfos else matchedInfos
|
||||
map.getOrPut(substitutedDescriptor.wrap()) { ArrayList() }.add(info)
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedInfos.isNotEmpty()) {
|
||||
val lookupElement = lookupElementFactory()
|
||||
if (lookupElement != null) {
|
||||
add(lookupElement.addTailAndNameSimilarity(matchedInfos))
|
||||
if (!matchedInfos.isEmpty()) {
|
||||
for ((substitutedDescriptor, infos) in matchedInfos) {
|
||||
val lookupElement = lookupElementFactory(substitutedDescriptor.unwrap())
|
||||
if (lookupElement != null) {
|
||||
add(lookupElement.addTailAndNameSimilarity(infos))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (matchedInfosNotNullable.isNotEmpty()) {
|
||||
addLookupElementsForNullable(lookupElementFactory, matchedInfosNotNullable)
|
||||
else {
|
||||
for ((substitutedDescriptor, infos) in makeNullableInfos) {
|
||||
addLookupElementsForNullable({ lookupElementFactory(substitutedDescriptor.unwrap()) }, infos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableCollection<LookupElement>.addLookupElementsForNullable(factory: () -> LookupElement?, matchedInfos: Collection<ExpectedInfo>) {
|
||||
private fun MutableCollection<LookupElement>.addLookupElementsForNullable(factory: () -> LookupElement?, matchedInfos: Collection<ExpectedInfo>) {
|
||||
var lookupElement = factory()
|
||||
if (lookupElement != null) {
|
||||
lookupElement = object: LookupElementDecorator<LookupElement>(lookupElement!!) {
|
||||
@@ -205,8 +241,6 @@ fun LookupElementFactory.createLookupElement(
|
||||
return element
|
||||
}
|
||||
|
||||
fun JetType.isSubtypeOf(expectedType: JetType) = !isError() && JetTypeChecker.DEFAULT.isSubtypeOf(this, expectedType)
|
||||
|
||||
fun <T : Any> T?.toList(): List<T> = if (this != null) listOf(this) else listOf()
|
||||
fun <T : Any> T?.toSet(): Set<T> = if (this != null) setOf(this) else setOf()
|
||||
|
||||
@@ -235,4 +269,3 @@ fun LookupElement.assignSmartCompletionPriority(priority: SmartCompletionItemPri
|
||||
putUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY, priority)
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(array: Array<String>){}
|
||||
|
||||
fun f(){
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "array", tailText: "(vararg t: String) (kotlin)", typeText: "Array<String>" }
|
||||
// ABSENT: arrayOfNulls
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(array: Array<String?>){}
|
||||
|
||||
fun f(){
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "array", tailText: "(vararg t: String?) (kotlin)", typeText: "Array<String?>" }
|
||||
// EXIST: { lookupString: "arrayOfNulls", tailText: "(size: Int) (kotlin)", typeText: "Array<String?>" }
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(list: List<String>){}
|
||||
|
||||
fun f(){
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "listOf", tailText: "() (kotlin)", typeText: "List<String>" }
|
||||
// EXIST: { lookupString: "listOf", tailText: "(vararg values: String) (kotlin)", typeText: "List<String>" }
|
||||
// EXIST: { lookupString: "arrayListOf", tailText: "(vararg values: String!) (kotlin)", typeText: "ArrayList<String!>" }
|
||||
@@ -0,0 +1,6 @@
|
||||
fun foo(list: List<String>): Collection<Int> {
|
||||
return list.<caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "map", tailText: "(transform: (String) -> Int) for Iterable<T> in kotlin", typeText: "List<Int>" }
|
||||
// ABSENT: filter
|
||||
@@ -0,0 +1,13 @@
|
||||
class C<T> {
|
||||
class object {
|
||||
fun<T> create(t: T): C<T>{}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(c: C<String>){}
|
||||
|
||||
fun f(){
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "create", itemText: "C.create", tailText: "(t: String) (<root>)", typeText: "C<String>" }
|
||||
@@ -0,0 +1,14 @@
|
||||
fun<T> emptyList(): List<T> = listOf()
|
||||
|
||||
fun foo(list: List<String>){}
|
||||
fun foo(list: List<String>, i: Int){}
|
||||
fun foo(list: List<Int>, b: Boolean){}
|
||||
fun foo(list: List<Int>, c: Char){}
|
||||
|
||||
fun f(){
|
||||
foo(empty<caret>)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "emptyList", typeText: "List<String>" }
|
||||
// EXIST: { lookupString: "emptyList", typeText: "List<Int>" }
|
||||
// NUMBER: 2
|
||||
@@ -0,0 +1,16 @@
|
||||
fun nothingFoo() = throw Exception()
|
||||
|
||||
fun<T> genericFoo1(t: T): T = t
|
||||
|
||||
fun<T: Any> genericFoo2(t: T): T? = t
|
||||
|
||||
fun<T: Runnable> genericFoo3(t: T): T = t
|
||||
|
||||
fun foo(): Runnable {
|
||||
return <caret>
|
||||
}
|
||||
|
||||
// ABSENT: nothingFoo
|
||||
// ABSENT: genericFoo1
|
||||
// ABSENT: genericFoo2
|
||||
// EXIST: { itemText: "genericFoo3", tailText: "(t: Runnable) (<root>)", typeText: "Runnable" }
|
||||
@@ -9,6 +9,7 @@ fun bar(p: (String) -> Boolean) {
|
||||
|
||||
// ORDER: ::doFilter
|
||||
// ORDER: p
|
||||
// ORDER: countTo
|
||||
// ORDER: {...}
|
||||
// ORDER: { String -> ... }
|
||||
// ORDER: ::error
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.jet.completion;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -258,12 +257,48 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericFunction1.kt")
|
||||
public void testGenericFunction1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericFunction1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericFunction2.kt")
|
||||
public void testGenericFunction2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericFunction2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericFunction3.kt")
|
||||
public void testGenericFunction3() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericFunction3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericFunction4.kt")
|
||||
public void testGenericFunction4() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericFunction4.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericFunction5.kt")
|
||||
public void testGenericFunction5() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericFunction5.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericMethodArgument.kt")
|
||||
public void testGenericMethodArgument() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GenericMethodArgument.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GroupBySubstitutor.kt")
|
||||
public void testGroupBySubstitutor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/GroupBySubstitutor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("IfCondition.kt")
|
||||
public void testIfCondition() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/IfCondition.kt");
|
||||
@@ -732,6 +767,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SkipDeclarationsOfType.kt")
|
||||
public void testSkipDeclarationsOfType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/SkipDeclarationsOfType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SkipUnresolvedTypes.kt")
|
||||
public void testSkipUnresolvedTypes() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/SkipUnresolvedTypes.kt");
|
||||
|
||||
Reference in New Issue
Block a user