diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index 9db4598c3e2f..c0d2bff82a89 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -628,6 +628,7 @@ public final class JavaStructuralSearchProfile extends StructuralSearchProfile { @Override public void provideAdditionalReplaceOptions(@NotNull PsiElement node, @NotNull ReplaceOptions options, @NotNull ReplacementBuilder builder) { + final StructuralSearchProfile profile = this; node.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { @@ -663,7 +664,7 @@ public final class JavaStructuralSearchProfile extends StructuralSearchProfile { @Override public void visitElement(@NotNull PsiElement element) { final String type = element.getText(); - if (MatchUtil.isTypedVariable(type)) { + if (profile.isReplacementTypedVariable(type)) { final ParameterInfo typeInfo = builder.findParameterization(element); if (typeInfo != null) { typeInfo.setArgumentContext(false); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchUtil.java index 4173b166007b..00379c5bf884 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchUtil.java @@ -14,10 +14,6 @@ public final class MatchUtil { private static final String REG_EXP_META_CHARS = ".$|()[]{}^?*+\\"; private static final Pattern ACCENTS = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); - public static boolean isTypedVariable(@NotNull String name) { - return name.length() > 1 && name.charAt(0) == '$' && name.charAt(name.length() - 1) == '$'; - } - public static boolean containsRegExpMetaChar(String s) { return s.chars().anyMatch(MatchUtil::isRegExpMetaChar); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java index 4ad5a7660a51..083420c3f4ba 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java @@ -421,4 +421,18 @@ public abstract class StructuralSearchProfile { public boolean isApplicableContextConfiguration(@NotNull Configuration configuration) { return !configuration.isPredefined(); } + + public boolean isReplacementTypedVariable(@NotNull String name) { + return name.length() > 1 && name.charAt(0) == '$' && name.charAt(name.length() - 1) == '$'; + } + + @NotNull + public String compileReplacementTypedVariable(@NotNull String name) { + return "$" + name + "$"; + } + + @NotNull + public String stripReplacementTypedVariableDecorations(@NotNull String name) { + return name.substring(1, name.length() - 1); + } } 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 6d96413e3c19..b755608bc5f7 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 @@ -94,15 +94,15 @@ public final class ReplacementBuilder { assert dialect != null; final PatternContextInfo context = new PatternContextInfo(PatternTreeContext.Block, options.getMatchOptions().getPatternContext()); final PsiElement[] elements = - MatcherImplUtil.createTreeFromText(options.getReplacement(), context, fileType, dialect, project, false); + MatcherImplUtil.createTreeFromText(prepareReplacementPattern(), context, fileType, dialect, project, false); if (elements.length > 0) { final PsiElement patternNode = elements[0].getParent(); patternNode.accept(new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(@NotNull PsiElement element) { final String text = element.getText(); - if (MatchUtil.isTypedVariable(text)) { - final Collection infos = findParameterization(Replacer.stripTypedVariableDecoration(text)); + if (profile.isReplacementTypedVariable(text)) { + final Collection infos = findParameterization(profile.stripReplacementTypedVariableDecorations(text)); for (ParameterInfo info : infos) { if (info.getElement() == null) { info.setElement(element); @@ -181,8 +181,33 @@ public final class ReplacementBuilder { public ParameterInfo findParameterization(PsiElement element) { if (element == null) return null; + StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(element); + assert profile != null; final String text = element.getText(); - if (!MatchUtil.isTypedVariable(text)) return null; - return ContainerUtil.find(findParameterization(Replacer.stripTypedVariableDecoration(text)), info -> info.getElement() == element); + if (!profile.isReplacementTypedVariable(text)) return null; + return ContainerUtil.find(findParameterization(profile.stripReplacementTypedVariableDecorations(text)), info -> info.getElement() == element); + } + + @NotNull + public String prepareReplacementPattern() { + final LanguageFileType fileType = options.getMatchOptions().getFileType(); + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); + assert profile != null; + + final StringBuilder buf = new StringBuilder(); + final Template template = TemplateManager.getInstance(myProject).createTemplate("", "", options.getReplacement()); + final int segmentsCount = template.getSegmentsCount(); + final String text = template.getTemplateText(); + + int prevOffset = 0; + for (int i = 0; i < segmentsCount; i++) { + final int offset = template.getSegmentOffset(i); + final String name = template.getSegmentName(i); + final String compiledName = profile.compileReplacementTypedVariable(name); + buf.append(text, prevOffset, offset).append(compiledName); + prevOffset = offset; + } + buf.append(text.substring(prevOffset)); + return buf.toString(); } } 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 1fa242b6da23..8ed3ceffcb08 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 @@ -55,10 +55,6 @@ public class Replacer { replacementBuilder = new ReplacementBuilder(this.project, this.options); } - public static String stripTypedVariableDecoration(final String type) { - return type.substring(1, type.length() - 1); - } - public static int insertSubstitution(StringBuilder result, int offset, final ParameterInfo info, String image) { if (!image.isEmpty()) { result.insert(offset + info.getStartIndex(), image);