java postfix templates: "new" postfix template IDEA-122440

This commit is contained in:
anstarovoyt
2018-04-27 16:09:50 +03:00
parent d7dfd68d15
commit 50348eacc6
28 changed files with 259 additions and 29 deletions
@@ -48,6 +48,7 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
new ArgumentPostfixTemplate(this),
new CastExpressionPostfixTemplate(),
new NewExpressionPostfixTemplate(),
new CastVarPostfixTemplate(),
new ElseStatementPostfixTemplate(),
new IfStatementPostfixTemplate(),
@@ -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<PsiElement> 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<Bar>, 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<PsiClass> 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);
}
}
@@ -0,0 +1 @@
new Foo(<spot></spot>)
@@ -0,0 +1 @@
<spot>Foo</spot>$key
@@ -0,0 +1,6 @@
<html>
<body>
Inserts new call for the class.
</body>
</html>
@@ -1,5 +1,5 @@
public class Foo {
void m() {
new Foo();<caret>
new Foo()<caret>
}
}
@@ -1,5 +0,0 @@
public class Foo<T> {
void m() {
Foo<Integer>.new<caret>
}
}
@@ -1,5 +0,0 @@
public class Foo<T> {
void m() {
new Foo<Integer>();<caret>
}
}
@@ -1,5 +0,0 @@
public abstract class Foo<T, U> {
void m() {
Foo<Integer, U>.new<caret>
}
}
@@ -1,6 +0,0 @@
public abstract class Foo<T, U> {
void m() {
new Foo<Integer, U>() {<caret>
};
}
}
@@ -1,7 +1,6 @@
public abstract class Foo {
void m() {
new Foo() {<caret>
};
new Foo()<caret>
}
}
@@ -1,7 +1,7 @@
public class Foo {
public Foo(int x) { }
void m() {
new Foo(<caret>);
new Foo(<caret>)
Bar a = new Bar();
}
}
@@ -1,7 +1,6 @@
public class Foo {
void m() {
new IFoo() {<caret>
};
new IFoo()<caret>
f();
}
}
@@ -1,6 +1,6 @@
public abstract class Foo {
void m() {
new FooBar(<caret>);
new FooBar(<caret>)
}
class FooBar { private FooBar(int x) { } }
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
new Foo().new<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
new Foo().new <caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object p) {
m(Foo.new<caret>)
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object p) {
m(new Foo())
}
}
@@ -1,5 +1,5 @@
public class Foo {
void m() {
Foo variable = new Foo();<caret>
Foo variable = new Foo()<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
Foo11.new<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
new Foo11()
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
Foo().new<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
new Foo()<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
m().new<caret>
}
}
@@ -0,0 +1,7 @@
public class Foo {
void m(): Foo {
m().new<caret>
return new Foo();
}
}
@@ -0,0 +1,7 @@
public class Foo {
void m(): Foo {
m().new <caret>
return new Foo();
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
m().new <caret>
}
}
@@ -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();
}
}