Introduce Property: Forbid lazy properties/properties with initializers in traits
This commit is contained in:
+14
-7
@@ -16,33 +16,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine
|
package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine
|
||||||
|
|
||||||
import org.jetbrains.kotlin.types.JetType
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status
|
||||||
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle
|
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import org.jetbrains.kotlin.types.CommonSupertypes
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.*
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.*
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
|
||||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange
|
import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.idea.util.isUnit
|
import org.jetbrains.kotlin.idea.util.isUnit
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
|
|
||||||
trait Parameter {
|
trait Parameter {
|
||||||
val argumentText: String
|
val argumentText: String
|
||||||
@@ -310,7 +307,10 @@ enum class ExtractionTarget(val name: String) {
|
|||||||
|
|
||||||
PROPERTY_WITH_INITIALIZER : ExtractionTarget("property with initializer") {
|
PROPERTY_WITH_INITIALIZER : ExtractionTarget("property with initializer") {
|
||||||
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
return checkSignatureAndParent(descriptor) && checkSimpleControlFlow(descriptor) && checkSimpleBody(descriptor)
|
return checkSignatureAndParent(descriptor)
|
||||||
|
&& checkSimpleControlFlow(descriptor)
|
||||||
|
&& checkSimpleBody(descriptor)
|
||||||
|
&& checkNotTrait(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,13 +322,20 @@ enum class ExtractionTarget(val name: String) {
|
|||||||
|
|
||||||
LAZY_PROPERTY : ExtractionTarget("lazy property") {
|
LAZY_PROPERTY : ExtractionTarget("lazy property") {
|
||||||
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
return checkSignatureAndParent(descriptor) && checkSimpleControlFlow(descriptor)
|
return checkSignatureAndParent(descriptor)
|
||||||
|
&& checkSimpleControlFlow(descriptor)
|
||||||
|
&& checkNotTrait(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean
|
abstract fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean
|
||||||
|
|
||||||
class object {
|
class object {
|
||||||
|
fun checkNotTrait(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
|
val parent = descriptor.extractionData.targetSibling.getStrictParentOfType<JetDeclaration>()
|
||||||
|
return !(parent is JetClass && parent.isTrait())
|
||||||
|
}
|
||||||
|
|
||||||
fun checkSimpleBody(descriptor: ExtractableCodeDescriptor): Boolean {
|
fun checkSimpleBody(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
val expression = descriptor.extractionData.getExpressions().singleOrNull()
|
val expression = descriptor.extractionData.getExpressions().singleOrNull()
|
||||||
return expression != null && expression !is JetDeclaration && expression !is JetBlockExpression
|
return expression != null && expression !is JetDeclaration && expression !is JetBlockExpression
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// EXTRACTION_TARGET: lazy property
|
||||||
|
|
||||||
|
trait T {
|
||||||
|
fun foo(): Int = <selection>1</selection>
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Can't generate lazy property: 1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// EXTRACTION_TARGET: property with getter
|
||||||
|
trait T {
|
||||||
|
fun foo(): Int {
|
||||||
|
return <selection>1</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// EXTRACTION_TARGET: property with getter
|
||||||
|
trait T {
|
||||||
|
private val i: Int
|
||||||
|
get() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): Int {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// EXTRACTION_TARGET: property with initializer
|
||||||
|
|
||||||
|
trait T {
|
||||||
|
fun foo(): Int = <selection>1</selection>
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Can't generate property with initializer: 1
|
||||||
+18
@@ -1947,6 +1947,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
|||||||
doIntroducePropertyTest(fileName);
|
doIntroducePropertyTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extractLazyToTrait.kt")
|
||||||
|
public void testExtractLazyToTrait() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractLazyToTrait.kt");
|
||||||
|
doIntroducePropertyTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extractLazyWithBlock.kt")
|
@TestMetadata("extractLazyWithBlock.kt")
|
||||||
public void testExtractLazyWithBlock() throws Exception {
|
public void testExtractLazyWithBlock() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractLazyWithBlock.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractLazyWithBlock.kt");
|
||||||
@@ -2007,6 +2013,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
|||||||
doIntroducePropertyTest(fileName);
|
doIntroducePropertyTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extractWithGetterToTrait.kt")
|
||||||
|
public void testExtractWithGetterToTrait() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithGetterToTrait.kt");
|
||||||
|
doIntroducePropertyTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extractWithInitializerAndBlock.kt")
|
@TestMetadata("extractWithInitializerAndBlock.kt")
|
||||||
public void testExtractWithInitializerAndBlock() throws Exception {
|
public void testExtractWithInitializerAndBlock() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithInitializerAndBlock.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithInitializerAndBlock.kt");
|
||||||
@@ -2043,6 +2055,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
|||||||
doIntroducePropertyTest(fileName);
|
doIntroducePropertyTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extractWithInitializerToTrait.kt")
|
||||||
|
public void testExtractWithInitializerToTrait() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithInitializerToTrait.kt");
|
||||||
|
doIntroducePropertyTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extractWithParams.kt")
|
@TestMetadata("extractWithParams.kt")
|
||||||
public void testExtractWithParams() throws Exception {
|
public void testExtractWithParams() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithParams.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/extractWithParams.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user