diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/surroundWith/expression/KotlinExpressionSurrounder.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/surroundWith/expression/KotlinExpressionSurrounder.java
index b29300b6122..4999c001314 100644
--- a/idea/src/org/jetbrains/jet/plugin/codeInsight/surroundWith/expression/KotlinExpressionSurrounder.java
+++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/surroundWith/expression/KotlinExpressionSurrounder.java
@@ -5,10 +5,15 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
+import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
+import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
+import org.jetbrains.jet.plugin.codeInsight.surroundWith.KotlinSurrounderUtils;
public abstract class KotlinExpressionSurrounder implements Surrounder {
@@ -17,7 +22,16 @@ public abstract class KotlinExpressionSurrounder implements Surrounder {
if (elements.length != 1 || !(elements[0] instanceof JetExpression)) {
return false;
}
- return isApplicable((JetExpression) elements[0]);
+
+ JetExpression expression = (JetExpression) elements[0];
+ if (expression instanceof JetCallExpression && expression.getParent() instanceof JetQualifiedExpression) {
+ return false;
+ }
+ JetType type = KotlinSurrounderUtils.getExpressionType(expression);
+ if (type == null || type.equals(KotlinBuiltIns.getInstance().getUnitType())) {
+ return false;
+ }
+ return isApplicable(expression);
}
protected abstract boolean isApplicable(@NotNull JetExpression expression);
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/if.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/if.kt
new file mode 100644
index 00000000000..35f28de24f0
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/if.kt
@@ -0,0 +1,5 @@
+fun foo() {
+ if (1 == 2) {}
+}
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/import.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/import.kt
new file mode 100644
index 00000000000..2f245584bc0
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/import.kt
@@ -0,0 +1,3 @@
+import kotlin
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedFirst.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedFirst.kt
new file mode 100644
index 00000000000..87fa03e0a4a
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedFirst.kt
@@ -0,0 +1,3 @@
+import kotlin.io
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedSecond.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedSecond.kt
new file mode 100644
index 00000000000..f8d9373c67e
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedSecond.kt
@@ -0,0 +1,3 @@
+import kotlin.io
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/packageName.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/packageName.kt
new file mode 100644
index 00000000000..5f00584be3b
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/packageName.kt
@@ -0,0 +1,3 @@
+package foo
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterName.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterName.kt
new file mode 100644
index 00000000000..bb71058c644
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterName.kt
@@ -0,0 +1,3 @@
+fun foo(a: Int) {}
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterWithType.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterWithType.kt
new file mode 100644
index 00000000000..38689c5e77a
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterWithType.kt
@@ -0,0 +1,3 @@
+fun foo(a: Int) {}
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecond.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecond.kt
new file mode 100644
index 00000000000..09043a53fbc
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecond.kt
@@ -0,0 +1,6 @@
+fun foo() {
+ val a = ""
+ a.charAt(1)
+}
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecondWithBracket.kt b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecondWithBracket.kt
new file mode 100644
index 00000000000..39d056e01f4
--- /dev/null
+++ b/idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecondWithBracket.kt
@@ -0,0 +1,6 @@
+fun foo() {
+ val a = ""
+ a.charAt(1)
+}
+
+// IS_APPLICABLE: false
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/AbstractSurroundWithTest.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/AbstractSurroundWithTest.java
index cbb81d09e40..c7697e6b8f9 100644
--- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/AbstractSurroundWithTest.java
+++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/AbstractSurroundWithTest.java
@@ -17,15 +17,22 @@
package org.jetbrains.jet.plugin.codeInsight.surroundWith;
import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler;
+import com.intellij.lang.LanguageSurrounders;
+import com.intellij.lang.surroundWith.SurroundDescriptor;
import com.intellij.lang.surroundWith.Surrounder;
+import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.psi.PsiElement;
import com.intellij.testFramework.LightCodeInsightTestCase;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.plugin.codeInsight.surroundWith.expression.KotlinNotSurrounder;
-import org.jetbrains.jet.plugin.codeInsight.surroundWith.expression.KotlinParenthesesSurrounder;
-import org.jetbrains.jet.plugin.codeInsight.surroundWith.expression.KotlinStringTemplateSurrounder;
-import org.jetbrains.jet.plugin.codeInsight.surroundWith.expression.KotlinWhenSurrounder;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.InTextDirectivesUtils;
+import org.jetbrains.jet.plugin.codeInsight.surroundWith.expression.*;
import org.jetbrains.jet.plugin.codeInsight.surroundWith.statement.*;
+import java.io.File;
+import java.util.List;
+
public abstract class AbstractSurroundWithTest extends LightCodeInsightTestCase {
public void doTestWithIfSurrounder(String path) throws Exception {
@@ -47,7 +54,7 @@ public abstract class AbstractSurroundWithTest extends LightCodeInsightTestCase
public void doTestWithStringTemplateSurrounder(String path) throws Exception {
doTest(path, new KotlinStringTemplateSurrounder());
}
-
+
public void doTestWithWhenSurrounder(String path) throws Exception {
doTest(path, new KotlinWhenSurrounder());
}
@@ -70,10 +77,51 @@ public abstract class AbstractSurroundWithTest extends LightCodeInsightTestCase
private void doTest(String path, Surrounder surrounder) throws Exception {
configureByFile(path);
+
+ String fileText = FileUtil.loadFile(new File(path));
+ String isApplicableString = InTextDirectivesUtils.findStringWithPrefix("// IS_APPLICABLE: ", fileText);
+
+ if (isApplicableString != null) {
+ boolean isApplicableExpected = toString().equals("true");
+ PsiElement[] elementsToSurround = getElementsToSurround(surrounder);
+ assert elementsToSurround != null : "Couldn't find elements to surround";
+ assert isApplicableExpected == surrounder.isApplicable(elementsToSurround)
+ : "isApplicable() for " + surrounder.getClass() + " should return " + isApplicableExpected;
+ if (isApplicableExpected) {
+ invokeSurroundAndCheck(path, surrounder);
+ }
+ }
+ else {
+ invokeSurroundAndCheck(path, surrounder);
+ }
+ }
+
+ private void invokeSurroundAndCheck(@NotNull String path, @NotNull Surrounder surrounder) {
SurroundWithHandler.invoke(getProject(), getEditor(), getFile(), surrounder);
checkResultByFile(path + ".after");
}
+ @Nullable
+ private PsiElement[] getElementsToSurround(@NotNull Surrounder surrounder) {
+ List surroundDescriptors =
+ LanguageSurrounders.INSTANCE.allForLanguage(getFile().getViewProvider().getBaseLanguage());
+
+ String surrounderDescription = surrounder.getTemplateDescription();
+ for (SurroundDescriptor descriptor : surroundDescriptors) {
+ Surrounder[] surrounders = descriptor.getSurrounders();
+ for (Surrounder surrounderInDescriptor : surrounders) {
+ if (surrounderInDescriptor.getTemplateDescription().equals(surrounderDescription)) {
+ SelectionModel selection = getEditor().getSelectionModel();
+ PsiElement[] elements = descriptor.getElementsToSurround(
+ getFile(), selection.getSelectionStart(), selection.getSelectionEnd());
+ return elements;
+ }
+ }
+ }
+
+ return null;
+ }
+
@NotNull
@Override
protected String getTestDataPath() {
diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/SurroundWithTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/SurroundWithTestGenerated.java
index 4d696078c6d..787d0fde601 100644
--- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/SurroundWithTestGenerated.java
+++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/surroundWith/SurroundWithTestGenerated.java
@@ -142,6 +142,7 @@ public class SurroundWithTestGenerated extends AbstractSurroundWithTest {
}
@TestMetadata("idea/testData/codeInsight/surroundWith/parentheses")
+ @InnerTestClasses({Parentheses.NotApplicable.class})
public static class Parentheses extends AbstractSurroundWithTest {
public void testAllFilesPresentInParentheses() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/codeInsight/surroundWith/parentheses"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -162,6 +163,65 @@ public class SurroundWithTestGenerated extends AbstractSurroundWithTest {
doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/partOfExpr.kt");
}
+ @TestMetadata("idea/testData/codeInsight/surroundWith/parentheses/notApplicable")
+ public static class NotApplicable extends AbstractSurroundWithTest {
+ public void testAllFilesPresentInNotApplicable() throws Exception {
+ JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/codeInsight/surroundWith/parentheses/notApplicable"), Pattern.compile("^(.+)\\.kt$"), true);
+ }
+
+ @TestMetadata("if.kt")
+ public void testIf() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/if.kt");
+ }
+
+ @TestMetadata("import.kt")
+ public void testImport() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/import.kt");
+ }
+
+ @TestMetadata("importQualifiedFirst.kt")
+ public void testImportQualifiedFirst() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedFirst.kt");
+ }
+
+ @TestMetadata("importQualifiedSecond.kt")
+ public void testImportQualifiedSecond() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/importQualifiedSecond.kt");
+ }
+
+ @TestMetadata("packageName.kt")
+ public void testPackageName() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/packageName.kt");
+ }
+
+ @TestMetadata("parameterName.kt")
+ public void testParameterName() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterName.kt");
+ }
+
+ @TestMetadata("parameterWithType.kt")
+ public void testParameterWithType() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/parameterWithType.kt");
+ }
+
+ @TestMetadata("qualifiedExpressionSecond.kt")
+ public void testQualifiedExpressionSecond() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecond.kt");
+ }
+
+ @TestMetadata("qualifiedExpressionSecondWithBracket.kt")
+ public void testQualifiedExpressionSecondWithBracket() throws Exception {
+ doTestWithParenthesesSurrounder("idea/testData/codeInsight/surroundWith/parentheses/notApplicable/qualifiedExpressionSecondWithBracket.kt");
+ }
+
+ }
+
+ public static Test innerSuite() {
+ TestSuite suite = new TestSuite("Parentheses");
+ suite.addTestSuite(Parentheses.class);
+ suite.addTestSuite(NotApplicable.class);
+ return suite;
+ }
}
@TestMetadata("idea/testData/codeInsight/surroundWith/stringTemplate")
@@ -292,7 +352,7 @@ public class SurroundWithTestGenerated extends AbstractSurroundWithTest {
suite.addTestSuite(If.class);
suite.addTestSuite(IfElse.class);
suite.addTestSuite(Not.class);
- suite.addTestSuite(Parentheses.class);
+ suite.addTest(Parentheses.innerSuite());
suite.addTestSuite(StringTemplate.class);
suite.addTestSuite(When.class);
suite.addTestSuite(TryCatch.class);