Create from usage: Support generation of Java methods from usages in Kotlin code
This commit is contained in:
+89
-15
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.refactoring.JetNameSuggester
|
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import java.util.LinkedHashSet
|
import java.util.LinkedHashSet
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
@@ -46,13 +45,10 @@ import java.util.ArrayList
|
|||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.idea.refactoring.EmptyValidator
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.CollectingValidator
|
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isMultiLine
|
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
import com.intellij.psi.SmartPointerManager
|
import com.intellij.psi.SmartPointerManager
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
@@ -69,6 +65,18 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
|
|||||||
import org.jetbrains.kotlin.idea.util.isUnit
|
import org.jetbrains.kotlin.idea.util.isUnit
|
||||||
import com.intellij.openapi.editor.ScrollType
|
import com.intellij.openapi.editor.ScrollType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||||
|
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||||
|
import com.intellij.psi.PsiModifier
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.*
|
||||||
|
|
||||||
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
|
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
|
||||||
private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt"
|
private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt"
|
||||||
@@ -228,7 +236,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
receiverClassDescriptor =
|
receiverClassDescriptor =
|
||||||
placement.receiverTypeCandidate.theType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor
|
placement.receiverTypeCandidate.theType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor
|
||||||
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.classDescriptorToDeclaration(it) }
|
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.classDescriptorToDeclaration(it) }
|
||||||
containingElement = if (config.isExtension) config.currentFile else classDeclaration as JetElement
|
containingElement = when {
|
||||||
|
!config.isExtension && classDeclaration is JetElement -> classDeclaration
|
||||||
|
else -> config.currentFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("Unexpected placement: $placement")
|
else -> throw IllegalArgumentException("Unexpected placement: $placement")
|
||||||
}
|
}
|
||||||
@@ -243,12 +254,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
containingFileEditor = config.currentEditor!!
|
containingFileEditor = config.currentEditor!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val scope = if (config.isExtension || receiverClassDescriptor == null) {
|
val scope = getDeclarationScope()
|
||||||
currentFileModule.getPackage(config.currentFile.getPackageFqName())!!.getMemberScope()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(receiverClassDescriptor as ClassDescriptorWithResolutionScopes).getScopeForMemberDeclarationResolution()
|
|
||||||
}
|
|
||||||
|
|
||||||
receiverTypeCandidate = receiverType?.let { TypeCandidate(it, scope) }
|
receiverTypeCandidate = receiverType?.let { TypeCandidate(it, scope) }
|
||||||
|
|
||||||
@@ -297,6 +303,41 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
mandatoryTypeParametersAsCandidates.forEach { it.render(typeParameterNameMap, fakeFunction) }
|
mandatoryTypeParametersAsCandidates.forEach { it.render(typeParameterNameMap, fakeFunction) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getDeclarationScope(): JetScope {
|
||||||
|
if (config.isExtension || receiverClassDescriptor == null) {
|
||||||
|
return currentFileModule.getPackage(config.currentFile.getPackageFqName())!!.getMemberScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receiverClassDescriptor is ClassDescriptorWithResolutionScopes) {
|
||||||
|
return receiverClassDescriptor.getScopeForMemberDeclarationResolution()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (receiverClassDescriptor is JavaClassDescriptor, "Unexpected receiver class: ${receiverClassDescriptor}")
|
||||||
|
|
||||||
|
val typeParamScope = with(
|
||||||
|
WritableScopeImpl(
|
||||||
|
JetScope.Empty,
|
||||||
|
receiverClassDescriptor,
|
||||||
|
RedeclarationHandler.DO_NOTHING,
|
||||||
|
"Scope with type parameters for ${receiverClassDescriptor.getName()}"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
receiverClassDescriptor.getTypeConstructor().getParameters().forEach { addClassifierDescriptor(it) }
|
||||||
|
changeLockLevel(WritableScope.LockLevel.READING)
|
||||||
|
}
|
||||||
|
|
||||||
|
val projections = receiverClassDescriptor.getTypeConstructor().getParameters()
|
||||||
|
.map { TypeProjectionImpl(it.getDefaultType()) }
|
||||||
|
val memberScope = receiverClassDescriptor.getMemberScope(projections)
|
||||||
|
|
||||||
|
return ChainedScope(
|
||||||
|
receiverClassDescriptor,
|
||||||
|
"Classifier resolution scope: ${receiverClassDescriptor.getName()}",
|
||||||
|
typeParamScope,
|
||||||
|
memberScope
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun collectSubstitutionsForReceiverTypeParameters(
|
private fun collectSubstitutionsForReceiverTypeParameters(
|
||||||
receiverType: JetType?,
|
receiverType: JetType?,
|
||||||
result: MutableMap<JetType, JetType>
|
result: MutableMap<JetType, JetType>
|
||||||
@@ -715,6 +756,38 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
typeRef.replace(fullyQualifiedReceiverTypeRef)
|
typeRef.replace(fullyQualifiedReceiverTypeRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun transformToJavaMemberIfApplicable(declaration: JetNamedDeclaration): Boolean {
|
||||||
|
if (config.isExtension || receiverClassDescriptor !is JavaClassDescriptor) return false
|
||||||
|
|
||||||
|
val targetClass = DescriptorToSourceUtils.classDescriptorToDeclaration(receiverClassDescriptor) as? PsiClass
|
||||||
|
if (targetClass == null || !targetClass.canRefactor()) return false
|
||||||
|
|
||||||
|
val project = declaration.getProject()
|
||||||
|
|
||||||
|
val newJavaMethod: PsiMethod = when (declaration) {
|
||||||
|
is JetNamedFunction -> {
|
||||||
|
val method = createJavaMethod(declaration, targetClass)
|
||||||
|
|
||||||
|
val modifierList = method.getModifierList()
|
||||||
|
modifierList.setModifierProperty(PsiModifier.STATIC, false)
|
||||||
|
modifierList.setModifierProperty(PsiModifier.FINAL, false)
|
||||||
|
|
||||||
|
method
|
||||||
|
}
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
|
||||||
|
declaration.delete()
|
||||||
|
|
||||||
|
JavaCodeStyleManager.getInstance(project).shortenClassReferences(newJavaMethod);
|
||||||
|
|
||||||
|
val descriptor = OpenFileDescriptor(project, targetClass.getContainingFile().getVirtualFile())
|
||||||
|
val targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
|
||||||
|
CreateFromUsageUtils.setupEditor(newJavaMethod, targetEditor)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupEditor(declaration: JetNamedDeclaration) {
|
private fun setupEditor(declaration: JetNamedDeclaration) {
|
||||||
val caretModel = containingFileEditor.getCaretModel()
|
val caretModel = containingFileEditor.getCaretModel()
|
||||||
|
|
||||||
@@ -812,12 +885,13 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
if (callElement != null) {
|
if (callElement != null) {
|
||||||
setupCallTypeArguments(callElement, expression?.currentTypeParameters ?: Collections.emptyList())
|
setupCallTypeArguments(callElement, expression?.currentTypeParameters ?: Collections.emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
// change short type names to fully qualified ones (to be shortened below)
|
|
||||||
setupTypeReferencesForShortening(newDeclaration, elementsToShorten, parameterTypeExpressions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEditor(newDeclaration)
|
if (!transformToJavaMemberIfApplicable(newDeclaration)) {
|
||||||
|
// change short type names to fully qualified ones (to be shortened below)
|
||||||
|
setupTypeReferencesForShortening(newDeclaration, elementsToShorten, parameterTypeExpressions)
|
||||||
|
setupEditor(newDeclaration)
|
||||||
|
}
|
||||||
|
|
||||||
onFinish()
|
onFinish()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,9 +75,18 @@ import org.jetbrains.kotlin.psi.psiUtil.parents
|
|||||||
import com.intellij.refactoring.util.RefactoringUIUtil
|
import com.intellij.refactoring.util.RefactoringUIUtil
|
||||||
import com.intellij.psi.PsiMember
|
import com.intellij.psi.PsiMember
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor
|
||||||
|
import com.intellij.psi.PsiElementFactory
|
||||||
|
import com.intellij.psi.PsiModifier
|
||||||
|
import com.intellij.psi.PsiTypeParameterList
|
||||||
|
import com.intellij.refactoring.changeSignature.ChangeSignatureUtil
|
||||||
|
import com.intellij.psi.PsiModifierList
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
|
import com.intellij.lang.java.JavaLanguage
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
|
||||||
|
|
||||||
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
|
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
|
||||||
val data = getCopyableUserData(key)
|
val data = getCopyableUserData(key)
|
||||||
@@ -410,12 +419,72 @@ public fun comparePossiblyOverridingDescriptors(currentDescriptor: DeclarationDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun PsiElement.canRefactor(): Boolean {
|
public fun PsiElement.canRefactor(): Boolean {
|
||||||
return when (this) {
|
return when {
|
||||||
is PsiPackage ->
|
this is PsiPackage ->
|
||||||
getDirectories().any { it.canRefactor() }
|
getDirectories().any { it.canRefactor() }
|
||||||
is JetElement, is PsiDirectory ->
|
this is JetElement,
|
||||||
|
this is PsiMember && getLanguage() == JavaLanguage.INSTANCE,
|
||||||
|
this is PsiDirectory ->
|
||||||
isWritable() && ProjectRootsUtil.isInProjectSource(this)
|
isWritable() && ProjectRootsUtil.isInProjectSource(this)
|
||||||
else ->
|
else ->
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun copyModifierListItems(from: PsiModifierList, to: PsiModifierList, withPsiModifiers: Boolean = true) {
|
||||||
|
if (withPsiModifiers) {
|
||||||
|
for (modifier in PsiModifier.MODIFIERS) {
|
||||||
|
if (from.hasExplicitModifier(modifier)) {
|
||||||
|
to.setModifierProperty(modifier, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (annotation in from.getAnnotations()) {
|
||||||
|
to.addAnnotation(annotation.getQualifiedName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun createJavaMethod(function: JetNamedFunction, targetClass: PsiClass): PsiMethod {
|
||||||
|
val template = LightClassUtil.getLightClassMethod(function)
|
||||||
|
?: throw AssertionError("Can't generate light method: ${JetPsiUtil.getElementTextWithContext(function)}")
|
||||||
|
|
||||||
|
val factory = PsiElementFactory.SERVICE.getInstance(template.getProject())
|
||||||
|
val method = targetClass.add(factory.createMethod(template.getName(), template.getReturnType())) as PsiMethod
|
||||||
|
|
||||||
|
copyModifierListItems(template.getModifierList(), method.getModifierList())
|
||||||
|
|
||||||
|
val templateTypeParamList = template.getTypeParameterList()
|
||||||
|
if (templateTypeParamList != null) {
|
||||||
|
val targetTypeParamList = method.addAfter(factory.createTypeParameterList(), method.getModifierList()) as PsiTypeParameterList
|
||||||
|
val newTypeParams = templateTypeParamList.getTypeParameters()
|
||||||
|
.map { factory.createTypeParameter(it.getName(), it.getExtendsList().getReferencedTypes()) }
|
||||||
|
ChangeSignatureUtil.synchronizeList(
|
||||||
|
targetTypeParamList,
|
||||||
|
newTypeParams,
|
||||||
|
{ it.getTypeParameters().toList() },
|
||||||
|
BooleanArray(newTypeParams.size())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetParamList = method.getParameterList()
|
||||||
|
val newParams = template.getParameterList().getParameters().map {
|
||||||
|
val param = factory.createParameter(it.getName(), it.getType())
|
||||||
|
copyModifierListItems(it.getModifierList(), param.getModifierList())
|
||||||
|
param
|
||||||
|
}
|
||||||
|
ChangeSignatureUtil.synchronizeList(
|
||||||
|
targetParamList,
|
||||||
|
newParams,
|
||||||
|
{ it.getParameters().toList() },
|
||||||
|
BooleanArray(newParams.size())
|
||||||
|
)
|
||||||
|
|
||||||
|
if (template.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT) || targetClass.isInterface()) {
|
||||||
|
method.getBody().delete()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CreateFromUsageUtils.setupMethodBody(method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return method
|
||||||
|
}
|
||||||
|
|||||||
+1
@@ -1,5 +1,6 @@
|
|||||||
// "Create class 'Foo'" "false"
|
// "Create class 'Foo'" "false"
|
||||||
// ACTION: Create extension function 'Foo'
|
// ACTION: Create extension function 'Foo'
|
||||||
|
// ACTION: Create function 'Foo'
|
||||||
// ACTION: Convert to expression body
|
// ACTION: Convert to expression body
|
||||||
// ERROR: Unresolved reference: Foo
|
// ERROR: Unresolved reference: Foo
|
||||||
|
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create extension function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int {
|
||||||
|
return A().foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A.foo(): Int {
|
||||||
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create extension function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int {
|
||||||
|
return A().<caret>foo()
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create extension function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int? {
|
||||||
|
return A().foo(1, "2")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A.foo(i: Int, s: String): Int? {
|
||||||
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create extension function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int? {
|
||||||
|
return A().<caret>foo(1, "2")
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// "Create function 'foo'" "false"
|
||||||
|
// ACTION: Convert to expression body
|
||||||
|
// ACTION: Create extension function 'foo'
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int {
|
||||||
|
return A().<caret>foo()
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
<T, U> U foo(U u, T t);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Create function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(a: A): Int? {
|
||||||
|
return a.foo<String, Int>(1, "2")
|
||||||
|
}
|
||||||
|
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(a: A): Int? {
|
||||||
|
return a.<caret>foo<String, Int>(1, "2")
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
interface A {
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Integer foo(int i, @NotNull String s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
// "Create extension function 'foo'" "true"
|
// "Create function 'foo'" "true"
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
fun test(): Int {
|
fun test(): Int? {
|
||||||
return A().foo(1, "2")
|
return A().foo(1, "2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun A.foo(i: Int, s: String): Int {
|
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
// "Create extension function 'foo'" "true"
|
// "Create function 'foo'" "true"
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
fun test(): Int {
|
fun test(): Int? {
|
||||||
return A().<caret>foo(1, "2")
|
return A().<caret>foo(1, "2")
|
||||||
}
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
|
||||||
|
public <T, U> U foo(U u, T t) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// "Create function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int {
|
||||||
|
return A().foo<String, Int>(1, "2")
|
||||||
|
}
|
||||||
|
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create function 'foo'" "true"
|
||||||
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
fun test(): Int {
|
||||||
|
return A().<caret>foo<String, Int>(1, "2")
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -319,12 +319,42 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionFunOnGroovyType.before.Main.kt")
|
||||||
|
public void testExtensionFunOnGroovyType() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/extensionFunOnGroovyType.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionFunOnJavaType.before.Main.kt")
|
||||||
|
public void testExtensionFunOnJavaType() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/extensionFunOnJavaType.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funOnGroovyType.before.Main.kt")
|
||||||
|
public void testFunOnGroovyType() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnGroovyType.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funOnJavaInterface.before.Main.kt")
|
||||||
|
public void testFunOnJavaInterface() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaInterface.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("funOnJavaType.before.Main.kt")
|
@TestMetadata("funOnJavaType.before.Main.kt")
|
||||||
public void testFunOnJavaType() throws Exception {
|
public void testFunOnJavaType() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt");
|
||||||
doTestWithExtraFile(fileName);
|
doTestWithExtraFile(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericFunOnJavaType.before.Main.kt")
|
||||||
|
public void testGenericFunOnJavaType() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/genericFunOnJavaType.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user