Completion to insert type arguments for a call when they are likely required

This commit is contained in:
Valentin Kipyatkov
2015-08-19 20:12:48 +03:00
parent 4743a69d76
commit 5fc6525db6
34 changed files with 372 additions and 80 deletions
@@ -103,6 +103,9 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
)
}
override val expectedInfos: Collection<ExpectedInfo>
get() = smartCompletion?.expectedInfos ?: emptyList()
private fun calcCompletionKind(): CompletionKind {
if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) {
return CompletionKind.NAMED_ARGUMENTS_ONLY
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
@@ -142,10 +143,11 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = nameExpression?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it) }
protected val lookupElementFactory: LookupElementFactory = run {
var receiverTypes = emptyList<JetType>()
if (receiversData != null) {
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
var receiverTypes = receiversData.receivers.flatMap { receiverValue ->
receiverTypes = receiversData.receivers.flatMap { receiverValue ->
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
if (dataFlowValue.isPredictable) { // we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed
resolutionFacade.frontendService<SmartCastManager>()
@@ -159,12 +161,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
if (receiversData.callType == CallType.SAFE) {
receiverTypes = receiverTypes.map { it.makeNotNullable() }
}
}
LookupElementFactory(resolutionFacade, receiverTypes)
}
else {
LookupElementFactory(resolutionFacade, emptyList())
}
LookupElementFactory(resolutionFacade, receiverTypes, { expectedInfos })
}
private val collectorContext = if (expression?.getParent() is JetSimpleNameStringTemplateEntry)
@@ -230,6 +229,8 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
protected abstract val descriptorKindFilter: DescriptorKindFilter?
protected abstract val expectedInfos: Collection<ExpectedInfo>
protected open fun createSorter(): CompletionSorter {
var sorter = CompletionSorter.defaultSorter(parameters, prefixMatcher)!!
@@ -65,6 +65,7 @@ object KDocNameCompletionProvider: CompletionProvider<CompletionParameters>() {
class KDocNameCompletionSession(parameters: CompletionParameters,
resultSet: CompletionResultSet): CompletionSession(CompletionSessionConfiguration(parameters), parameters, resultSet) {
override val descriptorKindFilter: DescriptorKindFilter? get() = null
override val expectedInfos: Collection<ExpectedInfo> get() = emptyList()
override fun doComplete() {
val position = parameters.getPosition().getParentOfType<KDocName>(false) ?: return
@@ -77,7 +77,7 @@ object KeywordCompletion {
.withInsertHandler(if (keywordToken !in FUNCTION_KEYWORDS)
KotlinKeywordInsertHandler
else
KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER)
KotlinFunctionInsertHandler(needTypeArguments = false, needValueArguments = false))
consumer(element)
}
}
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.completion.handlers.*
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -42,6 +43,8 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
public data class PackageLookupObject(val fqName: FqName) : DeclarationLookupObject {
override val psiElement: PsiElement? get() = null
@@ -59,8 +62,11 @@ public data class PackageLookupObject(val fqName: FqName) : DeclarationLookupObj
public class LookupElementFactory(
private val resolutionFacade: ResolutionFacade,
private val receiverTypes: Collection<JetType>
private val receiverTypes: Collection<JetType>,
expectedInfosCalculator: () -> Collection<ExpectedInfo>
) {
private val expectedInfos by lazy { expectedInfosCalculator() }
public fun createLookupElement(
descriptor: DeclarationDescriptor,
boldImmediateMembers: Boolean,
@@ -368,36 +374,74 @@ public class LookupElementFactory(
return typeParameter.containingDeclaration == original
}
companion object {
public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
return when (descriptor) {
is FunctionDescriptor -> {
val parameters = descriptor.getValueParameters()
when (parameters.size()) {
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
return when (descriptor) {
is FunctionDescriptor -> {
val needTypeArguments = needTypeArguments(descriptor)
val parameters = descriptor.valueParameters
when (parameters.size()) {
0 -> KotlinFunctionInsertHandler(needTypeArguments, needValueArguments = false)
1 -> {
val parameterType = parameters.single().getType()
if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
if (parameterCount <= 1) {
// otherwise additional item with lambda template is to be added
return KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false))
}
1 -> {
val parameterType = parameters.single().getType()
if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
if (parameterCount <= 1) {
// otherwise additional item with lambda template is to be added
return KotlinFunctionInsertHandler(needTypeArguments, needValueArguments = true, lambdaInfo = GenerateLambdaInfo(parameterType, false))
}
KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
}
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
KotlinFunctionInsertHandler(needTypeArguments, needValueArguments = true)
}
else -> KotlinFunctionInsertHandler(needTypeArguments, needValueArguments = true)
}
is PropertyDescriptor -> KotlinPropertyInsertHandler
is ClassifierDescriptor -> KotlinClassifierInsertHandler
else -> BaseDeclarationInsertHandler()
}
is PropertyDescriptor -> KotlinPropertyInsertHandler
is ClassifierDescriptor -> KotlinClassifierInsertHandler
else -> BaseDeclarationInsertHandler()
}
}
private fun needTypeArguments(function: FunctionDescriptor): Boolean {
if (function.typeParameters.isEmpty()) return false
val originalFunction = function.original
val typeParameters = originalFunction.typeParameters
val potentiallyInferred = HashSet<TypeParameterDescriptor>()
fun addPotentiallyInferred(type: JetType) {
val descriptor = type.constructor.declarationDescriptor as? TypeParameterDescriptor
if (descriptor != null && descriptor in typeParameters) {
potentiallyInferred.add(descriptor)
}
if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type) && KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(type).size() <= 1) {
// do not rely on inference from input of function type with one or no arguments - use only return type of functional type
addPotentiallyInferred(KotlinBuiltIns.getReturnTypeFromFunctionType(type))
return
}
for (argument in type.arguments) {
if (!argument.isStarProjection) { // otherwise we can fall into infinite recursion
addPotentiallyInferred(argument.type)
}
}
}
originalFunction.extensionReceiverParameter?.type?.let { addPotentiallyInferred(it) }
originalFunction.valueParameters.forEach { addPotentiallyInferred(it.type) }
val returnType = originalFunction.returnType
// check that there is an expected type and return value from the function can potentially match it
if (returnType != null && expectedInfos.any { it.fuzzyType?.checkIsSuperTypeOf(originalFunction.fuzzyReturnType()!!) != null }) {
addPotentiallyInferred(returnType)
}
return originalFunction.typeParameters.any { it !in potentiallyInferred }
}
}
@@ -138,6 +138,8 @@ class LookupElementsCollector(
private fun addSpecialFunctionDescriptorElement(descriptor: FunctionDescriptor, parameterType: JetType) {
var lookupElement = lookupElementFactory.createLookupElement(descriptor, true)
val needTypeArguments = (lookupElementFactory.getDefaultInsertHandler(descriptor) as KotlinFunctionInsertHandler).needTypeArguments
val lambdaInfo = GenerateLambdaInfo(parameterType, true)
lookupElement = object : LookupElementDecorator<LookupElement>(lookupElement) {
override fun renderElement(presentation: LookupElementPresentation) {
@@ -150,7 +152,7 @@ class LookupElementsCollector(
}
override fun handleInsert(context: InsertionContext) {
KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, true)).handleInsert(context, this)
KotlinFunctionInsertHandler(needTypeArguments, needValueArguments = true, lambdaInfo = lambdaInfo).handleInsert(context, this)
}
}
@@ -54,7 +54,7 @@ object PackageDirectiveCompletion {
val variants = ReferenceVariantsHelper(bindingContext, resolutionFacade, { true }).getPackageReferenceVariants(expression, prefixMatcher.asNameFilter())
for (variant in variants) {
val lookupElement = LookupElementFactory(resolutionFacade, listOf()).createLookupElement(variant, false)
val lookupElement = LookupElementFactory(resolutionFacade, emptyList(), { emptyList() }).createLookupElement(variant, false)
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
result.addElement(lookupElement)
}
@@ -35,24 +35,18 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.types.JetType
enum class CaretPosition {
IN_BRACKETS,
AFTER_BRACKETS
}
data class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean)
class KotlinFunctionInsertHandler(val caretPosition: CaretPosition, val lambdaInfo: GenerateLambdaInfo?) : KotlinCallableInsertHandler() {
init {
if (caretPosition == CaretPosition.AFTER_BRACKETS && lambdaInfo != null) {
throw IllegalArgumentException("CaretPosition.AFTER_BRACKETS with lambdaInfo != null combination is not supported")
}
}
class KotlinFunctionInsertHandler(
val needTypeArguments: Boolean,
val needValueArguments: Boolean,
val lambdaInfo: GenerateLambdaInfo? = null
) : KotlinCallableInsertHandler() {
public override fun handleInsert(context: InsertionContext, item: LookupElement) {
super.handleInsert(context, item)
val psiDocumentManager = PsiDocumentManager.getInstance(context.getProject())
val psiDocumentManager = PsiDocumentManager.getInstance(context.project)
psiDocumentManager.commitAllDocuments()
psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.getDocument())
@@ -88,31 +82,46 @@ class KotlinFunctionInsertHandler(val caretPosition: CaretPosition, val lambdaIn
context.setAddCompletionChar(false)
}
var offset = context.getTailOffset()
val document = context.getDocument()
val chars = document.getCharsSequence()
var offset = context.tailOffset
val document = context.document
val editor = context.editor
val project = context.project
val chars = document.charsSequence
val insertLambda = lambdaInfo != null && completionChar != '(' && !(completionChar == '\t' && chars.isCharAt(offset, '('))
val openingBracket = if (insertLambda) '{' else '('
val closingBracket = if (insertLambda) '}' else ')'
var insertTypeArguments = needTypeArguments && (completionChar == '\n' || completionChar == '\r')
if (completionChar == Lookup.REPLACE_SELECT_CHAR) {
val offset1 = chars.skipSpaces(offset)
if (offset1 < chars.length()) {
if (chars[offset1] == '<') {
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
PsiDocumentManager.getInstance(project).commitDocument(document)
val token = context.getFile().findElementAt(offset1)!!
if (token.getNode().getElementType() == JetTokens.LT) {
val parent = token.getParent()
if (parent is JetTypeArgumentList && parent.getText().indexOf('\n') < 0/* if type argument list is on multiple lines this is more likely wrong parsing*/) {
offset = parent.endOffset
insertTypeArguments = false
}
}
}
}
}
if (insertLambda && lambdaInfo!!.explicitParameters) {
insertTypeArguments = false
}
if (insertTypeArguments) {
document.insertString(offset, "<>")
editor.caretModel.moveToOffset(offset + 1)
offset += 2
}
var openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)
var closeBracketOffset = openingBracketOffset?.let { chars.indexOfSkippingSpace(closingBracket, it + 1) }
var inBracketsShift = 0
@@ -127,7 +136,7 @@ class KotlinFunctionInsertHandler(val caretPosition: CaretPosition, val lambdaIn
context.setAddCompletionChar(false)
}
if (isInsertSpacesInOneLineFunctionEnabled(context.getProject())) {
if (isInsertSpacesInOneLineFunctionEnabled(project)) {
document.insertString(offset, " { }")
inBracketsShift = 1
}
@@ -138,22 +147,23 @@ class KotlinFunctionInsertHandler(val caretPosition: CaretPosition, val lambdaIn
else {
document.insertString(offset, "()")
}
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
PsiDocumentManager.getInstance(project).commitDocument(document)
openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)!!
closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1)!!
}
val editor = context.getEditor()
if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == null) {
editor.getCaretModel().moveToOffset(openingBracketOffset + 1 + inBracketsShift)
AutoPopupController.getInstance(context.getProject())?.autoPopupParameterInfo(editor, offsetElement)
}
else {
editor.getCaretModel().moveToOffset(closeBracketOffset + 1)
if (!insertTypeArguments) {
if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == null) {
editor.caretModel.moveToOffset(openingBracketOffset + 1 + inBracketsShift)
AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement)
}
else {
editor.caretModel.moveToOffset(closeBracketOffset + 1)
}
}
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
PsiDocumentManager.getInstance(project).commitDocument(document)
if (insertLambda && lambdaInfo!!.explicitParameters) {
insertLambdaTemplate(context, TextRange(openingBracketOffset, closeBracketOffset!! + 1), lambdaInfo!!.lambdaType)
@@ -163,14 +173,9 @@ class KotlinFunctionInsertHandler(val caretPosition: CaretPosition, val lambdaIn
private fun shouldPlaceCaretInBrackets(completionChar: Char): Boolean {
if (completionChar == ',' || completionChar == '.' || completionChar == '=') return false
if (completionChar == '(') return true
return caretPosition == CaretPosition.IN_BRACKETS
return needValueArguments
}
companion object {
public val NO_PARAMETERS_HANDLER: KotlinFunctionInsertHandler = KotlinFunctionInsertHandler(CaretPosition.AFTER_BRACKETS, null)
public val WITH_PARAMETERS_HANDLER: KotlinFunctionInsertHandler = KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, null)
private fun isInsertSpacesInOneLineFunctionEnabled(project: Project)
= CodeStyleSettingsManager.getSettings(project).getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
}
private fun isInsertSpacesInOneLineFunctionEnabled(project: Project)
= CodeStyleSettingsManager.getSettings(project).getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
}
@@ -38,6 +38,17 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
// we do not include SAM-constructors because they are handled separately and adding them requires iterating of java classes
override val descriptorKindFilter = DescriptorKindFilter.VALUES exclude SamConstructorDescriptorKindExclude
private val smartCompletion by lazy {
expression?.let {
SmartCompletion(it, resolutionFacade,
bindingContext, isVisibleFilter, inDescriptor, prefixMatcher, originalSearchScope,
toFromOriginalFileMapper, lookupElementFactory)
}
}
override val expectedInfos: Collection<ExpectedInfo>
get() = smartCompletion?.expectedInfos ?: emptyList()
override fun doComplete() {
if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) {
NamedArgumentCompletion.complete(position, collector, bindingContext)
@@ -47,16 +58,11 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
if (expression != null) {
addFunctionLiteralArgumentCompletions()
val completion = SmartCompletion(
expression, resolutionFacade, bindingContext, isVisibleFilter, inDescriptor,
prefixMatcher, originalSearchScope, toFromOriginalFileMapper, lookupElementFactory
)
val (additionalItems, inheritanceSearcher) = completion.additionalItems()
val (additionalItems, inheritanceSearcher) = smartCompletion!!.additionalItems()
collector.addElements(additionalItems)
if (nameExpression != null) {
val filter = completion.descriptorFilter
val filter = smartCompletion!!.descriptorFilter
if (filter != null) {
referenceVariants.forEach { collector.addElements(filter(it)) }
flushToResultSet()
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.idea.completion.*
import org.jetbrains.kotlin.idea.completion.handlers.CaretPosition
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMethodsHandler
import org.jetbrains.kotlin.idea.core.psiClassToDescriptor
@@ -185,9 +184,9 @@ class TypeInstantiationItems(
}
val baseInsertHandler = when (visibleConstructors.size()) {
0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER
1 -> LookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler
else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER
0 -> KotlinFunctionInsertHandler(needTypeArguments = false, needValueArguments = false)
1 -> lookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler
else -> KotlinFunctionInsertHandler(needTypeArguments = false, needValueArguments = true)
}
insertHandler = object : InsertHandler<LookupElement> {
@@ -200,7 +199,7 @@ class TypeInstantiationItems(
shortenReferences(context, context.getStartOffset(), context.getTailOffset())
}
}
if (baseInsertHandler.caretPosition == CaretPosition.IN_BRACKETS) {
if (baseInsertHandler.needValueArguments) {
lookupElement = lookupElement.keepOldArgumentListOnTab()
}
if (baseInsertHandler.lambdaInfo != null) {
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): String { }
fun f(list: List<Any>): String {
return list.<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): String { }
fun f(list: List<Any>): String {
return list.foo<<caret>>()
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.myFilterIsInstance(): Collection<T> { }
fun foo(list: List<Any>): String {
return list.<caret>
}
// ELEMENT: myFilterIsInstance
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.myFilterIsInstance(): Collection<T> { }
fun foo(list: List<Any>): String {
return list.myFilterIsInstance<<caret>>()
}
// ELEMENT: myFilterIsInstance
@@ -0,0 +1,8 @@
fun <T> foo(p : (T, Int) -> Boolean){}
fun main(args: Array<String>) {
fo<caret>
}
// ELEMENT: foo
// TAIL_TEXT: " { T, Int -> ... } (p: (T, Int) -> Boolean) (<root>)"
@@ -0,0 +1,8 @@
fun <T> foo(p : (T, Int) -> Boolean){}
fun main(args: Array<String>) {
foo { t, i -> <caret> }
}
// ELEMENT: foo
// TAIL_TEXT: " { T, Int -> ... } (p: (T, Int) -> Boolean) (<root>)"
@@ -0,0 +1,7 @@
fun <T1, T2> T1.foo(handler: (T2) -> Boolean) {}
fun f() {
"".<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
fun <T1, T2> T1.foo(handler: (T2) -> Boolean) {}
fun f() {
"".foo<<caret>> { }
}
// ELEMENT: foo
@@ -0,0 +1,5 @@
fun f(list: List<String>) {
list.<caret>
}
// ELEMENT: map
@@ -0,0 +1,5 @@
fun f(list: List<String>) {
list.map { <caret> }
}
// ELEMENT: map
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.myFirstIsInstance(): T { }
fun foo(list: List<Any>): String {
return list.<caret>
}
// ELEMENT: myFirstIsInstance
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.myFirstIsInstance(): T { }
fun foo(list: List<Any>): String {
return list.myFirstIsInstance()<caret>
}
// ELEMENT: myFirstIsInstance
@@ -0,0 +1,7 @@
fun <T1, reified T2> foo(t: T1): T1 {}
fun f() {
<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
fun <T1, reified T2> foo(t: T1): T1 {}
fun f() {
foo<<caret>>()
}
// ELEMENT: foo
@@ -0,0 +1,9 @@
inline fun <reified R> Iterable<*>.myFilterIsInstance(): List<R> {
return filterIsInstanceTo(ArrayList<R>())
}
fun foo(list: List<Any>) {
list.<caret>
}
// ELEMENT: myFilterIsInstance
@@ -0,0 +1,9 @@
inline fun <reified R> Iterable<*>.myFilterIsInstance(): List<R> {
return filterIsInstanceTo(ArrayList<R>())
}
fun foo(list: List<Any>) {
list.myFilterIsInstance<<caret>>()
}
// ELEMENT: myFilterIsInstance
@@ -0,0 +1,7 @@
fun <T1, T2> T1.foo(t: T2): T2 = t
fun foo() {
"".<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
fun <T1, T2> T1.foo(t: T2): T2 = t
fun foo() {
"".foo(<caret>)
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): List<T> { }
fun f(list: List<Any>): Collection<String> {
return list.<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): List<T> { }
fun f(list: List<Any>): Collection<String> {
return list.foo()<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): String { }
fun f(list: List<Any>): String {
return list.<caret>
}
// ELEMENT: foo
@@ -0,0 +1,7 @@
public inline fun <reified T> Iterable<*>.foo(): String { }
fun f(list: List<Any>): String {
return list.foo<<caret>>()
}
// ELEMENT: foo
@@ -400,4 +400,67 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
doTest(fileName);
}
}
@TestMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeArgsForCall extends AbstractBasicCompletionHandlerTest {
public void testAllFilesPresentInTypeArgsForCall() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/basic/typeArgsForCall"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("ExpectedTypeDoesNotHelp.kt")
public void testExpectedTypeDoesNotHelp() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/ExpectedTypeDoesNotHelp.kt");
doTest(fileName);
}
@TestMetadata("ExpectedTypeDoesNotHelp2.kt")
public void testExpectedTypeDoesNotHelp2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/ExpectedTypeDoesNotHelp2.kt");
doTest(fileName);
}
@TestMetadata("ExplicitLambdaSignature.kt")
public void testExplicitLambdaSignature() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/ExplicitLambdaSignature.kt");
doTest(fileName);
}
@TestMetadata("FunctionTypeParameter1.kt")
public void testFunctionTypeParameter1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/FunctionTypeParameter1.kt");
doTest(fileName);
}
@TestMetadata("FunctionTypeParameter2.kt")
public void testFunctionTypeParameter2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/FunctionTypeParameter2.kt");
doTest(fileName);
}
@TestMetadata("HasExpectedType.kt")
public void testHasExpectedType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/HasExpectedType.kt");
doTest(fileName);
}
@TestMetadata("NotAllTypeArgumentsFromParameters.kt")
public void testNotAllTypeArgumentsFromParameters() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/NotAllTypeArgumentsFromParameters.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/Simple.kt");
doTest(fileName);
}
@TestMetadata("TypeArgumentsFromParameters.kt")
public void testTypeArgumentsFromParameters() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/typeArgsForCall/TypeArgumentsFromParameters.kt");
doTest(fileName);
}
}
}
@@ -311,6 +311,12 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
doTest(fileName);
}
@TestMetadata("DoNotInsertTypeArguments.kt")
public void testDoNotInsertTypeArguments() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/DoNotInsertTypeArguments.kt");
doTest(fileName);
}
@TestMetadata("DoNotReplaceOnEnter.kt")
public void testDoNotReplaceOnEnter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/DoNotReplaceOnEnter.kt");
@@ -413,6 +419,12 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
doTest(fileName);
}
@TestMetadata("InsertTypeArguments.kt")
public void testInsertTypeArguments() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/InsertTypeArguments.kt");
doTest(fileName);
}
@TestMetadata("JavaEnumMemberInsertsImport.kt")
public void testJavaEnumMemberInsertsImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/JavaEnumMemberInsertsImport.kt");