Correct handling of erroneous code during code extraction
This commit is contained in:
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ThrowExceptionInst
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
@@ -287,20 +286,21 @@ fun Pseudocode.getElementValuesRecursively(element: KtElement): List<PseudoValue
|
||||
return results
|
||||
}
|
||||
|
||||
fun KtElement.getContainingPseudocode(context: BindingContext): Pseudocode? {
|
||||
val pseudocodeDeclaration =
|
||||
PsiTreeUtil.getParentOfType(this, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtScript::class.java)
|
||||
?: getNonStrictParentOfType<KtProperty>()
|
||||
?: return null
|
||||
val KtElement.containingDeclarationForPseudocode: KtDeclaration?
|
||||
get() = PsiTreeUtil.getParentOfType(this, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtScript::class.java)
|
||||
?: getNonStrictParentOfType<KtProperty>()
|
||||
|
||||
val enclosingPseudocodeDeclaration = (pseudocodeDeclaration as? KtFunctionLiteral)?.let {
|
||||
fun KtDeclaration.getContainingPseudocode(context: BindingContext): Pseudocode? {
|
||||
val enclosingPseudocodeDeclaration = (this as? KtFunctionLiteral)?.let {
|
||||
it.parents.firstOrNull { it is KtDeclaration && it !is KtFunctionLiteral } as? KtDeclaration
|
||||
} ?: pseudocodeDeclaration
|
||||
} ?: this
|
||||
|
||||
val enclosingPseudocode = PseudocodeUtil.generatePseudocode(enclosingPseudocodeDeclaration, context)
|
||||
return enclosingPseudocode.getPseudocodeByElement(pseudocodeDeclaration)
|
||||
return enclosingPseudocode.getPseudocodeByElement(this)
|
||||
}
|
||||
|
||||
fun KtElement.getContainingPseudocode(context: BindingContext) = containingDeclarationForPseudocode?.getContainingPseudocode(context)
|
||||
|
||||
fun Pseudocode.getPseudocodeByElement(element: KtElement): Pseudocode? {
|
||||
if (correspondingElement == element) return this
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ fun getFunctionForExtractedFragment(
|
||||
val message = when(errorMessage) {
|
||||
ErrorMessage.NO_EXPRESSION -> "Cannot perform an action without an expression"
|
||||
ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.name}:$breakpointLine"
|
||||
ErrorMessage.SYNTAX_ERRORS -> "Cannot perform an action due to erroneous code"
|
||||
ErrorMessage.SUPER_CALL -> "Cannot perform an action for expression with super call"
|
||||
ErrorMessage.DENOTABLE_TYPES -> "Cannot perform an action because following types are unavailable from debugger scope"
|
||||
ErrorMessage.ERROR_TYPES -> "Cannot perform an action because this code fragment contains erroneous types"
|
||||
|
||||
@@ -6,6 +6,7 @@ introduce.property=Introduce Property
|
||||
introduce.parameter=Introduce Parameter
|
||||
cannot.refactor.no.container=Cannot refactor in this place
|
||||
cannot.refactor.no.expression=Cannot perform refactoring without an expression
|
||||
cannot.refactor.syntax.errors=Cannot refactor due to erroneous code
|
||||
cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type
|
||||
cannot.refactor.package.expression=Cannot introduce package reference
|
||||
extract.function=Extract Function
|
||||
|
||||
+2
@@ -505,6 +505,7 @@ class AnalysisResult (
|
||||
enum class ErrorMessage {
|
||||
NO_EXPRESSION,
|
||||
NO_CONTAINER,
|
||||
SYNTAX_ERRORS,
|
||||
SUPER_CALL,
|
||||
DENOTABLE_TYPES,
|
||||
ERROR_TYPES,
|
||||
@@ -526,6 +527,7 @@ class AnalysisResult (
|
||||
when (this) {
|
||||
NO_EXPRESSION -> "cannot.refactor.no.expression"
|
||||
NO_CONTAINER -> "cannot.refactor.no.container"
|
||||
SYNTAX_ERRORS -> "cannot.refactor.syntax.errors"
|
||||
SUPER_CALL -> "cannot.extract.super.call"
|
||||
DENOTABLE_TYPES -> "parameter.types.are.not.denotable"
|
||||
ERROR_TYPES -> "error.types.in.generated.function"
|
||||
|
||||
+3
-1
@@ -624,7 +624,9 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
|
||||
val bindingContext = bindingContext ?: return noContainerError
|
||||
|
||||
val pseudocode = commonParent.getContainingPseudocode(bindingContext) ?: return noContainerError
|
||||
val declaration = commonParent.containingDeclarationForPseudocode ?: return noContainerError
|
||||
val pseudocode = declaration.getContainingPseudocode(bindingContext)
|
||||
?: return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.SYNTAX_ERRORS))
|
||||
val localInstructions = getLocalInstructions(pseudocode)
|
||||
|
||||
val modifiedVarDescriptorsWithExpressions = localInstructions.getModifiedVarDescriptors(bindingContext)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// EXTRACTION_TARGET: property with getter
|
||||
|
||||
fun doSomethingStrangeWithCollection(collection: Collection<String>): Collection<String>? {
|
||||
val groupsByLength = collection.groupBy { s -> { s.length } }
|
||||
|
||||
val maximumSizeOfGroup = groupsByLength.values.maxBy { it.size }.
|
||||
return groupsByLength.values.firstOrNull { group -> {<selection>group.size == maximumSizeOfGroup</selection>} }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Cannot refactor due to erroneous code
|
||||
+6
@@ -3124,6 +3124,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
||||
doIntroducePropertyTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("syntaxErrors.kt")
|
||||
public void testSyntaxErrors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/syntaxErrors.kt");
|
||||
doIntroducePropertyTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterNotResolvableInTargetScope.kt")
|
||||
public void testTypeParameterNotResolvableInTargetScope() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceProperty/typeParameterNotResolvableInTargetScope.kt");
|
||||
|
||||
Reference in New Issue
Block a user