Create from Usage: Suggest synthetic function classes as extension receivers
This commit is contained in:
+6
-1
@@ -35,6 +35,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.getContainingPseudocode
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -435,7 +436,11 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
else null
|
||||
|
||||
val ownerTypeString = if (isExtension) "${receiverTypeCandidate!!.renderedType!!}." else ""
|
||||
val ownerTypeString = if (isExtension) {
|
||||
val renderedType = receiverTypeCandidate!!.renderedType!!
|
||||
val isFunctionType = receiverTypeCandidate.theType.constructor.declarationDescriptor is FunctionClassDescriptor
|
||||
if (isFunctionType) "($renderedType)." else "$renderedType."
|
||||
} else ""
|
||||
|
||||
val classKind = (callableInfo as? PrimaryConstructorInfo)?.classInfo?.kind
|
||||
|
||||
|
||||
+14
-5
@@ -22,16 +22,16 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.chooseContainerElementIfNecessary
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.psi.JetClassBody
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import java.util.HashSet
|
||||
|
||||
@@ -61,9 +61,18 @@ public abstract class CreateCallableFromUsageFixBase<E : JetElement>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeclaration(descriptor: ClassifierDescriptor, project: Project): PsiElement? {
|
||||
if (descriptor is FunctionClassDescriptor) {
|
||||
val psiFactory = JetPsiFactory(project)
|
||||
val syntheticClass = psiFactory.createClass(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(descriptor))
|
||||
return psiFactory.createAnalyzableFile("${descriptor.name.asString()}.kt", "", element).add(syntheticClass)
|
||||
}
|
||||
return DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor)
|
||||
}
|
||||
|
||||
private fun getDeclarationIfApplicable(project: Project, candidate: TypeCandidate): PsiElement? {
|
||||
val descriptor = candidate.theType.constructor.declarationDescriptor ?: return null
|
||||
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
|
||||
val declaration = getDeclaration(descriptor, project) ?: return null
|
||||
if (declaration !is JetClassOrObject && declaration !is PsiClass) return null
|
||||
return if (isExtension || declaration.canRefactor()) declaration else null
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// "Create extension function 'bar'" "true"
|
||||
|
||||
fun foo(block: (Int) -> String) {
|
||||
block.b<caret>ar()
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
// "Create extension function 'bar'" "true"
|
||||
|
||||
fun foo(block: (Int) -> String) {
|
||||
block.bar()
|
||||
}
|
||||
|
||||
fun <P1, R> ((P1) -> R).bar() {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
@@ -1790,6 +1790,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionalTypeInReceiver.kt")
|
||||
public void testFunctionalTypeInReceiver() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/functionalTypeInReceiver.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inLambda.kt")
|
||||
public void testInLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/inLambda.kt");
|
||||
|
||||
Reference in New Issue
Block a user