From 50348eacc6f659f7d76cafcff87cce159c9b909f Mon Sep 17 00:00:00 2001 From: anstarovoyt Date: Fri, 27 Apr 2018 16:08:13 +0300 Subject: [PATCH] java postfix templates: "new" postfix template IDEA-122440 --- .../JavaPostfixTemplateProvider.java | 1 + .../NewExpressionPostfixTemplate.java | 115 ++++++++++++++++++ .../after.java.template | 1 + .../before.java.template | 1 + .../description.html | 6 + .../postfix/templates/new/new01_after.java | 2 +- .../template/postfix/templates/new/new02.java | 5 - .../postfix/templates/new/new02_after.java | 5 - .../template/postfix/templates/new/new03.java | 5 - .../postfix/templates/new/new03_after.java | 6 - .../postfix/templates/new/new04_after.java | 3 +- .../postfix/templates/new/new05_after.java | 2 +- .../postfix/templates/new/new07_after.java | 3 +- .../postfix/templates/new/new08_after.java | 2 +- .../postfix/templates/new/newAfterNew.java | 5 + .../templates/new/newAfterNew_after.java | 5 + .../templates/new/newInsideExpression.java | 5 + .../new/newInsideExpression_after.java | 5 + .../new/newOnAssignExpression_after.java | 2 +- .../postfix/templates/new/newUnresolved.java | 5 + .../templates/new/newUnresolved_after.java | 5 + .../postfix/templates/new/newWithCall.java | 5 + .../templates/new/newWithCall_after.java | 5 + .../postfix/templates/new/notClassCall.java | 5 + .../templates/new/notClassCallWithClass.java | 7 ++ .../new/notClassCallWithClass_after.java | 7 ++ .../templates/new/notClassCall_after.java | 5 + .../NewExpressionPostfixTemplateTest.java | 65 ++++++++++ 28 files changed, 259 insertions(+), 29 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NewExpressionPostfixTemplate.java create mode 100644 java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/after.java.template create mode 100644 java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/before.java.template create mode 100644 java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/description.html delete mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java delete mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java delete mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java delete mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall_after.java create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/template/postfix/templates/NewExpressionPostfixTemplateTest.java diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java index eb62f4b41742..b8c2105b15f2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java @@ -48,6 +48,7 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider { new ArgumentPostfixTemplate(this), new CastExpressionPostfixTemplate(), + new NewExpressionPostfixTemplate(), new CastVarPostfixTemplate(), new ElseStatementPostfixTemplate(), new IfStatementPostfixTemplate(), diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NewExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NewExpressionPostfixTemplate.java new file mode 100644 index 000000000000..5b55dd1492f7 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NewExpressionPostfixTemplate.java @@ -0,0 +1,115 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.Lookup; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset; + +public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate { + private static final Condition CONSTRUCTOR = expression -> { + if (!(expression instanceof PsiReferenceExpression) && + !(expression instanceof PsiMethodCallExpression)) { + return false; + } + + PsiReferenceExpression ref = expression instanceof PsiMethodCallExpression ? + ((PsiMethodCallExpression)expression).getMethodExpression() : + (PsiReferenceExpression)expression; + + PsiExpression qualifierExpression = ref.getQualifierExpression(); + + //disabled for qualified elements + //todo implement proper support for Foo, Foo.new Bar() and java.util.Foo + if (qualifierExpression != null) return false; + + JavaResolveResult result = ref.advancedResolve(true); + + PsiElement element = result.getElement(); + return element == null || element instanceof PsiClass; + }; + + protected NewExpressionPostfixTemplate() { + super("new", "new T()", selectorAllExpressionsWithCurrentOffset(CONSTRUCTOR)); + } + + @Nullable + @Override + public String getTemplateString(@NotNull PsiElement element) { + return element instanceof PsiMethodCallExpression ? "new $expr$" : "new $expr$($END$)"; + } + + @Override + public void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { + if (!(expression instanceof PsiReferenceExpression)) { + super.expandForChooseExpression(expression, editor); + return; + } + PsiReferenceExpression refExpression = (PsiReferenceExpression)expression; + JavaResolveResult result = refExpression.advancedResolve(true); + PsiElement element = result.getElement(); + + if (!(element instanceof PsiClass)) { + super.expandForChooseExpression(expression, editor); + return; + } + + WriteAction.run(() -> insertConstructorCallWithSmartBraces(expression, editor, (PsiClass)element)); + } + + public void insertConstructorCallWithSmartBraces(@NotNull PsiElement expression, + @NotNull Editor editor, + @NotNull PsiClass javaClass) { + Document document = editor.getDocument(); + PsiFile file = expression.getContainingFile(); + Project project = expression.getProject(); + + SmartPsiElementPointer pointer = SmartPointerManager.getInstance(editor.getProject()).createSmartPsiElementPointer(javaClass); + replaceExpressionTextByNewExpressionInDocument(project, expression, document); + + if (!javaClass.isValid()) { + javaClass = pointer.getElement(); + } + + //noinspection ConstantConditions / false positive + if (javaClass == null) return; + + JavaPsiClassReferenceElement item = JavaClassNameCompletionContributor.createClassLookupItem(javaClass, true); + + item.handleInsert(createInsertionContext(editor, file, item)); + } + + @NotNull + private static InsertionContext createInsertionContext(@NotNull Editor editor, + @NotNull PsiFile file, + @NotNull JavaPsiClassReferenceElement item) { + Document document = editor.getDocument(); + final OffsetMap offsetMap = new OffsetMap(document); + final InsertionContext insertionContext = new InsertionContext(offsetMap, + Lookup.AUTO_INSERT_SELECT_CHAR, + new LookupElement[]{item}, + file, editor, false); + + int offset = editor.getCaretModel().getOffset(); + return CompletionUtil.newContext(insertionContext, item, offset, offset); + } + + private static void replaceExpressionTextByNewExpressionInDocument(@NotNull Project project, + @NotNull PsiElement expression, + @NotNull Document document) { + TextRange range = expression.getTextRange(); + document.replaceString(range.getStartOffset(), range.getEndOffset(), "new " + expression.getText()); + + PsiDocumentManager.getInstance(project).commitDocument(document); + } +} diff --git a/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/after.java.template b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/after.java.template new file mode 100644 index 000000000000..962e42520724 --- /dev/null +++ b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/after.java.template @@ -0,0 +1 @@ +new Foo() \ No newline at end of file diff --git a/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/before.java.template b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/before.java.template new file mode 100644 index 000000000000..ce8b9c0fb407 --- /dev/null +++ b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/before.java.template @@ -0,0 +1 @@ +Foo$key \ No newline at end of file diff --git a/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/description.html b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/description.html new file mode 100644 index 000000000000..63391e8ec56e --- /dev/null +++ b/java/java-impl/src/postfixTemplates/NewExpressionPostfixTemplate/description.html @@ -0,0 +1,6 @@ + + + +Inserts new call for the class. + + diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java index 6e5cbcda3a40..5ae77b7eabdb 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java @@ -1,5 +1,5 @@ public class Foo { void m() { - new Foo(); + new Foo() } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java deleted file mode 100644 index 3a79f1ba3deb..000000000000 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java +++ /dev/null @@ -1,5 +0,0 @@ -public class Foo { - void m() { - Foo.new - } -} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java deleted file mode 100644 index ea6b65245654..000000000000 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java +++ /dev/null @@ -1,5 +0,0 @@ -public class Foo { - void m() { - new Foo(); - } -} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java deleted file mode 100644 index 1d13ef1731f4..000000000000 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java +++ /dev/null @@ -1,5 +0,0 @@ -public abstract class Foo { - void m() { - Foo.new - } -} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java deleted file mode 100644 index b6f938b0bb26..000000000000 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java +++ /dev/null @@ -1,6 +0,0 @@ -public abstract class Foo { - void m() { - new Foo() { - }; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java index 838fa7be2ee4..c9664eacec0c 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java @@ -1,7 +1,6 @@ public abstract class Foo { void m() { - new Foo() { - }; + new Foo() } } diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java index 5a46dc4963f8..398c63df42d8 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java @@ -1,7 +1,7 @@ public class Foo { public Foo(int x) { } void m() { - new Foo(); + new Foo() Bar a = new Bar(); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java index 1d97581f803c..668364518bb7 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java @@ -1,7 +1,6 @@ public class Foo { void m() { - new IFoo() { - }; + new IFoo() f(); } } diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java index 9982ebf1ba2b..494895837f9f 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java @@ -1,6 +1,6 @@ public abstract class Foo { void m() { - new FooBar(); + new FooBar() } class FooBar { private FooBar(int x) { } } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew.java new file mode 100644 index 000000000000..5e96328382a9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + new Foo().new + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew_after.java new file mode 100644 index 000000000000..b4795333fb49 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newAfterNew_after.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + new Foo().new + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression.java new file mode 100644 index 000000000000..d4acaeacbde4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression.java @@ -0,0 +1,5 @@ +public class Foo { + void m(Object p) { + m(Foo.new) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression_after.java new file mode 100644 index 000000000000..e13b52387562 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newInsideExpression_after.java @@ -0,0 +1,5 @@ +public class Foo { + void m(Object p) { + m(new Foo()) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java index e0f83fc41d48..3f9fd3c2ffcf 100644 --- a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java @@ -1,5 +1,5 @@ public class Foo { void m() { - Foo variable = new Foo(); + Foo variable = new Foo() } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved.java new file mode 100644 index 000000000000..6c11e0150fe0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + Foo11.new + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved_after.java new file mode 100644 index 000000000000..c607532d928c --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newUnresolved_after.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + new Foo11() + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall.java new file mode 100644 index 000000000000..a817263d77e3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + Foo().new + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall_after.java new file mode 100644 index 000000000000..5ae77b7eabdb --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newWithCall_after.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + new Foo() + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall.java new file mode 100644 index 000000000000..87d472af0702 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + m().new + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass.java new file mode 100644 index 000000000000..3a911d9924a7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass.java @@ -0,0 +1,7 @@ +public class Foo { + void m(): Foo { + m().new + + return new Foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass_after.java new file mode 100644 index 000000000000..cb45899db1ec --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCallWithClass_after.java @@ -0,0 +1,7 @@ +public class Foo { + void m(): Foo { + m().new + + return new Foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall_after.java new file mode 100644 index 000000000000..9175cb64202e --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/notClassCall_after.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + m().new + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/template/postfix/templates/NewExpressionPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/template/postfix/templates/NewExpressionPostfixTemplateTest.java new file mode 100644 index 000000000000..63f2355cc33f --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/template/postfix/templates/NewExpressionPostfixTemplateTest.java @@ -0,0 +1,65 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.codeInsight.template.postfix.templates; + +import org.jetbrains.annotations.NotNull; + +public class NewExpressionPostfixTemplateTest extends PostfixTemplateTestCase { + + @NotNull + @Override + protected String getSuffix() { + return "new"; + } + + public void testNew01() { + doTest(); + } + + public void testNew04() { + doTest(); + } + + public void testNew05() { + doTest(); + } + + public void testNew06() { + doTest(); + } + + public void testNew07() { + doTest(); + } + + public void testNew08() { + doTest(); + } + + public void testNewOnAssignExpression() { + doTest(); + } + + public void testNewInsideExpression() { + doTest(); + } + + public void testNewWithCall() { + doTest(); + } + + public void testNotClassCall() { + doTest(); + } + + public void testNotClassCallWithClass() { + doTest(); + } + + public void testNewUnresolved() { + doTest(); + } + + public void testNewAfterNew() { + doTest(); + } +}