Create Function From Usage: Quick-fix for functions invoked via call expressions

This commit is contained in:
Alexey Sedunov
2014-09-24 18:16:29 +04:00
parent 22e3557895
commit 6043c6d0a7
49 changed files with 694 additions and 103 deletions
@@ -232,6 +232,11 @@ public class QuickFixRegistrar {
QuickFixes.factories.put(NO_VALUE_FOR_PARAMETER, CreateBinaryOperationActionFactory.INSTANCE$);
QuickFixes.factories.put(TOO_MANY_ARGUMENTS, CreateBinaryOperationActionFactory.INSTANCE$);
QuickFixes.factories.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, CreateFunctionFromCallActionFactory.INSTANCE$);
QuickFixes.factories.put(UNRESOLVED_REFERENCE, CreateFunctionFromCallActionFactory.INSTANCE$);
QuickFixes.factories.put(NO_VALUE_FOR_PARAMETER, CreateFunctionFromCallActionFactory.INSTANCE$);
QuickFixes.factories.put(TOO_MANY_ARGUMENTS, CreateFunctionFromCallActionFactory.INSTANCE$);
QuickFixes.factories.put(FUNCTION_EXPECTED, CreateInvokeFunctionActionFactory.INSTANCE$);
QuickFixes.factories.put(TYPE_MISMATCH, new QuickFixFactoryForTypeMismatchError());
@@ -0,0 +1,52 @@
package org.jetbrains.jet.plugin.quickfix.createFromUsage.createFunction
import org.jetbrains.jet.plugin.quickfix.JetSingleIntentionActionFactory
import org.jetbrains.jet.lang.diagnostics.Diagnostic
import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.types.Variance
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.plugin.quickfix.QuickFixUtil
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.calls.callUtil.getCall
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.resolve.scopes.receivers.Qualifier
object CreateFunctionFromCallActionFactory : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val callExpr = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetCallExpression>()) ?: return null
val calleeExpr = callExpr.getCalleeExpression() as? JetSimpleNameExpression ?: return null
if (calleeExpr.getReferencedNameElementType() != JetTokens.IDENTIFIER) return null
val callParent = callExpr.getParent()
val fullCallExpr =
if (callParent is JetQualifiedExpression && callParent.getSelectorExpression() == callExpr) callParent else callExpr
val context = AnalyzerFacadeWithCache.getContextForElement(callExpr)
val receiver = callExpr.getCall(context)?.getExplicitReceiver() ?: return null
val receiverType = when (receiver) {
ReceiverValue.NO_RECEIVER -> TypeInfo.Empty
is Qualifier -> when {
receiver.classifier != null -> TypeInfo(receiver.expression, Variance.IN_VARIANCE)
else -> return null
}
else -> TypeInfo(receiver.getType(), Variance.IN_VARIANCE)
}
val anyType = KotlinBuiltIns.getInstance().getNullableAnyType()
val parameters = callExpr.getValueArguments().map {
ParameterInfo(
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
it.getArgumentName()?.getReferenceExpression()?.getReferencedName()
)
}
val returnType = TypeInfo(fullCallExpr, Variance.OUT_VARIANCE)
return CreateFunctionFromUsageFix(callExpr, FunctionInfo(calleeExpr.getReferencedName(), receiverType, returnType, parameters))
}
}
@@ -2,50 +2,19 @@ package org.jetbrains.jet.plugin.quickfix.createFromUsage.createFunction
import com.intellij.psi.PsiElement
import org.jetbrains.jet.plugin.quickfix.createFromUsage.CreateFromUsageFixBase
import com.intellij.ide.util.PsiElementListCellRenderer
import org.jetbrains.jet.lang.psi.JetClass
import org.jetbrains.jet.plugin.presentation.JetClassPresenter
import javax.swing.JList
import java.awt.Component
import org.jetbrains.jet.lang.psi.JetFile
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.plugin.JetBundle
import com.intellij.openapi.project.Project
import com.intellij.openapi.application.ApplicationManager
import com.intellij.ui.components.JBList
import javax.swing.ListSelectionModel
import com.intellij.openapi.ui.popup.PopupChooserBuilder
import com.intellij.openapi.command.CommandProcessor
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
import org.jetbrains.jet.lang.psi.JetClassOrObject
import org.jetbrains.jet.plugin.refactoring.chooseContainerElementIfNecessary
import org.jetbrains.jet.plugin.refactoring.getExtractionContainers
import org.jetbrains.jet.lang.psi.JetClassBody
public class CreateFunctionFromUsageFix(element: PsiElement, val functionInfo: FunctionInfo) : CreateFromUsageFixBase(element) {
/**
* Represents an element in the class selection list.
*/
private class ClassCandidate(val typeCandidate: TypeCandidate, file: JetFile) {
val jetClass: JetClass = DescriptorToDeclarationUtil.getDeclaration(
file, DescriptorUtils.getClassDescriptorForType(typeCandidate.theType)
) as JetClass
}
private class ClassCandidateListCellRenderer : PsiElementListCellRenderer<JetClass>() {
private val presenter = JetClassPresenter()
override fun getElementText(element: JetClass): String? =
presenter.getPresentation(element)?.getPresentableText()
protected override fun getContainerText(element: JetClass?, name: String?): String? =
element?.let { presenter.getPresentation(it) }?.getLocationString()
override fun getIconFlags(): Int = 0
public override fun getListCellRendererComponent(
list: JList<out Any?>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean
): Component? =
super.getListCellRendererComponent(list, (value as ClassCandidate).jetClass, index, isSelected, cellHasFocus)
}
override fun getText(): String {
return JetBundle.message("create.function.from.usage", functionInfo.name)
}
@@ -53,32 +22,29 @@ public class CreateFunctionFromUsageFix(element: PsiElement, val functionInfo: F
override fun invoke(project: Project, editor: Editor?, file: JetFile?) {
val functionBuilder = FunctionBuilderConfiguration(functionInfo, file!!, editor!!).createBuilder()
val ownerTypeCandidates = functionBuilder.computeTypeCandidates(functionInfo.receiverTypeInfo)
assert(!ownerTypeCandidates.empty)
fun runBuilder(placement: FunctionPlacement) {
functionBuilder.placement = placement
CommandProcessor.getInstance().executeCommand(project, { functionBuilder.build() }, getText(), null)
}
if (ownerTypeCandidates.size == 1 || ApplicationManager.getApplication()!!.isUnitTestMode()) {
functionBuilder.receiverTypeCandidate = ownerTypeCandidates.first!!
functionBuilder.build()
val popupTitle = JetBundle.message("choose.target.class.or.trait.title")
val receiverTypeCandidates = functionBuilder.computeTypeCandidates(functionInfo.receiverTypeInfo)
if (receiverTypeCandidates.isNotEmpty()) {
val toPsi: (TypeCandidate) -> JetClassOrObject = {
val descriptor = DescriptorUtils.getClassDescriptorForType(it.theType)
DescriptorToDeclarationUtil.getDeclaration(file, descriptor) as JetClassOrObject
}
chooseContainerElementIfNecessary(receiverTypeCandidates, editor, popupTitle, false, toPsi) {
runBuilder(FunctionPlacement.WithReceiver(it))
}
}
else {
// class selection
val list = JBList(ownerTypeCandidates.map { ClassCandidate(it, file) })
val renderer = ClassCandidateListCellRenderer()
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
list.setCellRenderer(renderer)
val builder = PopupChooserBuilder(list)
renderer.installSpeedSearch(builder)
assert(functionInfo.receiverTypeInfo is TypeInfo.Empty, "No receiver type candidates: ${element.getText()} in ${file.getText()}")
builder.setTitle(JetBundle.message("choose.target.class.or.trait.title"))
.setItemChoosenCallback {
val selectedCandidate = list.getSelectedValue() as ClassCandidate?
if (selectedCandidate != null) {
functionBuilder.receiverTypeCandidate = selectedCandidate.typeCandidate
CommandProcessor.getInstance().executeCommand(project, { functionBuilder.build() }, getText(), null)
}
}
.createPopup()
.showInBestPositionFor(editor)
chooseContainerElementIfNecessary(element.getExtractionContainers(), editor, popupTitle, true, { it }) {
val container = if (it is JetClassBody) it.getParent() as JetClassOrObject else it
runBuilder(FunctionPlacement.NoReceiver(container))
}
}
}
}
@@ -15,6 +15,10 @@ import org.jetbrains.jet.plugin.util.supertypes
* Represents a concrete type or a set of types yet to be inferred from an expression.
*/
abstract class TypeInfo(val variance: Variance) {
object Empty: TypeInfo(Variance.INVARIANT) {
override fun getPossibleTypes(builder: FunctionBuilder): List<JetType> = Collections.emptyList()
}
class ByExpression(val expression: JetExpression, variance: Variance): TypeInfo(variance) {
override val possibleNamesFromExpression: Array<String> by Delegates.lazy {
JetNameSuggester.suggestNamesForExpression(expression, EmptyValidator)
@@ -31,7 +35,7 @@ abstract class TypeInfo(val variance: Variance) {
class ByReceiverType(variance: Variance): TypeInfo(variance) {
override fun getPossibleTypes(builder: FunctionBuilder): List<JetType> =
builder.receiverTypeCandidate.theType.getPossibleSupertypes(variance)
(builder.placement as FunctionPlacement.WithReceiver).receiverTypeCandidate.theType.getPossibleSupertypes(variance)
}
open val possibleNamesFromExpression: Array<String> get() = ArrayUtil.EMPTY_STRING_ARRAY
@@ -52,6 +52,7 @@ import org.jetbrains.jet.plugin.refactoring.EmptyValidator
import org.jetbrains.jet.plugin.refactoring.CollectingValidator
import org.jetbrains.jet.plugin.util.isUnit
import org.jetbrains.jet.plugin.refactoring.runWriteAction
import com.intellij.util.ArrayUtil
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt"
@@ -90,14 +91,17 @@ class FunctionBuilderConfiguration(
val currentEditor: Editor
)
trait FunctionPlacement {
class WithReceiver(val receiverTypeCandidate: TypeCandidate): FunctionPlacement
class NoReceiver(val containingElement: JetElement): FunctionPlacement
}
class FunctionBuilder(val config: FunctionBuilderConfiguration) {
private var finished: Boolean = false
val currentFileContext: BindingContext
val currentFileModule: ModuleDescriptor
public var receiverTypeCandidate: TypeCandidate by Delegates.notNull()
private val typeCandidates = HashMap<TypeInfo, List<TypeCandidate>>();
{
@@ -106,6 +110,8 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
currentFileModule = exhaust.getModuleDescriptor()
}
public var placement: FunctionPlacement by Delegates.notNull()
fun computeTypeCandidates(typeInfo: TypeInfo): List<TypeCandidate> =
typeCandidates.getOrPut(typeInfo) { typeInfo.getPossibleTypes(this).map { TypeCandidate(it) } }
@@ -136,44 +142,48 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
}
}
private inner class Context {
private inner class Context() {
val isUnit: Boolean
val isExtension: Boolean
val containingFile: JetFile
val containingFileEditor: Editor
val receiverClass: JetClass?
val receiverClassDescriptor: ClassDescriptor
val containingElement: JetElement
val receiverClassDescriptor: ClassDescriptor?
val typeParameterNameMap: Map<TypeParameterDescriptor, String>
val receiverTypeCandidate: TypeCandidate?
{
// gather relevant information
receiverClassDescriptor = DescriptorUtils.getClassDescriptorForType(receiverTypeCandidate.theType)
val receiverType = receiverClassDescriptor.getDefaultType()
val classDeclaration = DescriptorToSourceUtils.classDescriptorToDeclaration(receiverClassDescriptor)
if (classDeclaration is JetClass) {
receiverClass = classDeclaration
isExtension = !classDeclaration.isWritable()
val placement = placement
when {
placement is FunctionPlacement.NoReceiver -> {
receiverClassDescriptor = null
isExtension = false
containingElement = placement.containingElement
}
placement is FunctionPlacement.WithReceiver -> {
receiverClassDescriptor = DescriptorUtils.getClassDescriptorForType(placement.receiverTypeCandidate.theType)
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.classDescriptorToDeclaration(it) }
isExtension = !(classDeclaration is JetClassOrObject && classDeclaration.isWritable())
containingElement = if (isExtension) config.currentFile else classDeclaration as JetElement
}
else -> throw IllegalArgumentException("Unexpected function kind: $placement")
}
else {
receiverClass = null
isExtension = true
val receiverType = receiverClassDescriptor?.getDefaultType()
}
if (isExtension) {
containingFile = config.currentFile
containingFileEditor = config.currentEditor
}
else {
containingFile = receiverClass!!.getContainingJetFile()
NavigationUtil.activateFileWithPsiElement(containingFile)
containingFile = containingElement.getContainingJetFile()
if (containingFile != config.currentFile) {
NavigationUtil.activateFileWithPsiElement(containingElement)
containingFileEditor = FileEditorManager.getInstance(config.currentFile.getProject())!!.getSelectedTextEditor()!!
}
else {
containingFileEditor = config.currentEditor
}
isUnit = config.functionInfo.returnTypeInfo.let { it is TypeInfo.ByType && it.theType.isUnit() }
val scope = if (isExtension) {
val scope = if (isExtension || receiverClassDescriptor == null) {
currentFileModule.getPackage(config.currentFile.getPackageFqName())!!.getMemberScope()
}
else {
@@ -181,8 +191,9 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
}
// figure out type substitutions for type parameters
val classTypeParameters = receiverType.getArguments()
val ownerTypeArguments = receiverTypeCandidate.theType.getArguments()
val classTypeParameters = receiverType?.getArguments() ?: Collections.emptyList()
val ownerTypeArguments = (placement as? FunctionPlacement.WithReceiver)?.receiverTypeCandidate?.theType?.getArguments()
?: Collections.emptyList()
assert(ownerTypeArguments.size == classTypeParameters.size)
val substitutions = ownerTypeArguments.zip(classTypeParameters).map {
JetTypeSubstitution(it.first.getType(), it.second.getType())
@@ -193,7 +204,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
}
// now that we have done substitutions, we can throw it away
receiverTypeCandidate = TypeCandidate(receiverType, scope)
receiverTypeCandidate = receiverType?.let { TypeCandidate(it, scope) }
// figure out type parameter renames to avoid conflicts
typeParameterNameMap = getTypeParameterRenames(scope)
@@ -201,7 +212,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
if (!isUnit) {
renderTypeCandidates(config.functionInfo.returnTypeInfo, typeParameterNameMap)
}
receiverTypeCandidate.render(typeParameterNameMap)
receiverTypeCandidate?.render(typeParameterNameMap)
}
private fun renderTypeCandidates(
@@ -218,25 +229,39 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
val psiFactory = JetPsiFactory(currentFile)
if (isExtension) {
// create as extension function
val ownerTypeString = receiverTypeCandidate.renderedType!!
val ownerTypeString = receiverTypeCandidate!!.renderedType!!
val func = psiFactory.createFunction(
"fun $ownerTypeString.${functionInfo.name}($parametersString)$returnTypeString { }"
)
return currentFile.add(func) as JetNamedFunction
}
else {
receiverClass!!
// create as regular function
val func = psiFactory.createFunction("fun ${functionInfo.name}($parametersString)$returnTypeString { }")
var classBody = receiverClass.getBody()
if (classBody == null) {
classBody = receiverClass.add(psiFactory.createEmptyClassBody()) as JetClassBody
receiverClass.addBefore(psiFactory.createWhiteSpace(), classBody)
when (containingElement) {
is JetFile -> {
return currentFile.add(func) as JetNamedFunction
}
is JetClassOrObject -> {
var classBody = containingElement.getBody()
if (classBody == null) {
classBody = containingElement.add(psiFactory.createEmptyClassBody()) as JetClassBody
containingElement.addBefore(psiFactory.createWhiteSpace(), classBody)
}
val rBrace = classBody!!.getRBrace()
//TODO: Assert rbrace not null? It can be if the class isn't closed.
return classBody!!.addBefore(func, rBrace) as JetNamedFunction
}
is JetBlockExpression -> {
return containingElement.addAfter(func, containingElement.getLBrace()) as JetNamedFunction
}
else -> throw AssertionError("Invalid containing element: ${containingElement.getText()}")
}
val rBrace = classBody!!.getRBrace()
//TODO: Assert rbrace not null? It can be if the class isn't closed.
return classBody!!.addBefore(func, rBrace) as JetNamedFunction
}
}
}
@@ -244,7 +269,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
private fun getTypeParameterRenames(scope: JetScope): Map<TypeParameterDescriptor, String> {
val allTypeParametersNotInScope = LinkedHashSet<TypeParameterDescriptor>()
allTypeParametersNotInScope.addAll(receiverTypeCandidate.typeParameters.toList())
allTypeParametersNotInScope.addAll(receiverTypeCandidate?.typeParameters?.toList() ?: Collections.emptyList())
config.functionInfo.parameterInfos.stream()
.flatMap { typeCandidates[it.typeInfo]!!.stream() }
@@ -266,7 +291,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
typeRefsToShorten: MutableList<JetTypeReference>, parameterTypeExpressions: List<TypeExpression>,
returnTypeExpression: TypeExpression?) {
if (isExtension) {
val receiverTypeRef = JetPsiFactory(func).createType(receiverTypeCandidate.theType.renderLong(typeParameterNameMap))
val receiverTypeRef = JetPsiFactory(func).createType(receiverTypeCandidate!!.theType.renderLong(typeParameterNameMap))
replaceWithLongerName(receiverTypeRef, receiverTypeCandidate.theType)
val funcReceiverTypeRef = func.getReceiverTypeRef()
@@ -310,8 +335,10 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
val fileTemplate = FileTemplateManager.getInstance()!!.getCodeTemplate(TEMPLATE_FROM_USAGE_FUNCTION_BODY)
val properties = Properties()
properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, if (isUnit) "Unit" else func.getReturnTypeRef()!!.getText())
properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFqName(receiverClassDescriptor).asString())
properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, receiverClassDescriptor.getName().asString())
receiverClassDescriptor?.let {
properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFqName(it).asString())
properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, it.getName().asString())
}
properties.setProperty(ATTRIBUTE_FUNCTION_NAME, config.functionInfo.name)
val bodyText = try {
@@ -339,7 +366,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
private fun setupTypeParameterListTemplate(builder: TemplateBuilderImpl, func: JetNamedFunction): TypeParameterListExpression {
val typeParameterMap = HashMap<String, Array<String>>()
val receiverTypeParameterNames = receiverTypeCandidate.typeParameterNames
val receiverTypeParameterNames = receiverTypeCandidate?.let { it.typeParameterNames!! } ?: ArrayUtil.EMPTY_STRING_ARRAY
config.functionInfo.parameterInfos.stream().flatMap { typeCandidates[it.typeInfo]!!.stream() }.forEach {
typeParameterMap[it.renderedType!!] = it.typeParameterNames!!
@@ -352,7 +379,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
}
// ((3, 3) is after "fun")
builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false)
return TypeParameterListExpression(receiverTypeParameterNames!!, typeParameterMap)
return TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap)
}
private fun setupParameterTypeTemplates(builder: TemplateBuilder, parameterList: JetParameterList): List<TypeExpression> {
@@ -1,4 +1,5 @@
// "class com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFixBase" "false"
// ACTION: Create function 'FooPackage' from usage
// ERROR: Unresolved reference: FooPackage
package packageClass
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(arg: T, s: String, function: Function1<T, T>): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo(2, "2") { (p: Int) -> p + 1 }
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(function: Function1<T, T>): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo { (p: Int) -> p + 1 }
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(a: Int): A<T> = throw Exception()
fun foo(arg: T, s: String): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo(2, "2")
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(i: Int, s: String): A<T> = throw Exception()
fun foo(arg: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo(2)
}
@@ -0,0 +1,14 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
class object {
fun foo(i: Int): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
fun test() {
val a: Int = A.foo(2)
}
@@ -0,0 +1,8 @@
// "Create function 'foo' from usage" "true"
fun test() {
val a: Int = Unit.foo(2)
}
fun Unit.foo(i: Int): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,10 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun test() {
val a: A<Int> = 2.foo(A(1))
}
fun Int.foo(A: A<Int>): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
object A {
fun foo(i: Int): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: Int = A.foo(2)
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(arg: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo(2)
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(u: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test<U>(u: U) {
val a: A<U> = A(u).foo(u)
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(abc: T, ghi: A<T>, def: String): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
val a: A<Int> = A(1).foo(abc = 1, ghi = A(2), def = "s")
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
// ERROR: <html>Type mismatch.<table><tr><td>Required:</td><td>kotlin.Int</td></tr><tr><td>Found:</td><td>A&lt;kotlin.Int&gt;</td></tr></table></html>
class A<T>(val n: T) {
fun foo(s: String, arg: T): Any {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test(): Int {
return A(1).foo("s", 1) as A<Int>
}
@@ -0,0 +1,10 @@
// "Create function 'foo' from usage" "true"
fun test() {
fun foo(i: Int, s: String): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
fun nestedTest(): Int {
return foo(2, "2")
}
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A {
class B {
fun test(): Int {
return foo(2, "2")
}
fun foo(i: Int, s: String): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A {
object B {
fun test(): Int {
return foo(2, "2")
}
fun foo(i: Int, s: String): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
@@ -0,0 +1,10 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun test(): A<Int> {
return this.foo(2, "2")
}
fun foo(i: Int, s: String): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(i: Int, s: String): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun <U> A<U>.test(): A<Int> {
return this.foo(2, "2")
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
inner class B<U>(val m: U) {
fun test(): A<Int> {
return this.foo(2, "2")
}
fun foo(i: Int, s: String): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
inner class B<U>(val m: U) {
fun test(): A<Int> {
return this@A.foo(2, "2")
}
}
fun foo(i: Int, s: String): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -0,0 +1,8 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return foo(2, "2")
}
fun foo(i: Int, s: String): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,12 @@
// "Create function 'foo' from usage" "true"
// ERROR: Unresolved reference: s
class A<T>(val n: T) {
fun foo(s: Any, arg: T): T {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test(): Int {
return A(1).foo(s, 1)
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
}
fun test() {
val a: A<Int> = A(1).<caret>foo(2, "2") { (p: Int) -> p + 1 }
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
}
fun test() {
val a: A<Int> = A(1).<caret>foo { (p: Int) -> p + 1 }
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(a: Int): A<T> = throw Exception()
}
fun test() {
val a: A<Int> = A(1).foo(2, <caret>"2")
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun foo(i: Int, s: String): A<T> = throw Exception()
}
fun test() {
val a: A<Int> = A(1).foo(2<caret>)
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
class object {
}
}
fun test() {
val a: Int = A.<caret>foo(2)
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test() {
val a: Int = Unit.<caret>foo(2)
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun test() {
val a: A<Int> = 2.<caret>foo(A(1))
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
object A
fun test() {
val a: Int = A.<caret>foo(2)
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun test() {
val a: A<Int> = A(1).<caret>foo(2)
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun test<U>(u: U) {
val a: A<U> = A(u).<caret>foo(u)
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun test() {
val a: A<Int> = A(1).<caret>foo(abc = 1, ghi = A(2), def = "s")
}
@@ -0,0 +1,8 @@
// "Create function 'foo' from usage" "true"
// ERROR: <html>Type mismatch.<table><tr><td>Required:</td><td>kotlin.Int</td></tr><tr><td>Found:</td><td>A&lt;kotlin.Int&gt;</td></tr></table></html>
class A<T>(val n: T)
fun test(): Int {
return A(1).<caret>foo("s", 1) as A<Int>
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
fun test() {
fun nestedTest(): Int {
return <caret>foo(2, "2")
}
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A {
class B {
fun test(): Int {
return <caret>foo(2, "2")
}
}
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A {
object B {
fun test(): Int {
return <caret>foo(2, "2")
}
}
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
fun test(): A<Int> {
return this.<caret>foo(2, "2")
}
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T)
fun <U> A<U>.test(): A<Int> {
return this.<caret>foo(2, "2")
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
inner class B<U>(val m: U) {
fun test(): A<Int> {
return this.<caret>foo(2, "2")
}
}
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
class A<T>(val n: T) {
inner class B<U>(val m: U) {
fun test(): A<Int> {
return this@A.<caret>foo(2, "2")
}
}
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return <caret>foo(2, "2")
}
@@ -0,0 +1,8 @@
// "Create function 'foo' from usage" "true"
// ERROR: Unresolved reference: s
class A<T>(val n: T)
fun test(): Int {
return A(1).<caret>foo(s, 1)
}
@@ -618,7 +618,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
@TestMetadata("idea/testData/quickfix/createFromUsage")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({CreateFromUsage.BinaryOperations.class, CreateFromUsage.Component.class, CreateFromUsage.Get.class, CreateFromUsage.HasNext.class, CreateFromUsage.Invoke.class, CreateFromUsage.Iterator.class, CreateFromUsage.Next.class, CreateFromUsage.Set.class, CreateFromUsage.UnaryOperations.class})
@InnerTestClasses({CreateFromUsage.BinaryOperations.class, CreateFromUsage.Call.class, CreateFromUsage.Component.class, CreateFromUsage.Get.class, CreateFromUsage.HasNext.class, CreateFromUsage.Invoke.class, CreateFromUsage.Iterator.class, CreateFromUsage.Next.class, CreateFromUsage.Set.class, CreateFromUsage.UnaryOperations.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class CreateFromUsage extends AbstractQuickFixTest {
public void testAllFilesPresentInCreateFromUsage() throws Exception {
@@ -719,6 +719,142 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
@TestMetadata("idea/testData/quickfix/createFromUsage/call")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class Call extends AbstractQuickFixTest {
public void testAllFilesPresentInCall() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/call"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeCallWithLambdaArg.kt")
public void testCallWithLambdaArg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeCallWithLambdaArg.kt");
doTest(fileName);
}
@TestMetadata("beforeCallWithLambdaArgOnly.kt")
public void testCallWithLambdaArgOnly() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeCallWithLambdaArgOnly.kt");
doTest(fileName);
}
@TestMetadata("beforeFunExtraArgs.kt")
public void testFunExtraArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunExtraArgs.kt");
doTest(fileName);
}
@TestMetadata("beforeFunMissingArgs.kt")
public void testFunMissingArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunMissingArgs.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnClassObject.kt")
public void testFunOnClassObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnClassObject.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnLibObject.kt")
public void testFunOnLibObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnLibObject.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnLibType.kt")
public void testFunOnLibType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnLibType.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnUserObject.kt")
public void testFunOnUserObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnUserObject.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnUserType.kt")
public void testFunOnUserType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnUserType.kt");
doTest(fileName);
}
@TestMetadata("beforeFunOnUserTypeWithTypeParams.kt")
public void testFunOnUserTypeWithTypeParams() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunOnUserTypeWithTypeParams.kt");
doTest(fileName);
}
@TestMetadata("beforeFunWithExplicitParamNamesOnUserType.kt")
public void testFunWithExplicitParamNamesOnUserType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeFunWithExplicitParamNamesOnUserType.kt");
doTest(fileName);
}
@TestMetadata("beforeInconsistentTypes.kt")
public void testInconsistentTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeInconsistentTypes.kt");
doTest(fileName);
}
@TestMetadata("beforeLocalFunNoReceiver.kt")
public void testLocalFunNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeLocalFunNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("beforeMemberFunNoReceiver.kt")
public void testMemberFunNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeMemberFunNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("beforeObjectMemberFunNoReceiver.kt")
public void testObjectMemberFunNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeObjectMemberFunNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInClass.kt")
public void testThisInClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeThisInClass.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInExtension.kt")
public void testThisInExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeThisInExtension.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInNestedClass1.kt")
public void testThisInNestedClass1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeThisInNestedClass1.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInNestedClass2.kt")
public void testThisInNestedClass2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeThisInNestedClass2.kt");
doTest(fileName);
}
@TestMetadata("beforeTopLevelFunNoReceiver.kt")
public void testTopLevelFunNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeTopLevelFunNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("beforeUnknownType.kt")
public void testUnknownType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/call/beforeUnknownType.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/component")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)