mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
SSR: remove need to wrap every pattern in a code block
This commit is contained in:
+27
-38
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.structuralsearch;
|
||||
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -46,22 +45,16 @@ import java.util.Map;
|
||||
*/
|
||||
public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
private final ReplacementContext myContext;
|
||||
private PsiCodeBlock codeBlock;
|
||||
private final PsiElement[] patternElements;
|
||||
|
||||
public JavaReplaceHandler(ReplacementContext context) {
|
||||
this.myContext = context;
|
||||
}
|
||||
|
||||
private PsiCodeBlock getCodeBlock() throws IncorrectOperationException {
|
||||
if (codeBlock == null) {
|
||||
codeBlock = (PsiCodeBlock)MatcherImplUtil.createTreeFromText(
|
||||
myContext.getOptions().getMatchOptions().getSearchPattern(),
|
||||
PatternTreeContext.Block,
|
||||
myContext.getOptions().getMatchOptions().getFileType(),
|
||||
myContext.getProject()
|
||||
)[0].getParent();
|
||||
}
|
||||
return codeBlock;
|
||||
patternElements = MatcherImplUtil.createTreeFromText(
|
||||
myContext.getOptions().getMatchOptions().getSearchPattern(),
|
||||
PatternTreeContext.Block,
|
||||
myContext.getOptions().getMatchOptions().getFileType(),
|
||||
myContext.getProject()
|
||||
);
|
||||
}
|
||||
|
||||
private static PsiElement findRealSubstitutionElement(PsiElement el) {
|
||||
@@ -96,17 +89,11 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiNamedElement getSymbolReplacementTarget(final PsiElement el)
|
||||
throws IncorrectOperationException {
|
||||
if (myContext.getOptions().getMatchOptions().getFileType() != StdFileTypes.JAVA) return null; //?
|
||||
final PsiStatement[] searchStatements = getCodeBlock().getStatements();
|
||||
if (searchStatements.length > 0 &&
|
||||
searchStatements[0] instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)searchStatements[0]).getExpression();
|
||||
private PsiNamedElement getSymbolReplacementTarget(final PsiElement el) {
|
||||
if (patternElements.length == 1 && patternElements[0] instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)patternElements[0]).getExpression();
|
||||
|
||||
if (expression instanceof PsiReferenceExpression &&
|
||||
((PsiReferenceExpression)expression).getQualifierExpression() == null
|
||||
) {
|
||||
if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).getQualifierExpression() == null) {
|
||||
// looks like symbol replacements, namely replace AAA by BBB, so lets do the best
|
||||
if (el instanceof PsiNamedElement) {
|
||||
return (PsiNamedElement)el;
|
||||
@@ -138,7 +125,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
return replacement;
|
||||
}
|
||||
|
||||
private boolean isSymbolReplacement(final PsiElement el) throws IncorrectOperationException {
|
||||
private boolean isSymbolReplacement(final PsiElement el) {
|
||||
return getSymbolReplacementTarget(el) != null;
|
||||
}
|
||||
|
||||
@@ -157,14 +144,14 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, PsiNamedElement> searchedNamedElements = Collector.collectNamedElements(getCodeBlock());
|
||||
Map<String, PsiNamedElement> patternNamedElements = Collector.collectNamedElements(patternElements);
|
||||
|
||||
for (String name : originalNamedElements.keySet()) {
|
||||
PsiNamedElement originalNamedElement = originalNamedElements.get(name);
|
||||
PsiNamedElement replacementNamedElement = replacedNamedElements.get(name);
|
||||
String key = newNameToSearchPatternNameMap.get(name);
|
||||
if (key == null) key = name;
|
||||
PsiNamedElement searchedNamedElement = searchedNamedElements.get(key);
|
||||
PsiNamedElement patternNamedElement = patternNamedElements.get(key);
|
||||
|
||||
if (replacementNamedElement == null && originalNamedElements.size() == 1 && replacedNamedElements.size() == 1) {
|
||||
replacementNamedElement = replacedNamedElements.entrySet().iterator().next().getValue();
|
||||
@@ -185,7 +172,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (replacementNamedElement != null && searchedNamedElement != null) {
|
||||
if (replacementNamedElement != null && patternNamedElement != null) {
|
||||
Replacer.handleComments(originalNamedElement, replacementNamedElement, myContext);
|
||||
}
|
||||
|
||||
@@ -201,24 +188,24 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
}
|
||||
|
||||
if (originalNamedElement instanceof PsiModifierListOwner &&
|
||||
searchedNamedElement instanceof PsiModifierListOwner &&
|
||||
patternNamedElement instanceof PsiModifierListOwner &&
|
||||
replacementNamedElement instanceof PsiModifierListOwner) {
|
||||
copyModifiersAndAnnotations((PsiModifierListOwner)originalNamedElement,
|
||||
(PsiModifierListOwner)searchedNamedElement,
|
||||
(PsiModifierListOwner)patternNamedElement,
|
||||
(PsiModifierListOwner)replacementNamedElement);
|
||||
}
|
||||
|
||||
if (originalNamedElement instanceof PsiMethod &&
|
||||
searchedNamedElement instanceof PsiMethod &&
|
||||
patternNamedElement instanceof PsiMethod &&
|
||||
replacementNamedElement instanceof PsiMethod) {
|
||||
copyMethodBodyIfNotReplaced((PsiMethod)originalNamedElement, (PsiMethod)searchedNamedElement, (PsiMethod)replacementNamedElement);
|
||||
copyMethodBodyIfNotReplaced((PsiMethod)originalNamedElement, (PsiMethod)patternNamedElement, (PsiMethod)replacementNamedElement);
|
||||
}
|
||||
|
||||
if (originalNamedElement instanceof PsiClass &&
|
||||
searchedNamedElement instanceof PsiClass &&
|
||||
patternNamedElement instanceof PsiClass &&
|
||||
replacementNamedElement instanceof PsiClass) {
|
||||
final PsiClass originalClass = (PsiClass)originalNamedElement;
|
||||
final PsiClass queryClass = (PsiClass)searchedNamedElement;
|
||||
final PsiClass queryClass = (PsiClass)patternNamedElement;
|
||||
final PsiClass replacementClass = (PsiClass)replacementNamedElement;
|
||||
|
||||
copyExtendsListIfNotReplaced(originalClass, queryClass, replacementClass);
|
||||
@@ -343,7 +330,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
queryQualifiedName.equals(originalReferenceElement.getReferenceName());
|
||||
}
|
||||
|
||||
private PsiElement handleSymbolReplacement(PsiElement replacement, final PsiElement el) throws IncorrectOperationException {
|
||||
private PsiElement handleSymbolReplacement(PsiElement replacement, final PsiElement el) {
|
||||
PsiNamedElement nameElement = getSymbolReplacementTarget(el);
|
||||
if (nameElement != null) {
|
||||
PsiElement oldReplacement = replacement;
|
||||
@@ -645,7 +632,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement createSemicolon(final PsiElement space) throws IncorrectOperationException {
|
||||
private static PsiElement createSemicolon(final PsiElement space) {
|
||||
final PsiStatement text = JavaPsiFacade.getInstance(space.getProject()).getElementFactory().createStatementFromText(";", null);
|
||||
return text.getFirstChild();
|
||||
}
|
||||
@@ -653,9 +640,11 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
|
||||
private static class Collector extends JavaRecursiveElementWalkingVisitor {
|
||||
private final HashMap<String, PsiNamedElement> namedElements = new HashMap<>(1);
|
||||
|
||||
public static Map<String, PsiNamedElement> collectNamedElements(PsiElement context) {
|
||||
public static Map<String, PsiNamedElement> collectNamedElements(PsiElement... elements) {
|
||||
final Collector collector = new Collector();
|
||||
context.accept(collector);
|
||||
for (PsiElement element : elements) {
|
||||
element.accept(collector);
|
||||
}
|
||||
return collector.namedElements;
|
||||
}
|
||||
|
||||
|
||||
+13
-29
@@ -50,6 +50,7 @@ import com.intellij.structuralsearch.plugin.ui.SearchContext;
|
||||
import com.intellij.structuralsearch.plugin.ui.UIUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.SmartList;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -198,7 +199,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
|
||||
|
||||
@Override
|
||||
public void compile(PsiElement[] elements, @NotNull GlobalCompilingVisitor globalVisitor) {
|
||||
elements[0].getParent().accept(new JavaCompilingVisitor(globalVisitor));
|
||||
new JavaCompilingVisitor(globalVisitor).compile(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -256,8 +257,8 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
|
||||
}
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
if (context == PatternTreeContext.Block) {
|
||||
final PsiElement element = elementFactory.createStatementFromText("{\n" + text + "\n}", null);
|
||||
final PsiElement[] children = ((PsiBlockStatement)element).getCodeBlock().getChildren();
|
||||
final PsiCodeBlock codeBlock = elementFactory.createCodeBlockFromText("{\n" + text + "\n}", null);
|
||||
final PsiElement[] children = codeBlock.getChildren();
|
||||
final int extraChildCount = 4;
|
||||
|
||||
if (children.length > extraChildCount) {
|
||||
@@ -295,24 +296,17 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
|
||||
if (endChild != null) endChild = endChild.getPrevSibling();
|
||||
if (startChild == endChild) return PsiElement.EMPTY_ARRAY; // nothing produced
|
||||
|
||||
final PsiCodeBlock codeBlock = elementFactory.createCodeBlock();
|
||||
final List<PsiElement> result = new ArrayList<>(3);
|
||||
assert startChild != null;
|
||||
for (PsiElement el = startChild.getNextSibling(); el != endChild && el != null; el = el.getNextSibling()) {
|
||||
if (el instanceof PsiErrorElement) continue;
|
||||
result.add(codeBlock.add(el));
|
||||
final List<PsiElement> result = new SmartList<>();
|
||||
for (PsiElement element = startChild.getNextSibling(); element != endChild && element != null; element = element.getNextSibling()) {
|
||||
if (element instanceof PsiErrorElement) continue;
|
||||
result.add(element);
|
||||
}
|
||||
|
||||
return PsiUtilCore.toPsiElementArray(result);
|
||||
}
|
||||
else if (context == PatternTreeContext.Expression) {
|
||||
final PsiExpression expression = elementFactory.createExpressionFromText(text, null);
|
||||
final PsiBlockStatement statement = (PsiBlockStatement)elementFactory.createStatementFromText("{\na\n}", null);
|
||||
final PsiElement[] children = statement.getCodeBlock().getChildren();
|
||||
if (children.length != 5) return PsiElement.EMPTY_ARRAY;
|
||||
final PsiExpressionStatement childStatement = (PsiExpressionStatement)children[2];
|
||||
childStatement.getExpression().replace(expression);
|
||||
return new PsiElement[] { childStatement };
|
||||
return new PsiElement[] {elementFactory.createExpressionFromText(text, null)};
|
||||
}
|
||||
else {
|
||||
return PsiFileFactory.getInstance(project).createFileFromText("__dummy.java", JavaFileType.INSTANCE, text).getChildren();
|
||||
@@ -434,26 +428,16 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
|
||||
public void checkReplacementPattern(Project project, ReplaceOptions options) {
|
||||
MatchOptions matchOptions = options.getMatchOptions();
|
||||
FileType fileType = matchOptions.getFileType();
|
||||
PsiElement[] statements = MatcherImplUtil.createTreeFromText(
|
||||
matchOptions.getSearchPattern(),
|
||||
PatternTreeContext.Block,
|
||||
fileType,
|
||||
project
|
||||
);
|
||||
PsiElement[] statements = createPatternTree(matchOptions.getSearchPattern(), PatternTreeContext.Block, fileType, project, false);
|
||||
final boolean searchIsExpression = statements.length == 1 && statements[0].getLastChild() instanceof PsiErrorElement;
|
||||
|
||||
PsiElement[] statements2 = MatcherImplUtil.createTreeFromText(
|
||||
options.getReplacement(),
|
||||
PatternTreeContext.Block,
|
||||
fileType,
|
||||
project
|
||||
);
|
||||
PsiElement[] statements2 = createPatternTree(options.getReplacement(), PatternTreeContext.Block, fileType, project, false);
|
||||
final boolean replaceIsExpression = statements2.length == 1 && statements2[0].getLastChild() instanceof PsiErrorElement;
|
||||
|
||||
ValidatingVisitor visitor = new ValidatingVisitor();
|
||||
for (PsiElement statement : statements2) {
|
||||
visitor.setCurrent((statements.length == 1 && (statement instanceof PsiExpressionStatement || statement instanceof PsiDeclarationStatement))
|
||||
? statement : null);
|
||||
visitor.setCurrent((statements.length == 1 &&
|
||||
(statement instanceof PsiExpressionStatement || statement instanceof PsiDeclarationStatement)) ? statement : null);
|
||||
statement.accept(visitor);
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -57,6 +57,14 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
this.myCompilingVisitor = compilingVisitor;
|
||||
}
|
||||
|
||||
public void compile(PsiElement[] topLevelElements) {
|
||||
for (PsiElement element : topLevelElements) {
|
||||
element.accept(this);
|
||||
final MatchingHandler matchingHandler = myCompilingVisitor.getContext().getPattern().getHandler(element);
|
||||
myCompilingVisitor.getContext().getPattern().setHandler(element, new TopLevelMatchingHandler(matchingHandler));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDocTag(PsiDocTag psiDocTag) {
|
||||
super.visitDocTag(psiDocTag);
|
||||
@@ -492,8 +500,6 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
|
||||
@Override
|
||||
public void visitCodeBlock(PsiCodeBlock block) {
|
||||
myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() + 1);
|
||||
|
||||
for (PsiElement el = block.getFirstChild(); el != null; el = el.getNextSibling()) {
|
||||
if (GlobalCompilingVisitor.getFilter().accepts(el)) {
|
||||
if (el instanceof PsiWhiteSpace) {
|
||||
@@ -502,14 +508,8 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
}
|
||||
else {
|
||||
el.accept(this);
|
||||
if (myCompilingVisitor.getCodeBlockLevel() == 1) {
|
||||
final MatchingHandler matchingHandler = myCompilingVisitor.getContext().getPattern().getHandler(el);
|
||||
myCompilingVisitor.getContext().getPattern().setHandler(el, new TopLevelMatchingHandler(matchingHandler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() - 1);
|
||||
}
|
||||
|
||||
private static boolean needsSupers(final PsiElement element, final MatchingHandler handler) {
|
||||
|
||||
+2
-4
@@ -116,7 +116,7 @@ public class Replacer {
|
||||
lastElement = elements[elements.length-1];
|
||||
parent = firstElement.getParent();
|
||||
|
||||
matchOptions.setScope(new LocalSearchScope(parent));
|
||||
matchOptions.setScope(new LocalSearchScope(elements));
|
||||
} else {
|
||||
parent = ((LocalSearchScope)options.getMatchOptions().getScope()).getScope()[0];
|
||||
firstElement = parent.getFirstChild();
|
||||
@@ -133,10 +133,8 @@ public class Replacer {
|
||||
resultPtrList.add(buildReplacement(result));
|
||||
}
|
||||
|
||||
sink.getMatches().clear();
|
||||
|
||||
int startOffset = firstElement.getTextRange().getStartOffset();
|
||||
int endOffset = filePattern ?0: parent.getTextLength() - (lastElement.getTextRange().getEndOffset());
|
||||
int endOffset = filePattern ? 0 : parent.getTextLength() - lastElement.getTextRange().getEndOffset();
|
||||
|
||||
// get nodes from text may contain
|
||||
PsiElement prevSibling = firstElement.getPrevSibling();
|
||||
|
||||
Reference in New Issue
Block a user