Used ConvertMemberToExtensionIntention in MigrateExternalExtensionFix instead of manually creating extension method
This commit is contained in:
+22
-12
@@ -54,6 +54,27 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
//TODO: local class
|
||||
|
||||
override fun applyTo(element: KtCallableDeclaration, editor: Editor?) {
|
||||
val (extension, bodyToSelect) = createExtensionCallableAndPrepareBodyToSelect(element)
|
||||
|
||||
editor?.apply {
|
||||
unblockDocument()
|
||||
|
||||
if (bodyToSelect != null) {
|
||||
val range = bodyToSelect!!.textRange
|
||||
moveCaret(range.startOffset, ScrollType.CENTER)
|
||||
selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||
}
|
||||
else {
|
||||
moveCaret(extension.textOffset, ScrollType.CENTER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun convert(element: KtCallableDeclaration): KtCallableDeclaration {
|
||||
return createExtensionCallableAndPrepareBodyToSelect(element).first
|
||||
}
|
||||
|
||||
private fun createExtensionCallableAndPrepareBodyToSelect(element: KtCallableDeclaration): Pair<KtCallableDeclaration, KtExpression?> {
|
||||
val descriptor = element.resolveToDescriptor()
|
||||
val containingClass = descriptor.containingDeclaration as ClassDescriptor
|
||||
|
||||
@@ -179,18 +200,7 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
}
|
||||
}
|
||||
|
||||
editor?.apply {
|
||||
unblockDocument()
|
||||
|
||||
if (bodyToSelect != null) {
|
||||
val range = bodyToSelect!!.textRange
|
||||
moveCaret(range.startOffset, ScrollType.CENTER)
|
||||
selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||
}
|
||||
else {
|
||||
moveCaret(extension.textOffset, ScrollType.CENTER)
|
||||
}
|
||||
}
|
||||
return extension to bodyToSelect
|
||||
}
|
||||
|
||||
private fun newTypeParameterList(member: KtCallableDeclaration): KtTypeParameterList? {
|
||||
|
||||
+5
-62
@@ -21,19 +21,16 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.checkAnnotationName
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.setReceiverType
|
||||
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.declarations.ConvertMemberToExtensionIntention
|
||||
import org.jetbrains.kotlin.idea.project.builtIns
|
||||
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.idea.util.addAnnotation
|
||||
import org.jetbrains.kotlin.js.PredefinedAnnotation
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs
|
||||
@@ -67,24 +64,19 @@ class MigrateExternalExtensionFix(declaration: KtNamedDeclaration)
|
||||
}
|
||||
|
||||
private fun fixNativeClass(containingClass: KtClassOrObject, project: Project, editor: Editor?, file: KtFile) {
|
||||
val membersToFix = containingClass.declarations.filterIsInstance<KtNamedDeclaration>().filter { isMemberDeclaration(it) }. map {
|
||||
val membersToFix = containingClass.declarations.filterIsInstance<KtCallableDeclaration>().filter { isMemberDeclaration(it) }. map {
|
||||
it to fetchJsNativeAnnotations(it)
|
||||
}.filter {
|
||||
it.second.annotations.isNotEmpty()
|
||||
}
|
||||
|
||||
var anchor: PsiElement = containingClass
|
||||
membersToFix.forEach { (memberDeclaration, annotations) ->
|
||||
membersToFix.asReversed().forEach { (memberDeclaration, annotations) ->
|
||||
if (annotations.nativeAnnotation != null && !annotations.isGetter && !annotations.isSetter && !annotations.isInvoke) {
|
||||
convertNativeAnnotationToJsName(memberDeclaration, annotations)
|
||||
annotations.nativeAnnotation.delete()
|
||||
} else {
|
||||
// TODO: find references
|
||||
createExtensionDeclaration(memberDeclaration, project, anchor)?.let { externalDeclaration ->
|
||||
memberDeclaration.delete()
|
||||
fixExtensionMemberDeclaration(externalDeclaration, project, null, file)
|
||||
anchor = externalDeclaration
|
||||
}
|
||||
val externalDeclaration = ConvertMemberToExtensionIntention().convert(memberDeclaration)
|
||||
fixExtensionMemberDeclaration(externalDeclaration, project, null, file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,55 +85,6 @@ class MigrateExternalExtensionFix(declaration: KtNamedDeclaration)
|
||||
fixAnnotations(containingClass, classAnnotations, null)
|
||||
}
|
||||
|
||||
private fun createExtensionDeclaration(declaration: KtNamedDeclaration, project: Project, anchor: PsiElement): KtNamedDeclaration? {
|
||||
val containingClass = declaration.containingClassOrObject ?: return null
|
||||
val builder = KtPsiFactory.CallableBuilder(if (declaration is KtNamedFunction) KtPsiFactory.CallableBuilder.Target.FUNCTION else KtPsiFactory.CallableBuilder.Target.READ_ONLY_PROPERTY)
|
||||
|
||||
// modifiers
|
||||
declaration.annotationEntries.forEach {
|
||||
builder.modifier(it.text)
|
||||
}
|
||||
|
||||
// type parameters
|
||||
builder.typeParams(containingClass.typeParameters.union((declaration as? KtTypeParameterListOwner)?.typeParameters ?: emptyList()).map { it.text })
|
||||
|
||||
// receiver
|
||||
builder.receiver(containingClass.name ?: "XXX")
|
||||
|
||||
// name
|
||||
builder.name(declaration.nameAsSafeName.identifier)
|
||||
|
||||
// parameters
|
||||
(declaration as? KtCallableDeclaration)?.valueParameters?.forEach {
|
||||
builder.param(it.nameAsSafeName.identifier, it.typeReference?.text ?: "XXX", it.defaultValue?.text)
|
||||
}
|
||||
|
||||
// return type
|
||||
val returnTypeReference = declaration.getReturnTypeReference()
|
||||
if (returnTypeReference != null)
|
||||
builder.returnType(returnTypeReference.text)
|
||||
else
|
||||
builder.noReturnType()
|
||||
|
||||
// body
|
||||
(declaration as? KtDeclarationWithBody)?.bodyExpression?.let {
|
||||
builder.blockBody(it.text)
|
||||
}
|
||||
|
||||
// Create function etc
|
||||
var newFunctionText = builder.asString()
|
||||
val psiFactory = KtPsiFactory(project)
|
||||
val newFunction = psiFactory.createFunction(newFunctionText)
|
||||
|
||||
val parent = anchor.parent
|
||||
val result = parent.addAfter(newFunction, anchor) as KtCallableDeclaration
|
||||
parent.addBefore(psiFactory.createNewLine(2), result)
|
||||
|
||||
// fix receiver type
|
||||
result.setReceiverType((containingClass.resolveToDescriptor(BodyResolveMode.PARTIAL) as ClassDescriptor).defaultType)
|
||||
return result
|
||||
}
|
||||
|
||||
private data class JsNativeAnnotations(val annotations: List<KtAnnotationEntry>, val nativeAnnotation: KtAnnotationEntry?, val isGetter: Boolean, val isSetter: Boolean, val isInvoke: Boolean)
|
||||
|
||||
private fun fetchJsNativeAnnotations(declaration: KtNamedDeclaration) : JsNativeAnnotations {
|
||||
|
||||
@@ -20,6 +20,6 @@ inline fun B.bar(a: B) {
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun <T> B.exp(t: T) {
|
||||
inline fun<T> B.exp(t: T) {
|
||||
asDynamic()(t)
|
||||
}
|
||||
@@ -20,6 +20,6 @@ inline fun B.bar(a: B) {
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun <T> B.exp(t: T) {
|
||||
inline fun<T> B.exp(t: T) {
|
||||
asDynamic()(t)
|
||||
}
|
||||
@@ -20,6 +20,6 @@ inline fun B.bar(a: B) {
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun <T> B.exp(t: T) {
|
||||
inline fun<T> B.exp(t: T) {
|
||||
asDynamic()(t)
|
||||
}
|
||||
+1
-1
@@ -5,6 +5,6 @@ external class B {
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun <T> B.exp(t: T) {
|
||||
inline fun<T> B.exp(t: T) {
|
||||
asDynamic()(t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user