mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] .new postfix template: support qualified references
Fixes IDEA-300278 'new' postfix doesn't work well for nested classes GitOrigin-RevId: 3b0b7a2e378dcf386b1813d7ec8af247379d2736
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bf1f4d88e0
commit
3ba76e26e3
+35
-46
@@ -19,36 +19,26 @@ import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplate
|
||||
|
||||
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 call ? call.getMethodExpression() :
|
||||
expression instanceof PsiReferenceExpression r ? r :
|
||||
null;
|
||||
if (ref == null) 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;
|
||||
PsiExpression qualifier = ref.getQualifierExpression();
|
||||
|
||||
JavaResolveResult result = ref.advancedResolve(true);
|
||||
|
||||
PsiElement element = result.getElement();
|
||||
if (element != null && !(element instanceof PsiClass)) return false;
|
||||
if (element != null) {
|
||||
PsiMethod[] constructors = ((PsiClass)element).getConstructors();
|
||||
if (constructors.length > 0) {
|
||||
PsiResolveHelper helper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
|
||||
if (ContainerUtil.and(constructors, m -> !helper.isAccessible(m, ref, (PsiClass)element))) {
|
||||
// All constructors aren't accessible
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
//todo implement proper support for Foo<Bar>, Foo.new Bar()
|
||||
if (qualifier != null && (!(qualifier instanceof PsiReferenceExpression) || element == null)) return false;
|
||||
|
||||
if (element == null) return true;
|
||||
if (!(element instanceof PsiClass cls)) return false;
|
||||
PsiMethod[] constructors = cls.getConstructors();
|
||||
if (constructors.length == 0) return true;
|
||||
PsiResolveHelper helper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
|
||||
// Check whether there's at least one accessible constructor
|
||||
return !ContainerUtil.and(constructors, m -> !helper.isAccessible(m, ref, cls));
|
||||
};
|
||||
|
||||
protected NewExpressionPostfixTemplate() {
|
||||
@@ -63,20 +53,16 @@ public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
|
||||
@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 (expression instanceof PsiReferenceExpression ref) {
|
||||
JavaResolveResult result = ref.advancedResolve(true);
|
||||
PsiElement element = result.getElement();
|
||||
|
||||
if (!(element instanceof PsiClass)) {
|
||||
super.expandForChooseExpression(expression, editor);
|
||||
return;
|
||||
if (element instanceof PsiClass psiClass) {
|
||||
WriteAction.run(() -> insertConstructorCallWithSmartBraces(expression, editor, psiClass));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WriteAction.run(() -> insertConstructorCallWithSmartBraces(expression, editor, (PsiClass)element));
|
||||
super.expandForChooseExpression(expression, editor);
|
||||
}
|
||||
|
||||
public void insertConstructorCallWithSmartBraces(@NotNull PsiElement expression,
|
||||
@@ -87,7 +73,7 @@ public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
Project project = expression.getProject();
|
||||
|
||||
SmartPsiElementPointer<PsiClass> pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(javaClass);
|
||||
replaceExpressionTextByNewExpressionInDocument(project, expression, document);
|
||||
int startOffset = replaceExpressionTextByNewExpressionInDocument(project, expression, document);
|
||||
|
||||
if (!javaClass.isValid()) {
|
||||
javaClass = pointer.getElement();
|
||||
@@ -97,13 +83,14 @@ public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
|
||||
JavaPsiClassReferenceElement item = JavaClassNameCompletionContributor.createClassLookupItem(javaClass, true);
|
||||
|
||||
item.handleInsert(createInsertionContext(editor, file, item));
|
||||
item.handleInsert(createInsertionContext(editor, file, item, startOffset));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static InsertionContext createInsertionContext(@NotNull Editor editor,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull JavaPsiClassReferenceElement item) {
|
||||
@NotNull JavaPsiClassReferenceElement item,
|
||||
int startOffset) {
|
||||
Document document = editor.getDocument();
|
||||
final OffsetMap offsetMap = new OffsetMap(document);
|
||||
final InsertionContext insertionContext = new InsertionContext(offsetMap,
|
||||
@@ -112,15 +99,17 @@ public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
file, editor, false);
|
||||
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
return CompletionUtil.newContext(insertionContext, item, offset, offset);
|
||||
return CompletionUtil.newContext(insertionContext, item, startOffset, offset);
|
||||
}
|
||||
|
||||
private static void replaceExpressionTextByNewExpressionInDocument(@NotNull Project project,
|
||||
@NotNull PsiElement expression,
|
||||
@NotNull Document document) {
|
||||
private static int replaceExpressionTextByNewExpressionInDocument(@NotNull Project project,
|
||||
@NotNull PsiElement expression,
|
||||
@NotNull Document document) {
|
||||
TextRange range = expression.getTextRange();
|
||||
document.replaceString(range.getStartOffset(), range.getEndOffset(), "new " + expression.getText());
|
||||
String newPrefix = "new ";
|
||||
document.replaceString(range.getStartOffset(), range.getEndOffset(), newPrefix + expression.getText());
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
return range.getStartOffset() + newPrefix.length();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
java.lang.String.new<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
java.lang.String.new<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class String {}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
new java.lang.String(<caret>)
|
||||
}
|
||||
}
|
||||
|
||||
class String {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
java.util.ArrayList.new<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class String {}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
new ArrayList<<caret>>()
|
||||
}
|
||||
}
|
||||
|
||||
class String {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
new String(<caret>)
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
Bar.new<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
class Bar {
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
Foo.Bar.new<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
class Bar {
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
new Foo.Bar()<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
class Bar {
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class ForStaticNestedNew {
|
||||
|
||||
class Scratch {
|
||||
public static void main(String[] args) {
|
||||
new Bar(<caret>)
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
class Bar {
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -71,6 +71,26 @@ public class NewExpressionPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewNestedClass() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewNestedClass2() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewFQN() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewFQNConflict() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewFQNImport() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewInaccessible() {
|
||||
myFixture.addClass("class Test {private Test() {}}");
|
||||
doTest();
|
||||
|
||||
Reference in New Issue
Block a user