mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
SSR: replace annotation parameters more reliably (IDEA-223146)
GitOrigin-RevId: a6342b4ef5920b380d850cc2ead087321848a559
This commit is contained in:
committed by
intellij-monorepo-bot
parent
aa727f33b1
commit
bfb8367066
@@ -61,53 +61,51 @@ public class AnnotationParamListElement extends CompositeElement {
|
||||
|
||||
@Override
|
||||
public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
|
||||
if (first.getElementType() == JavaElementType.NAME_VALUE_PAIR && last.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
|
||||
ASTNode lparenth = findChildByType(JavaTokenType.LPARENTH);
|
||||
if (lparenth == null) {
|
||||
CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
|
||||
LeafElement created = Factory.createSingleLeafElement(JavaTokenType.LPARENTH, "(", 0, 1, treeCharTab, getManager());
|
||||
super.addInternal(created, created, getFirstChildNode(), true);
|
||||
}
|
||||
ASTNode lparenth = findChildByType(JavaTokenType.LPARENTH);
|
||||
if (lparenth == null) {
|
||||
CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
|
||||
LeafElement created = Factory.createSingleLeafElement(JavaTokenType.LPARENTH, "(", 0, 1, treeCharTab, getManager());
|
||||
super.addInternal(created, created, getFirstChildNode(), true);
|
||||
}
|
||||
|
||||
ASTNode rparenth = findChildByType(JavaTokenType.RPARENTH);
|
||||
if (rparenth == null) {
|
||||
CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
|
||||
LeafElement created = Factory.createSingleLeafElement(JavaTokenType.RPARENTH, ")", 0, 1, treeCharTab, getManager());
|
||||
super.addInternal(created, created, getLastChildNode(), false);
|
||||
}
|
||||
ASTNode rparenth = findChildByType(JavaTokenType.RPARENTH);
|
||||
if (rparenth == null) {
|
||||
CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
|
||||
LeafElement created = Factory.createSingleLeafElement(JavaTokenType.RPARENTH, ")", 0, 1, treeCharTab, getManager());
|
||||
super.addInternal(created, created, getLastChildNode(), false);
|
||||
}
|
||||
|
||||
ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
|
||||
if (nodes.length == 1) {
|
||||
ASTNode node = nodes[0];
|
||||
if (node instanceof PsiNameValuePair) {
|
||||
PsiNameValuePair pair = (PsiNameValuePair)node;
|
||||
if (pair.getName() == null) {
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (value != null) {
|
||||
try {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(getPsi().getProject());
|
||||
PsiAnnotation annotation = factory.createAnnotationFromText("@AAA(value = " + value.getText() + ")", null);
|
||||
replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
|
||||
if (nodes.length == 1) {
|
||||
ASTNode node = nodes[0];
|
||||
if (node instanceof PsiNameValuePair) {
|
||||
PsiNameValuePair pair = (PsiNameValuePair)node;
|
||||
if (pair.getName() == null) {
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (value != null) {
|
||||
try {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(getPsi().getProject());
|
||||
PsiAnnotation annotation = factory.createAnnotationFromText("@AAA(value = " + value.getText() + ")", null);
|
||||
replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anchor == null) {
|
||||
if (before == null) before = Boolean.TRUE;
|
||||
anchor = findChildByType(before ? JavaTokenType.RPARENTH : JavaTokenType.LPARENTH);
|
||||
}
|
||||
|
||||
TreeElement firstAdded = super.addInternal(first, last, anchor, before);
|
||||
JavaSourceUtil.addSeparatingComma(this, first, NAME_VALUE_PAIR_BIT_SET);
|
||||
return firstAdded;
|
||||
}
|
||||
|
||||
return super.addInternal(first, last, anchor, before);
|
||||
if (anchor == null) {
|
||||
if (before == null) before = Boolean.TRUE;
|
||||
anchor = findChildByType(before ? JavaTokenType.RPARENTH : JavaTokenType.LPARENTH);
|
||||
}
|
||||
|
||||
TreeElement firstAdded = super.addInternal(first, last, anchor, before);
|
||||
if (first == last && first.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
|
||||
JavaSourceUtil.addSeparatingComma(this, first, NAME_VALUE_PAIR_BIT_SET);
|
||||
}
|
||||
return firstAdded;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2000-2019 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.structuralsearch;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -276,8 +275,9 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
if (originalMember == null) {
|
||||
continue;
|
||||
}
|
||||
for (Iterator<? extends PsiElement> iterator = elements.iterator(); iterator.hasNext(); ) {
|
||||
PsiElement element = iterator.next();
|
||||
final Iterator<? extends PsiElement> iterator = elements.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final PsiElement element = iterator.next();
|
||||
if (PsiElementOrderComparator.getInstance().compare(element, originalMember) < 0) {
|
||||
addElementAndWhitespaceBeforeAnchor(replacementClass, element, anchor);
|
||||
iterator.remove();
|
||||
@@ -327,7 +327,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyAnnotationParameters(PsiAnnotation original, PsiAnnotation query, PsiAnnotation replacement) {
|
||||
private void copyAnnotationParameters(PsiAnnotation original, PsiAnnotation query, PsiAnnotation replacement) {
|
||||
final PsiAnnotationParameterList originalParameters = original.getParameterList();
|
||||
if (originalParameters.getTextLength() > 0) {
|
||||
final PsiAnnotationParameterList replacementParameters = replacement.getParameterList();
|
||||
@@ -338,15 +338,14 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
final List<? extends PsiElement> unmatchedAttributes = original.getUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY);
|
||||
if (unmatchedAttributes != null) {
|
||||
for (PsiElement attribute : unmatchedAttributes) {
|
||||
replacementParameters.add(whiteSpace(attribute.getPrevSibling(), " "));
|
||||
replacementParameters.add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyModifiersAndAnnotations(PsiModifierListOwner original,
|
||||
PsiModifierListOwner query,
|
||||
PsiModifierListOwner replacement) {
|
||||
private void copyModifiersAndAnnotations(PsiModifierListOwner original, PsiModifierListOwner query, PsiModifierListOwner replacement) {
|
||||
final PsiModifierList originalModifierList = original.getModifierList();
|
||||
final PsiModifierList queryModifierList = query.getModifierList();
|
||||
final PsiModifierList replacementModifierList = replacement.getModifierList();
|
||||
@@ -354,39 +353,58 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
if (originalModifierList == null || queryModifierList == null || replacementModifierList == null) {
|
||||
return;
|
||||
}
|
||||
if (originalModifierList.getTextLength() != 0) {
|
||||
final PsiModifierList copy = (PsiModifierList)originalModifierList.copy();
|
||||
for (String modifier : PsiModifier.MODIFIERS) {
|
||||
if (replacementModifierList.hasExplicitModifier(modifier)) {
|
||||
copy.setModifierProperty(modifier, true);
|
||||
}
|
||||
else if (queryModifierList.hasExplicitModifier(modifier) && !replacementModifierList.hasModifierProperty(modifier)) {
|
||||
copy.setModifierProperty(modifier, false);
|
||||
final List<? extends PsiElement> unmatchedAnnotations = originalModifierList.getUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY);
|
||||
final PsiElement anchor = replacementModifierList.getFirstChild();
|
||||
boolean append = (anchor == null);
|
||||
PsiElement child = originalModifierList.getFirstChild();
|
||||
while (child != null) {
|
||||
if (child instanceof PsiKeyword) {
|
||||
append = true;
|
||||
@PsiModifier.ModifierConstant final String modifierText = child.getText();
|
||||
if (isCompatibleModifier(modifierText, replacementModifierList) && !queryModifierList.hasExplicitModifier(modifierText)) {
|
||||
if (anchor != null) replacementModifierList.add(whiteSpace(child.getPrevSibling(), " "));
|
||||
replacementModifierList.add(child);
|
||||
}
|
||||
}
|
||||
final List<? extends PsiElement> unmatchedAnnotations = originalModifierList.getUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY);
|
||||
if (unmatchedAnnotations != null) {
|
||||
outer:
|
||||
for (PsiAnnotation copyAnnotation : copy.getAnnotations()) {
|
||||
for (PsiElement unmatchedAnnotation : unmatchedAnnotations) {
|
||||
if (AnnotationUtil.equal(copyAnnotation, (PsiAnnotation)unmatchedAnnotation)) {
|
||||
continue outer;
|
||||
}
|
||||
else if (child instanceof PsiAnnotation && (unmatchedAnnotations == null || unmatchedAnnotations.contains(child))) {
|
||||
if (append) {
|
||||
if (anchor != null) replacementModifierList.add(whiteSpace(child.getPrevSibling(), " "));
|
||||
replacementModifierList.add(child);
|
||||
}
|
||||
else {
|
||||
final PsiElement next = replacementModifierList.addBefore(child, anchor).getNextSibling();
|
||||
final PsiWhiteSpace whiteSpace = whiteSpace(child.getNextSibling(), " ");
|
||||
if (!(next instanceof PsiWhiteSpace)) {
|
||||
replacementModifierList.addBefore(whiteSpace, anchor);
|
||||
}
|
||||
else {
|
||||
next.replace(whiteSpace);
|
||||
}
|
||||
copyAnnotation.delete();
|
||||
}
|
||||
}
|
||||
for (PsiAnnotation annotation : replacementModifierList.getAnnotations()) {
|
||||
copy.addBefore(annotation, copy.getFirstChild());
|
||||
}
|
||||
replacementModifierList.replace(copy);
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
private PsiWhiteSpace whiteSpace(PsiElement element, @SuppressWarnings("SameParameterValue") String defaultWs) {
|
||||
return element instanceof PsiWhiteSpace
|
||||
? (PsiWhiteSpace)element
|
||||
: (PsiWhiteSpace)PsiParserFacade.SERVICE.getInstance(myProject).createWhiteSpaceFromText(defaultWs);
|
||||
}
|
||||
|
||||
private static boolean isCompatibleModifier(String modifier, PsiModifierList modifierList) {
|
||||
if (PsiModifier.PUBLIC.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) || PsiModifier.PRIVATE.equals(modifier)) {
|
||||
return !modifierList.hasExplicitModifier(PsiModifier.PUBLIC)
|
||||
&& !modifierList.hasExplicitModifier(PsiModifier.PROTECTED)
|
||||
&& !modifierList.hasExplicitModifier(PsiModifier.PRIVATE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PsiElement handleSymbolReplacement(PsiElement replacement, final PsiElement el) {
|
||||
PsiNamedElement nameElement = getSymbolReplacementTarget(el);
|
||||
final PsiNamedElement nameElement = getSymbolReplacementTarget(el);
|
||||
if (nameElement != null) {
|
||||
PsiElement oldReplacement = replacement;
|
||||
final PsiElement oldReplacement = replacement;
|
||||
replacement = el.copy();
|
||||
((PsiNamedElement)replacement).setName(oldReplacement.getText());
|
||||
}
|
||||
|
||||
@@ -2108,9 +2108,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
|
||||
}
|
||||
|
||||
public void testReplaceAnnotation() {
|
||||
String in1 = "@SuppressWarnings(\"ALL\")\n" +
|
||||
"public class A {}";
|
||||
String what = "@SuppressWarnings(\"ALL\")";
|
||||
final String in1 = "@SuppressWarnings(\"ALL\")\n" +
|
||||
"public class A {}";
|
||||
final String what = "@SuppressWarnings(\"ALL\")";
|
||||
|
||||
final String expected1a = "public class A {}";
|
||||
assertEquals(expected1a, replace(in1, what, ""));
|
||||
@@ -2175,7 +2175,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
|
||||
"}";
|
||||
assertEquals(expected4, replace(in4, "@'_A('_p*=1)", "@$A$($p$=1, three=1)"));
|
||||
|
||||
final String expected4b = "class X { @Anno(one=2,two=1) String s;}";
|
||||
final String expected4b = "class X { @Anno(one=2, two=1) String s;}";
|
||||
assertEquals(expected4b, replace(in4, "@'_A('_p:one =1)", "@$A$($p$=2)"));
|
||||
|
||||
final String in5 = "@RunWith(SpringJUnit4ClassRunner.class)\n" +
|
||||
@@ -2195,6 +2195,33 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
|
||||
assertEquals(expected5, replace(in5, "@ContextConfiguration(classes = {'_X*})", "@ContextHierarchy(classes = {\n" +
|
||||
" @ContextConfiguration(classes = {$X$, Object.class})\n" +
|
||||
"})"));
|
||||
|
||||
final String in6 = "class X {\n" +
|
||||
" @WastingTime @Override\n" +
|
||||
" public @Constant @Sorrow String value() {\n" +
|
||||
" return null;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
final String expected6 = "class X {\n" +
|
||||
" @WastingTime @Override\n" +
|
||||
" private @Constant @Sorrow String value() {\n" +
|
||||
" return null;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
assertEquals(expected6, replace(in6, "'_ReturnType '_method('_ParameterType '_parameter*);",
|
||||
"private $ReturnType$ $method$($ParameterType$ $parameter$);"));
|
||||
|
||||
final String in7 = "public class IssueLink {\n" +
|
||||
" @XmlAttribute(name = \"default\", namespace = \"space\")\n" +
|
||||
" @Deprecated\n" +
|
||||
" public String typeInward;\n" +
|
||||
"}";
|
||||
final String expected7 = "public class IssueLink {\n" +
|
||||
" @XmlAttribute(name=\"default\", namespace = \"space\")\n" +
|
||||
" public String typeInward;\n" +
|
||||
"}";
|
||||
assertEquals(expected7, replace(in7, "@XmlAttribute(name=\"default\") @Deprecated '_Type '_field;",
|
||||
"@XmlAttribute(name=\"default\") $Type$ $field$;"));
|
||||
}
|
||||
|
||||
public void testReplacePolyadicExpression() {
|
||||
|
||||
Reference in New Issue
Block a user