Prevent expression selector from selecting just a label

Previously, extract variable could act on e.g. 'break@outerLoop' and
extract the label, leading into nonsensical 'val x = @outerLoop'.
Prevent JetRefactoringUtil.selectExpression from returning label
expressions to fix this.

 #KT-4515 Fixed
This commit is contained in:
Tuomas Tynkkynen
2014-02-06 09:56:51 -08:00
committed by Nikolay Krasko
parent 998d2c5ec8
commit 7a2321460d
8 changed files with 53 additions and 6 deletions
@@ -1042,4 +1042,9 @@ public class JetPsiUtil {
expression;
return (JetToken) elementType;
}
public static boolean isLabelIdentifierExpression(PsiElement element) {
return element instanceof JetSimpleNameExpression &&
((JetSimpleNameExpression) element).getReferencedNameElementType() == JetTokens.LABEL_IDENTIFIER;
}
}
@@ -13,10 +13,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetBlockExpression;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.renderer.DescriptorRenderer;
@@ -35,7 +32,13 @@ public class CodeInsightUtils {
else if (!(element instanceof JetExpression)) {
return null;
}
else if (element instanceof JetBlockExpression) {
// For cases like 'this@outerClass', don't return the label part
if (JetPsiUtil.isLabelIdentifierExpression(element)) {
element = PsiTreeUtil.getParentOfType(element, JetExpression.class);
}
if (element instanceof JetBlockExpression) {
List<JetElement> statements = ((JetBlockExpression) element).getStatements();
if (statements.size() == 1) {
JetElement elem = statements.get(0);
@@ -405,7 +405,11 @@ public class JetRefactoringUtil {
&& !(element instanceof JetClassBody)) {
if (element instanceof JetExpression && !(element instanceof JetStatementExpression)) {
boolean addExpression = true;
if (element.getParent() instanceof JetQualifiedExpression) {
if (JetPsiUtil.isLabelIdentifierExpression(element)) {
addExpression = false;
}
else if (element.getParent() instanceof JetQualifiedExpression) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) element.getParent();
if (qualifiedExpression.getReceiverExpression() != element) {
addExpression = false;
@@ -0,0 +1,7 @@
fun f() {
@loop while (true) {
break@lo<selection>o</selection>p
}
}
// KT-4515: Extract variable can attempt to extract a label from a labelled statement.
/* break@loop */
@@ -0,0 +1,6 @@
class Foo() {
val s = this@F<selection>o</selection>o.toString()
}
// KT-4515: Extract variable can attempt to extract a label from a labelled statement.
/* this@Foo */
@@ -0,0 +1,7 @@
fun f() {
@loop while (true) {
break@lo<caret>op
}
}
// KT-4515: Extract variable can attempt to extract a label from a labelled statement.
/* */
@@ -41,6 +41,16 @@ public class ExpressionSelectionTestGenerated extends AbstractExpressionSelectio
doTestExpressionSelection("idea/testData/expressionSelection/binaryExpr.kt");
}
@TestMetadata("labelledStatement.kt")
public void testLabelledStatement() throws Exception {
doTestExpressionSelection("idea/testData/expressionSelection/labelledStatement.kt");
}
@TestMetadata("labelledThis.kt")
public void testLabelledThis() throws Exception {
doTestExpressionSelection("idea/testData/expressionSelection/labelledThis.kt");
}
@TestMetadata("noExpression.kt")
public void testNoExpression() throws Exception {
doTestExpressionSelection("idea/testData/expressionSelection/noExpression.kt");
@@ -36,6 +36,11 @@ public class SmartSelectionTestGenerated extends AbstractSmartSelectionTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/smartSelection"), Pattern.compile("^([^\\.]+)\\.kt$"), true);
}
@TestMetadata("labelledStatement.kt")
public void testLabelledStatement() throws Exception {
doTestSmartSelection("idea/testData/smartSelection/labelledStatement.kt");
}
@TestMetadata("labelledThis.kt")
public void testLabelledThis() throws Exception {
doTestSmartSelection("idea/testData/smartSelection/labelledThis.kt");