diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/after.groovy.template
new file mode 100644
index 000000000000..77232d0e2b49
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/after.groovy.template
@@ -0,0 +1,5 @@
+class FooTest extends TestCase {
+ public void testFoo() {
+ assert "1" == "1" : "Error"
+ }
+}
diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/before.groovy.template
new file mode 100644
index 000000000000..dee86ee85aa4
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/before.groovy.template
@@ -0,0 +1,5 @@
+class FooTest extends TestCase {
+ public void testFoo() {
+ assertEquals("Error", "1", "1")
+ }
+}
diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/description.html b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/description.html
new file mode 100644
index 000000000000..99a52a9ed0ab
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/ConvertJunitAssertionToAssertStatementIntention/description.html
@@ -0,0 +1,6 @@
+
+
+This intention converts JUnit assertion to assert statement.
+For Groovy, it is standard to prefer the assert keyword to the JUnit assert methods.
+
+
\ No newline at end of file
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index ae21ba67a7b1..56a592da2e73 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -880,6 +880,11 @@
intention.category.groovy/intention.category.conversions
org.jetbrains.plugins.groovy.intentions.conversions.ConvertClosureToMethodIntention
+
+ org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle
+ intention.category.groovy/intention.category.conversions
+ org.jetbrains.plugins.groovy.intentions.conversions.ConvertJunitAssertionToAssertStatementIntention
+
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
index 6cf92546be0b..776d356f7e4a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
@@ -71,6 +71,8 @@ convert.closure.to.method.intention.name=Convert to method
convert.closure.to.method.intention.family.name=Convert property to method
convert.method.to.closure.intention.name=Convert to property
convert.method.to.closure.intention.family.name=Convert method to property of closure type
+convert.junit.assertion.to.assert.statement.intention.name=Convert JUnit assertion to assert statement
+convert.junit.assertion.to.assert.statement.intention.family.name=Convert JUnit assertion to assert statement
###########################################################################################################
# Convert parameter to map entry refactoring
###########################################################################################################
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertJunitAssertionToAssertStatementIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertJunitAssertionToAssertStatementIntention.java
new file mode 100644
index 000000000000..b5a4491e884e
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertJunitAssertionToAssertStatementIntention.java
@@ -0,0 +1,135 @@
+package org.jetbrains.plugins.groovy.intentions.conversions;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.intentions.base.Intention;
+import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class ConvertJunitAssertionToAssertStatementIntention extends Intention implements PsiElementPredicate {
+
+ private static final Pattern PATTERN = Pattern.compile("arg(\\d+)");
+
+ private static Map ourStatementMap = new HashMap();
+ static {
+ ourStatementMap.put("assertNotNull", new String[]{null, "assert arg0 != null", "assert arg1 != null : arg0"});
+ ourStatementMap.put("assertNull", new String[]{null, "assert arg0 == null", "assert arg1 == null : arg0"});
+
+ ourStatementMap.put("assertTrue", new String[]{null, "assert arg0", "assert arg1 : arg0"});
+ ourStatementMap.put("assertFalse", new String[]{null, "assert !arg0", "assert !arg1 : arg0"});
+
+ ourStatementMap.put("assertEquals", new String[]{null, null, "assert arg0 == arg1", "assert arg1 == arg2 : arg0"});
+
+ ourStatementMap.put("assertSame", new String[]{null, null, "assert arg0.is(arg1)", "assert arg1.is(arg2) : arg0"});
+ ourStatementMap.put("assertNotSame", new String[]{null, null, "assert !arg0.is(arg1)", "assert !arg1.is(arg2) : arg0"});
+ }
+
+ @Nullable
+ private static String getReplacementStatement(@NotNull PsiMethod method, @NotNull GrMethodCall methodCall) {
+ PsiClass containingClass = method.getContainingClass();
+ if (containingClass == null) return null;
+
+ String qualifiedName = containingClass.getQualifiedName();
+ if (!"junit.framework.Assert".equals(qualifiedName) && !"groovy.util.GroovyTestCase".equals(qualifiedName)) return null;
+
+ String[] replacementStatements = ourStatementMap.get(method.getName());
+ if (replacementStatements == null) return null;
+
+ GrArgumentList argumentList = methodCall.getArgumentList();
+ if (argumentList == null) return null;
+
+ if (argumentList.getNamedArguments().length > 0) return null;
+
+ GrExpression[] arguments = argumentList.getExpressionArguments();
+
+ if (arguments.length >= replacementStatements.length) return null;
+
+ return replacementStatements[arguments.length];
+ }
+
+ @Nullable
+ private static GrStatement getReplacementElement(@NotNull PsiMethod method, @NotNull GrMethodCall methodCall) {
+ String replacementStatement = getReplacementStatement(method, methodCall);
+ if (replacementStatement == null) return null;
+
+ @SuppressWarnings("ConstantConditions") final
+ GrExpression[] arguments = methodCall.getArgumentList().getExpressionArguments();
+
+ GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(method.getProject());
+
+ GrAssertStatement statement = (GrAssertStatement)factory.createStatementFromText(replacementStatement);
+
+ final Map replaceMap = new HashMap();
+
+ statement.acceptChildren(new GroovyRecursiveElementVisitor() {
+ @Override
+ public void visitExpression(GrExpression expression) {
+ Matcher matcher = PATTERN.matcher(expression.getText());
+ if (matcher.matches()) {
+ int index = Integer.parseInt(matcher.group(1));
+ replaceMap.put(expression, arguments[index]);
+ }
+ else {
+ super.visitExpression(expression);
+ }
+ }
+ });
+
+ for (Map.Entry entry : replaceMap.entrySet()) {
+ entry.getKey().replaceWithExpression(entry.getValue(), true);
+ }
+
+ return statement;
+ }
+
+ @Override
+ protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
+ GrMethodCall methodCall = (GrMethodCall)element;
+
+ PsiMethod method = methodCall.resolveMethod();
+ if (method == null) return;
+
+ GrStatement replacementElement = getReplacementElement(method, methodCall);
+ if (replacementElement == null) return;
+
+ ((GrMethodCall)element).replaceWithStatement(replacementElement);
+ }
+
+ @NotNull
+ @Override
+ protected PsiElementPredicate getElementPredicate() {
+ return this;
+ }
+
+ @Override
+ public boolean satisfiedBy(PsiElement element) {
+ if (!(element instanceof GrMethodCall)) return false;
+
+ GrMethodCall methodCall = (GrMethodCall)element;
+
+ PsiMethod method = methodCall.resolveMethod();
+ if (method == null) return false;
+
+ return getReplacementStatement(method, methodCall) != null;
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GroovyConvertJUnitIntentionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GroovyConvertJUnitIntentionTest.groovy
new file mode 100644
index 000000000000..97ea1cd25513
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GroovyConvertJUnitIntentionTest.groovy
@@ -0,0 +1,96 @@
+package org.jetbrains.plugins.groovy.intentions
+
+import com.intellij.codeInsight.intention.IntentionAction
+import com.intellij.psi.impl.source.PostprocessReformattingAspect
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
+
+/**
+ * @author Sergey Evdokimov
+ */
+class GroovyConvertJUnitIntentionTest extends LightCodeInsightFixtureTestCase {
+
+ public void testAssertFalse() {
+ doTest("""
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assertFalse("!!!", 1 == 2)
+ }
+}
+""", """
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assert !(1 == 2): "!!!"
+ }
+}
+""")
+ }
+
+ public void testAssertEquals() {
+ doTest("""
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assertEquals("!!!", 1, 2)
+ }
+}
+""", """
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assert 1 == 2: "!!!"
+ }
+}
+""")
+ }
+
+ public void testAssertNotSame() {
+ doTest("""
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assertNotSame("1", "2")
+ }
+}
+""", """
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assert !"1".is("2")
+ }
+}
+""")
+ }
+
+ public void testFail() {
+ doTest("""
+class A extends junit.framework.Assert {
+ public void testXxxx() {
+ assertSame("1")
+ }
+}
+""", null)
+ }
+
+ private void doTest(String before, String after) {
+ myFixture.addFileToProject("junit/framework/Assert.groovy", """
+package junit.framework;
+public class Assert {
+ public static void assertTrue(java.lang.String message, boolean condition) { }
+ public static void assertTrue(boolean condition) { }
+ public static void assertFalse(java.lang.String message, boolean condition) { }
+ public static void assertEquals(java.lang.Object expected, java.lang.Object actual) { }
+ public static void assertNotSame(java.lang.Object expected, java.lang.Object actual) { }
+}
+""")
+ myFixture.configureByText("A.groovy", before);
+
+ String hint = GroovyIntentionsBundle.message("convert.junit.assertion.to.assert.statement.intention.name");
+ final List list = myFixture.filterAvailableIntentions(hint);
+ if (after == null) {
+ assertEmpty(list);
+ return;
+ }
+
+ myFixture.launchAction(assertOneElement(list));
+ PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
+
+ myFixture.checkResult(after)
+ }
+
+}