ReconstructTypeInCastOrIsIntention - refactored
This commit is contained in:
@@ -412,8 +412,6 @@ hierarchy.legend.member.defined.in.superclass=Member is not defined in the class
|
|||||||
hierarchy.legend.member.should.be.defined=Member should be defined since the class is not abstract
|
hierarchy.legend.member.should.be.defined=Member should be defined since the class is not abstract
|
||||||
|
|
||||||
convert.to.extension=Convert to extension
|
convert.to.extension=Convert to extension
|
||||||
replace.by.reconstructed.type.family.name=Replace by Reconstructed Type
|
|
||||||
replace.by.reconstructed.type=Replace by ''{0}''
|
|
||||||
|
|
||||||
suppress.warnings.family=Suppress Warnings
|
suppress.warnings.family=Suppress Warnings
|
||||||
suppress.warning.for=Suppress ''{0}'' for {1} {2}
|
suppress.warning.for=Suppress ''{0}'' for {1} {2}
|
||||||
|
|||||||
@@ -709,7 +709,7 @@
|
|||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
<intentionAction>
|
<intentionAction>
|
||||||
<className>org.jetbrains.kotlin.idea.intentions.ReconstructTypeInCastOrIsAction</className>
|
<className>org.jetbrains.kotlin.idea.intentions.ReconstructTypeInCastOrIsIntention</className>
|
||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.intentions
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import org.jetbrains.kotlin.idea.JetBundle
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
import org.jetbrains.kotlin.types.JetType
|
|
||||||
|
|
||||||
public class ReconstructTypeInCastOrIsAction : PsiElementBaseIntentionAction() {
|
|
||||||
override fun getFamilyName(): String {
|
|
||||||
return JetBundle.message("replace.by.reconstructed.type.family.name")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
|
|
||||||
val typeRef = PsiTreeUtil.getTopmostParentOfType<JetTypeReference>(element, javaClass<JetTypeReference>())
|
|
||||||
assert(typeRef != null) { "Must be checked by isAvailable(): " + element }
|
|
||||||
|
|
||||||
val type = getReconstructedType(typeRef)
|
|
||||||
val newType = JetPsiFactory(typeRef).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
|
|
||||||
val replaced = typeRef!!.replace(newType) as JetTypeReference
|
|
||||||
ShortenReferences.DEFAULT.process(replaced)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
|
|
||||||
val typeRef = PsiTreeUtil.getTopmostParentOfType<JetTypeReference>(element, javaClass<JetTypeReference>())
|
|
||||||
if (typeRef == null) return false
|
|
||||||
|
|
||||||
// Only user types (like Foo) are interesting
|
|
||||||
val typeElement = typeRef.getTypeElement()
|
|
||||||
if (typeElement !is JetUserType) return false
|
|
||||||
|
|
||||||
// If there are generic arguments already, there's nothing to reconstruct
|
|
||||||
if (!typeElement.getTypeArguments().isEmpty()) return false
|
|
||||||
|
|
||||||
// We must be on the RHS of as/as?/is/!is or inside an is/!is-condition in when()
|
|
||||||
val outerExpression = PsiTreeUtil.getParentOfType<JetExpression>(typeRef, javaClass<JetExpression>())
|
|
||||||
if (outerExpression !is JetBinaryExpressionWithTypeRHS) {
|
|
||||||
val outerIsCondition = PsiTreeUtil.getParentOfType<JetWhenConditionIsPattern>(typeRef, javaClass<JetWhenConditionIsPattern>())
|
|
||||||
if (outerIsCondition == null) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val type = getReconstructedType(typeRef)
|
|
||||||
if (type == null || type.isError()) return false
|
|
||||||
|
|
||||||
// No type parameters expected => nothing to reconstruct
|
|
||||||
if (type.getConstructor().getParameters().isEmpty()) return false
|
|
||||||
|
|
||||||
setText(JetBundle.message("replace.by.reconstructed.type", type))
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getReconstructedType(typeRef: JetTypeReference): JetType? {
|
|
||||||
return typeRef.analyze(BodyResolveMode.FULL).get<JetTypeReference, JetType>(BindingContext.TYPE, typeRef)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||||
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
|
||||||
|
public class ReconstructTypeInCastOrIsIntention : JetSelfTargetingOffsetIndependentIntention<JetTypeReference>(javaClass(), "Replace by reconstructed type") {
|
||||||
|
override fun isApplicableTo(element: JetTypeReference): Boolean {
|
||||||
|
// Only user types (like Foo) are interesting
|
||||||
|
val typeElement = element.getTypeElement() as? JetUserType ?: return false
|
||||||
|
|
||||||
|
// If there are generic arguments already, there's nothing to reconstruct
|
||||||
|
if (typeElement.getTypeArguments().isNotEmpty()) return false
|
||||||
|
|
||||||
|
// We must be on the RHS of as/as?/is/!is or inside an is/!is-condition in when()
|
||||||
|
val expression = element.getParentOfType<JetExpression>(true)
|
||||||
|
if (expression !is JetBinaryExpressionWithTypeRHS && element.getParentOfType<JetWhenConditionIsPattern>(true) == null) return false
|
||||||
|
|
||||||
|
val type = getReconstructedType(element)
|
||||||
|
if (type == null || type.isError()) return false
|
||||||
|
|
||||||
|
// No type parameters expected => nothing to reconstruct
|
||||||
|
if (type.getConstructor().getParameters().isEmpty()) return false
|
||||||
|
|
||||||
|
val typePresentation = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
|
||||||
|
setText("Replace by '$typePresentation'")
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyTo(element: JetTypeReference, editor: Editor) {
|
||||||
|
val type = getReconstructedType(element)!!
|
||||||
|
val newType = JetPsiFactory(element).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
|
||||||
|
ShortenReferences.DEFAULT.process(element.replaced(newType))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getReconstructedType(typeRef: JetTypeReference): JetType? {
|
||||||
|
return typeRef.analyze().get(BindingContext.TYPE, typeRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
org.jetbrains.kotlin.idea.intentions.ReconstructTypeInCastOrIsAction
|
org.jetbrains.kotlin.idea.intentions.ReconstructTypeInCastOrIsIntention
|
||||||
|
|||||||
Reference in New Issue
Block a user