From a0dccdabcefbd58798903a5ca5fe6a2f83a6e42e Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 5 Oct 2017 16:19:15 +0200 Subject: [PATCH] SSR: rework ReplacementContext & ReplacementInfo --- .../structuralsearch/JavaReplaceHandler.java | 18 ++- .../JavaStructuralSearchProfile.java | 10 +- .../DocumentBasedReplaceHandler.java | 6 +- .../StructuralSearchProfile.java | 6 +- .../StructuralSearchUtil.java | 2 +- .../XmlStructuralSearchProfile.java | 4 +- .../plugin/replace/ReplacementInfo.java | 20 ++- .../replace/impl/ReplacementBuilder.java | 56 ++------ .../replace/impl/ReplacementContext.java | 46 ++----- .../replace/impl/ReplacementInfoImpl.java | 125 ++++++++++++++++-- .../plugin/replace/impl/Replacer.java | 86 ++---------- 11 files changed, 181 insertions(+), 198 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java index 8e947be54d70..e2cba6934551 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java @@ -30,6 +30,7 @@ import com.intellij.structuralsearch.plugin.replace.impl.ReplacementContext; import com.intellij.structuralsearch.plugin.replace.impl.Replacer; import com.intellij.structuralsearch.plugin.replace.impl.ReplacerUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.util.SmartList; import com.siyeh.ig.psiutils.ImportUtils; import com.siyeh.ig.psiutils.PsiElementOrderComparator; @@ -133,14 +134,12 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { * Copy all comments, doc comments, modifier lists and method bodies * that are present in matched nodes but not present in searched & replaced nodes */ - private void copyUnmatchedElements(final PsiElement original, final PsiElement replacement) { - Map newNameToSearchPatternNameMap = myContext.getNewName2PatternNameMap(); - + private void copyUnmatchedElements(PsiElement original, PsiElement replacement, ReplacementInfo info) { Map originalNamedElements = Collector.collectNamedElements(original); Map replacedNamedElements = Collector.collectNamedElements(replacement); if (originalNamedElements.size() == 0 && replacedNamedElements.size() == 0) { - Replacer.handleComments(original, replacement, myContext); + Replacer.handleComments(original, replacement, info); return; } @@ -149,8 +148,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { 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; + String key = ObjectUtils.notNull(info.getSearchPatternName(name), name); PsiNamedElement patternNamedElement = patternNamedElements.get(key); if (replacementNamedElement == null && originalNamedElements.size() == 1 && replacedNamedElements.size() == 1) { @@ -173,7 +171,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { } if (replacementNamedElement != null && patternNamedElement != null) { - Replacer.handleComments(originalNamedElement, replacementNamedElement, myContext); + Replacer.handleComments(originalNamedElement, replacementNamedElement, info); } if (comment != null && replacementNamedElement instanceof PsiDocCommentOwner && @@ -380,7 +378,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { if (listContext) { if (replacements.length > 1) { final PsiElement replacement = elementParent.addRangeBefore(replacements[0], replacements[replacements.length - 1], elementToReplace); - copyUnmatchedElements(elementToReplace, replacement); + copyUnmatchedElements(elementToReplace, replacement, info); } else if (replacements.length == 1) { PsiElement replacement = getMatchExpr(replacements[0], elementToReplace); @@ -395,7 +393,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { replacement = JavaPsiFacade.getElementFactory(variable.getProject()).createParameterFromText(parameterText, variable); } - copyUnmatchedElements(elementToReplace, replacement); + copyUnmatchedElements(elementToReplace, replacement, info); replacement = handleSymbolReplacement(replacement, elementToReplace); if (replacement instanceof PsiTryStatement) { @@ -459,7 +457,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { elementToReplace.getNode().getTreeParent().removeChild(elementToReplace.getNode()); } else { - copyUnmatchedElements(elementToReplace, replacement); + copyUnmatchedElements(elementToReplace, replacement, info); replacement = handleSymbolReplacement(replacement, elementToReplace); elementToReplace.replace(replacement); diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index 3b19aedb26ad..caff2df058f1 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -41,6 +41,7 @@ import com.intellij.structuralsearch.impl.matcher.compiler.GlobalCompilingVisito import com.intellij.structuralsearch.impl.matcher.compiler.JavaCompilingVisitor; import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; +import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; import com.intellij.structuralsearch.plugin.replace.impl.ParameterInfo; import com.intellij.structuralsearch.plugin.replace.impl.ReplacementBuilder; import com.intellij.structuralsearch.plugin.replace.impl.ReplacementContext; @@ -182,6 +183,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { @NotNull @Override public PsiElement getPresentableElement(PsiElement element) { + element = super.getPresentableElement(element); if (element instanceof PsiReferenceExpression) { final PsiElement parent = element.getParent(); if (parent instanceof PsiMethodCallExpression) { @@ -586,14 +588,14 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { MatchResult match, StringBuilder result, int offset, - HashMap matchMap) { + ReplacementInfo replacementInfo) { if (info.getName().equals(match.getName())) { final String replacementString; boolean forceAddingNewLine = false; if (info.isMethodParameterContext()) { final StringBuilder buf = new StringBuilder(); - handleMethodParameter(buf, info, matchMap); + handleMethodParameter(buf, info, replacementInfo); replacementString = buf.toString(); } else if (match.hasSons() && !match.isScopeMatch()) { @@ -758,7 +760,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { return match instanceof PsiMember; } - private static void handleMethodParameter(StringBuilder buf, ParameterInfo info, HashMap matchMap) { + private static void handleMethodParameter(StringBuilder buf, ParameterInfo info, ReplacementInfo replacementInfo) { if(!(info.getElement() instanceof PsiTypeElement)) { // no specific handling for name of method parameter since it is handled with type return; @@ -767,7 +769,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { String name = ((PsiParameter)info.getElement().getParent()).getName(); name = StructuralSearchUtil.isTypedVariable(name) ? Replacer.stripTypedVariableDecoration(name):name; - final MatchResult matchResult = matchMap.get(name); + final MatchResult matchResult = replacementInfo.getNamedMatchResult(name); if (matchResult == null) return; if (matchResult.isMultipleMatch()) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java index c2dc2392eac7..484d3cc77208 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java @@ -1,3 +1,4 @@ +// Copyright 2000-2017 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.openapi.editor.Document; @@ -9,7 +10,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; -import com.intellij.structuralsearch.plugin.replace.impl.ReplacementInfoImpl; import com.intellij.util.containers.HashMap; import java.util.Map; @@ -27,7 +27,6 @@ public class DocumentBasedReplaceHandler extends StructuralReplaceHandler { public void replace(ReplacementInfo info, ReplaceOptions options) { if (info.getMatchesCount() == 0) return; - assert info instanceof ReplacementInfoImpl; PsiElement element = info.getMatch(0); if (element == null) return; PsiFile file = element instanceof PsiFile ? (PsiFile)element : element.getContainingFile(); @@ -40,8 +39,7 @@ public class DocumentBasedReplaceHandler extends StructuralReplaceHandler { @Override public void prepare(ReplacementInfo info) { - assert info instanceof ReplacementInfoImpl; - MatchResult result = ((ReplacementInfoImpl)info).getMatchResult(); + MatchResult result = info.getMatchResult(); PsiElement element = result.getMatch(); PsiFile file = element instanceof PsiFile ? (PsiFile)element : element.getContainingFile(); Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java index 2112cfa00e0b..94a5d01b7c77 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java @@ -33,6 +33,7 @@ import com.intellij.structuralsearch.impl.matcher.GlobalMatchingVisitor; import com.intellij.structuralsearch.impl.matcher.PatternTreeContext; import com.intellij.structuralsearch.impl.matcher.compiler.GlobalCompilingVisitor; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; +import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; import com.intellij.structuralsearch.plugin.replace.impl.ParameterInfo; import com.intellij.structuralsearch.plugin.replace.impl.ReplacementBuilder; import com.intellij.structuralsearch.plugin.replace.impl.ReplacementContext; @@ -47,7 +48,6 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; /** * @author Eugene.Kudelevsky @@ -219,7 +219,7 @@ public abstract class StructuralSearchProfile { MatchResult match, StringBuilder result, int offset, - HashMap matchMap) { + ReplacementInfo replacementInfo) { if (info.getName().equals(match.getName())) { String replacementString = match.getMatchImage(); boolean forceAddingNewLine = false; @@ -284,6 +284,6 @@ public abstract class StructuralSearchProfile { @NotNull public PsiElement getPresentableElement(PsiElement element) { - return element; + return isIdentifier(element) ? element.getParent() : element; } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java index 6f0200a4d81e..6add119add44 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java @@ -66,7 +66,7 @@ public class StructuralSearchUtil { if (profile == null) { return element; } - return profile.getPresentableElement(getParentIfIdentifier(element)); + return profile.getPresentableElement(element); } private static StructuralSearchProfile[] getNewStyleProfiles() { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java index 823c95e138bc..c737e0b7e535 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java @@ -156,7 +156,7 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile { PsiElement replacement = ReplacerUtil.copySpacesAndCommentsBefore(elementToReplace, statements, replacementToMake, elementParent); // preserve comments - Replacer.handleComments(elementToReplace, replacement, myContext); + Replacer.handleComments(elementToReplace, replacement, info); elementToReplace.replace(replacement); } else { @@ -178,7 +178,7 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile { else if (statements.length == 1) { PsiElement replacement = statements[0]; - Replacer.handleComments(elementToReplace, replacement, context); + Replacer.handleComments(elementToReplace, replacement, info); try { elementParent.addBefore(replacement, elementToReplace); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ReplacementInfo.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ReplacementInfo.java index 2fd1c7f5b7e1..714c0f67a531 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ReplacementInfo.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ReplacementInfo.java @@ -1,15 +1,25 @@ +// Copyright 2000-2017 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.plugin.replace; import com.intellij.psi.PsiElement; +import com.intellij.structuralsearch.MatchResult; import org.jetbrains.annotations.Nullable; -public abstract class ReplacementInfo { - public abstract String getReplacement(); +public interface ReplacementInfo { + String getReplacement(); - public abstract void setReplacement(String replacement); + void setReplacement(String replacement); @Nullable - public abstract PsiElement getMatch(int index); + PsiElement getMatch(int index); - public abstract int getMatchesCount(); + int getMatchesCount(); + + MatchResult getNamedMatchResult(String name); + + MatchResult getMatchResult(); + + String getVariableName(PsiElement element); + + String getSearchPatternName(String sourceName); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java index 57171c999199..2c201100f80f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 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.plugin.replace.impl; import com.intellij.codeInsight.template.Template; @@ -30,11 +16,11 @@ import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil; import com.intellij.structuralsearch.impl.matcher.PatternTreeContext; import com.intellij.structuralsearch.impl.matcher.predicates.ScriptSupport; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; +import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; +import com.intellij.util.SmartList; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,7 +32,7 @@ import java.util.Map; */ public final class ReplacementBuilder { private final String replacement; - private final List parameterizations = new ArrayList<>(); + private final List parameterizations = new SmartList<>(); private final Map replacementVarsMap; private final ReplaceOptions options; private final Project myProject; @@ -105,7 +91,7 @@ public final class ReplacementBuilder { parameterizations.add(info); } - final StructuralSearchProfile profile = parameterizations != null ? StructuralSearchUtil.getProfileByFileType(fileType) : null; + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); if (profile != null) { try { final PsiElement[] elements = MatcherImplUtil.createTreeFromText( @@ -140,50 +126,30 @@ public final class ReplacementBuilder { } } - private static void fill(MatchResult r,Map m) { - if (r.getName()!=null) { - m.putIfAbsent(r.getName(), r); - } - - if (!r.isScopeMatch() || !r.isMultipleMatch()) { - for (final MatchResult matchResult : r.getAllSons()) { - fill(matchResult, m); - } - } else if (r.hasSons()) { - final List allSons = r.getAllSons(); - if (allSons.size() > 0) { - fill(allSons.get(0),m); - } - } - } - - String process(MatchResult match, ReplacementInfoImpl replacementInfo, FileType type) { - if (parameterizations==null) { + String process(MatchResult match, ReplacementInfo replacementInfo, FileType type) { + if (parameterizations.isEmpty()) { return replacement; } final StringBuilder result = new StringBuilder(replacement); - final HashMap matchMap = new HashMap<>(); - fill(match, matchMap); final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(type); assert profile != null; int offset = 0; for (final ParameterInfo info : parameterizations) { - MatchResult r = matchMap.get(info.getName()); + final MatchResult r = replacementInfo.getNamedMatchResult(info.getName()); if (info.isReplacementVariable()) { offset = Replacer.insertSubstitution(result, offset, info, generateReplacement(info, match)); } else if (r != null) { - offset = profile.handleSubstitution(info, r, result, offset, matchMap); + offset = profile.handleSubstitution(info, r, result, offset, replacementInfo); } else { offset = profile.handleNoSubstitution(info, offset, result); } } - replacementInfo.variableMap = matchMap; return result.toString(); } @@ -208,8 +174,4 @@ public final class ReplacementBuilder { return null; } - - public void addParametrization(@NotNull ParameterInfo e) { - parameterizations.add(e); - } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java index 70e22f71e68b..415bd5cee6ea 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java @@ -1,19 +1,18 @@ +// Copyright 2000-2017 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.plugin.replace.impl; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiNamedElement; -import com.intellij.structuralsearch.MatchResult; -import com.intellij.structuralsearch.StructuralSearchUtil; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; -import java.util.HashMap; -import java.util.Map; - public class ReplacementContext { - ReplacementInfoImpl replacementInfo; - ReplaceOptions options; - Project project; + + private final ReplaceOptions options; + private final Project project; + + ReplacementContext(ReplaceOptions _options, Project _project) { + options = _options; + project = _project; + } public ReplaceOptions getOptions() { return options; @@ -22,29 +21,4 @@ public class ReplacementContext { public Project getProject() { return project; } - - ReplacementContext(ReplaceOptions _options, Project _project) { - options = _options; - project = _project; - } - - public Map getNewName2PatternNameMap() { - Map newNameToSearchPatternNameMap = new HashMap<>(1); - final Map variableMap = replacementInfo.getVariableMap(); - - if (variableMap != null) { - for (String s : variableMap.keySet()) { - final MatchResult matchResult = replacementInfo.getVariableMap().get(s); - PsiElement match = matchResult.getMatch(); - match = StructuralSearchUtil.getParentIfIdentifier(match); - - if (match instanceof PsiNamedElement) { - final String name = ((PsiNamedElement)match).getName(); - - newNameToSearchPatternNameMap.put(name, s); - } - } - } - return newNameToSearchPatternNameMap; - } -} +} \ No newline at end of file diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementInfoImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementInfoImpl.java index 2a151aa70a4b..41af61a682cb 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementInfoImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementInfoImpl.java @@ -1,27 +1,49 @@ +// Copyright 2000-2017 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.plugin.replace.impl; -import com.intellij.psi.PsiElement; -import com.intellij.psi.SmartPsiElementPointer; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; import com.intellij.structuralsearch.MatchResult; +import com.intellij.structuralsearch.StructuralSearchUtil; import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; +import com.intellij.util.SmartList; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; -public class ReplacementInfoImpl extends ReplacementInfo { - List matchesPtrList; - String result; - MatchResult matchResult; - Map variableMap; - Map elementToVariableNameMap; +class ReplacementInfoImpl implements ReplacementInfo { + private final MatchResult matchResult; + private final List matchesPtrList = new SmartList<>(); + private final Map variableMap = new HashMap<>(); + private final Map elementToVariableNameMap = new HashMap<>(1); + private final Map sourceNameToSearchPatternNameMap = new HashMap<>(1); - public String getReplacement() { - return result; + private String replacement; + + ReplacementInfoImpl(MatchResult matchResult, Project project) { + this.matchResult = matchResult; + init(project); } + private void init(Project project) { + fillPointerList(project); + fillVariableMap(matchResult); + for(Map.Entry entry : variableMap.entrySet()) { + fillElementToVariableNameMap(entry.getKey(), entry.getValue()); + } + } + + @Override + public String getReplacement() { + return replacement; + } + + @Override public void setReplacement(String replacement) { - result = replacement; + this.replacement = replacement; } @Nullable @@ -35,11 +57,88 @@ public class ReplacementInfoImpl extends ReplacementInfo { return matchesPtrList.size(); } - public Map getVariableMap() { - return variableMap; + @Override + public MatchResult getNamedMatchResult(String name) { + return variableMap.get(name); } + @Override public MatchResult getMatchResult() { return matchResult; } + + @Override + public String getVariableName(PsiElement element) { + return elementToVariableNameMap.get(element); + } + + @Override + public String getSearchPatternName(String sourceName) { + return sourceNameToSearchPatternNameMap.get(sourceName); + } + + private void fillPointerList(Project project) { + final SmartPointerManager manager = SmartPointerManager.getInstance(project); + + if (MatchResult.MULTI_LINE_MATCH.equals(matchResult.getName())) { + final Iterator i = matchResult.getAllSons().iterator(); + while (i.hasNext()) { + final MatchResult r = i.next(); + + if (MatchResult.LINE_MATCH.equals(r.getName())) { + PsiElement element = r.getMatch(); + + if (element instanceof PsiDocCommentBase) { // doc comment is not collapsed when created in block + if (i.hasNext()) { + final MatchResult son = i.next(); + + if (MatchResult.LINE_MATCH.equals(son.getName()) && StructuralSearchUtil.isDocCommentOwner(son.getMatch())) { + element = son.getMatch(); + } else { + matchesPtrList.add(manager.createSmartPsiElementPointer(element)); + element = son.getMatch(); + } + } + } + matchesPtrList.add(manager.createSmartPsiElementPointer(element)); + } + } + } else { + matchesPtrList.add(manager.createSmartPsiElementPointer(matchResult.getMatch())); + } + } + + private void fillElementToVariableNameMap(final String name, final MatchResult matchResult) { + final boolean multiMatch = matchResult.isMultipleMatch() || matchResult.isScopeMatch(); + if (matchResult.hasSons() && multiMatch) { + for (MatchResult r : matchResult.getAllSons()) { + fillElementToVariableNameMap(name, r); + } + } else if (!multiMatch && matchResult.getMatchRef() != null) { + elementToVariableNameMap.put(matchResult.getMatch(), name); + } + } + + private void fillVariableMap(MatchResult r) { + final String name = r.getName(); + if (name != null) { + variableMap.putIfAbsent(name, r); + + final PsiElement element = StructuralSearchUtil.getParentIfIdentifier(r.getMatch()); + if (element instanceof PsiNamedElement) { + sourceNameToSearchPatternNameMap.put(((PsiNamedElement)element).getName(), name); + } + } + + if (!r.isScopeMatch() || !r.isMultipleMatch()) { + for (final MatchResult matchResult : r.getAllSons()) { + fillVariableMap(matchResult); + } + } else if (r.hasSons()) { + final List allSons = r.getAllSons(); + if (allSons.size() > 0) { + fillVariableMap(allSons.get(0)); + } + } + } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java index e34b4e386a13..027dc7cc1b2c 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java @@ -40,10 +40,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; /** * @author Maxim.Mossienko @@ -74,7 +71,7 @@ public class Replacer { } public String testReplace(String in, String what, String by, ReplaceOptions options) throws IncorrectOperationException { - return testReplace(in, what, by, options,false); + return testReplace(in, what, by, options, false); } public String testReplace(String in, String what, String by, ReplaceOptions options, boolean filePattern) { @@ -220,9 +217,8 @@ public class Replacer { } @Nullable - private PsiElement doReplace(final ReplacementInfo info) { - final ReplacementInfoImpl replacementInfo = (ReplacementInfoImpl)info; - final PsiElement element = replacementInfo.matchesPtrList.get(0).getElement(); + private PsiElement doReplace(ReplacementInfo info) { + final PsiElement element = info.getMatch(0); if (element==null || !element.isWritable() || !element.isValid()) return null; @@ -230,10 +226,8 @@ public class Replacer { CodeStyleManager.getInstance(project).performActionWithFormatterDisabled( (Runnable)() -> { - context.replacementInfo = replacementInfo; - if (replaceHandler != null) { - replaceHandler.replace(replacementInfo, options); + replaceHandler.replace(info, options); } } ); @@ -268,28 +262,17 @@ public class Replacer { context = new ReplacementContext(options, project); } if (replaceHandler == null) { - StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(psiContext); + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(psiContext); if (profile != null) { - replaceHandler = profile.getReplaceHandler(this.context); + replaceHandler = profile.getReplaceHandler(context); } } } - public static void handleComments(final PsiElement el, final PsiElement replacement, ReplacementContext context) throws IncorrectOperationException { - ReplacementInfoImpl replacementInfo = context.replacementInfo; - if (replacementInfo.elementToVariableNameMap == null) { - replacementInfo.elementToVariableNameMap = new HashMap<>(1); - Map variableMap = replacementInfo.variableMap; - if (variableMap != null) { - for(String name:variableMap.keySet()) { - fill(name,replacementInfo.variableMap.get(name),replacementInfo.elementToVariableNameMap); - } - } - } - - PsiElement lastChild = el.getLastChild(); + public static void handleComments(final PsiElement el, final PsiElement replacement, ReplacementInfo replacementInfo) { + final PsiElement lastChild = el.getLastChild(); if (lastChild instanceof PsiComment && - replacementInfo.elementToVariableNameMap.get(lastChild) == null && + replacementInfo.getVariableName(lastChild) == null && !(replacement.getLastChild() instanceof PsiComment) ) { PsiElement firstElementAfterStatementEnd = lastChild; @@ -303,7 +286,7 @@ public class Replacer { final PsiElement firstChild = el.getFirstChild(); if (firstChild instanceof PsiComment && !(firstChild instanceof PsiDocCommentBase) && - replacementInfo.elementToVariableNameMap.get(firstChild) == null + replacementInfo.getVariableName(firstChild) == null ) { PsiElement lastElementBeforeStatementStart = firstChild; @@ -315,17 +298,6 @@ public class Replacer { } } - private static void fill(final String name, final MatchResult matchResult, final Map elementToVariableNameMap) { - boolean b = matchResult.isMultipleMatch() || matchResult.isScopeMatch(); - if(matchResult.hasSons() && b) { - for(MatchResult r:matchResult.getAllSons()) { - fill(name, r, elementToVariableNameMap); - } - } else if (!b && matchResult.getMatchRef() != null) { - elementToVariableNameMap.put(matchResult.getMatch(),name); - } - } - public static void checkSupportedReplacementPattern(Project project, ReplaceOptions options) throws UnsupportedPatternException { try { String search = options.getMatchOptions().getSearchPattern(); @@ -384,44 +356,12 @@ public class Replacer { } public ReplacementInfo buildReplacement(MatchResult result) { - List l = new SmartList<>(); - SmartPointerManager manager = SmartPointerManager.getInstance(project); + final ReplacementInfoImpl replacementInfo = new ReplacementInfoImpl(result, project); - if (MatchResult.MULTI_LINE_MATCH.equals(result.getName())) { - for(Iterator i=result.getAllSons().iterator();i.hasNext();) { - final MatchResult r = i.next(); - - if (MatchResult.LINE_MATCH.equals(r.getName())) { - PsiElement element = r.getMatch(); - - if (element instanceof PsiDocCommentBase) { // doc comment is not collapsed when created in block - if (i.hasNext()) { - MatchResult matchResult = i.next(); - - if (MatchResult.LINE_MATCH.equals(matchResult.getName()) && - StructuralSearchUtil.isDocCommentOwner(matchResult.getMatch())) { - element = matchResult.getMatch(); - } else { - l.add( manager.createSmartPsiElementPointer(element) ); - element = matchResult.getMatch(); - } - } - } - l.add( manager.createSmartPsiElementPointer(element) ); - } - } - } else { - l.add(manager.createSmartPsiElementPointer(result.getMatch())); - } - - ReplacementInfoImpl replacementInfo = new ReplacementInfoImpl(); - - replacementInfo.matchesPtrList = l; if (replacementBuilder==null) { - replacementBuilder = new ReplacementBuilder(project,options); + replacementBuilder = new ReplacementBuilder(project, options); } - replacementInfo.result = replacementBuilder.process(result, replacementInfo, options.getMatchOptions().getFileType()); - replacementInfo.matchResult = result; + replacementInfo.setReplacement(replacementBuilder.process(result, replacementInfo, options.getMatchOptions().getFileType())); return replacementInfo; }