summaryrefslogtreecommitdiff
path: root/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java')
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java218
1 files changed, 218 insertions, 0 deletions
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
new file mode 100644
index 000000000000..e72fd5555531
--- /dev/null
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java
@@ -0,0 +1,218 @@
+package com.intellij.structuralsearch.plugin.replace.impl;
+
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.structuralsearch.MalformedPatternException;
+import com.intellij.structuralsearch.MatchResult;
+import com.intellij.structuralsearch.StructuralSearchProfile;
+import com.intellij.structuralsearch.StructuralSearchUtil;
+import com.intellij.structuralsearch.impl.matcher.MatchResultImpl;
+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.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author maxim
+ * Date: 24.02.2004
+ * Time: 15:34:57
+ */
+public final class ReplacementBuilder {
+ private String replacement;
+ private List<ParameterInfo> parameterizations;
+ private final Map<String, ScriptSupport> replacementVarsMap;
+ private final ReplaceOptions options;
+
+ ReplacementBuilder(final Project project,final ReplaceOptions options) {
+ replacementVarsMap = new HashMap<String, ScriptSupport>();
+ this.options = options;
+ String _replacement = options.getReplacement();
+ FileType fileType = options.getMatchOptions().getFileType();
+
+ final Template template = TemplateManager.getInstance(project).createTemplate("","",_replacement);
+
+ final int segmentsCount = template.getSegmentsCount();
+ replacement = template.getTemplateText();
+
+ for(int i=0;i<segmentsCount;++i) {
+ final int offset = template.getSegmentOffset(i);
+ final String name = template.getSegmentName(i);
+
+ final ParameterInfo info = new ParameterInfo();
+ info.setStartIndex(offset);
+ info.setName(name);
+ info.setReplacementVariable(options.getVariableDefinition(name) != null);
+
+ // find delimiter
+ int pos;
+ for(pos = offset-1; pos >=0 && pos < replacement.length() && Character.isWhitespace(replacement.charAt(pos));) {
+ --pos;
+ }
+
+ if (pos >= 0) {
+ if (replacement.charAt(pos) == ',') {
+ info.setHasCommaBefore(true);
+ }
+ info.setBeforeDelimiterPos(pos);
+ }
+
+ for(pos = offset; pos < replacement.length() && Character.isWhitespace(replacement.charAt(pos));) {
+ ++pos;
+ }
+
+ if (pos < replacement.length()) {
+ final char ch = replacement.charAt(pos);
+
+ if (ch == ';') {
+ info.setStatementContext(true);
+ }
+ else if (ch == ',' || ch == ')') {
+ info.setArgumentContext(true);
+ info.setHasCommaAfter(ch == ',');
+ }
+ info.setAfterDelimiterPos(pos);
+ }
+
+ if (parameterizations==null) {
+ parameterizations = new ArrayList<ParameterInfo>();
+ }
+
+ parameterizations.add(info);
+ }
+
+ final StructuralSearchProfile profile = parameterizations != null ? StructuralSearchUtil.getProfileByFileType(fileType) : null;
+ if (profile != null) {
+ try {
+ final PsiElement[] elements = MatcherImplUtil.createTreeFromText(
+ _replacement,
+ PatternTreeContext.Block,
+ fileType,
+ options.getMatchOptions().getDialect(),
+ options.getMatchOptions().getPatternContext(),
+ project,
+ false
+ );
+ if (elements.length > 0) {
+ final PsiElement patternNode = elements[0].getParent();
+ profile.provideAdditionalReplaceOptions(patternNode, options, this);
+ }
+ } catch (IncorrectOperationException e) {
+ throw new MalformedPatternException();
+ }
+ }
+ }
+
+ private static void fill(MatchResult r,Map<String,MatchResult> m) {
+ if (r.getName()!=null) {
+ if (m.get(r.getName()) == null) {
+ m.put(r.getName(), r);
+ }
+ }
+
+ if (!r.isScopeMatch() || !r.isMultipleMatch()) {
+ for (final MatchResult matchResult : r.getAllSons()) {
+ fill(matchResult, m);
+ }
+ } else if (r.hasSons()) {
+ final List<MatchResult> allSons = r.getAllSons();
+ if (allSons.size() > 0) {
+ fill(allSons.get(0),m);
+ }
+ }
+ }
+
+ String process(MatchResult match, ReplacementInfoImpl replacementInfo, FileType type) {
+ if (parameterizations==null) {
+ return replacement;
+ }
+
+ final StringBuilder result = new StringBuilder(replacement);
+ HashMap<String, MatchResult> matchMap = new HashMap<String, MatchResult>();
+ fill(match, matchMap);
+
+ int offset = 0;
+
+ final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(type);
+
+ for (final ParameterInfo info : parameterizations) {
+ MatchResult r = matchMap.get(info.getName());
+ if (info.isReplacementVariable()) {
+ offset = Replacer.insertSubstitution(result, offset, info, generateReplacement(info, match));
+ }
+ else if (r != null) {
+ offset = profile != null ? profile.handleSubstitution(info, r, result, offset, matchMap) : StructuralSearchProfile.defaultHandleSubstitution(info, r, result, offset);
+ }
+ else {
+ if (info.isHasCommaBefore()) {
+ result.delete(info.getBeforeDelimiterPos() + offset, info.getBeforeDelimiterPos() + 1 + offset);
+ --offset;
+ }
+ else if (info.isHasCommaAfter()) {
+ result.delete(info.getAfterDelimiterPos() + offset, info.getAfterDelimiterPos() + 1 + offset);
+ --offset;
+ }
+ else if (info.isVariableInitializerContext()) {
+ //if (info.afterDelimiterPos > 0) {
+ result.delete(info.getBeforeDelimiterPos() + offset, info.getAfterDelimiterPos() + offset - 1);
+ offset -= (info.getAfterDelimiterPos() - info.getBeforeDelimiterPos() - 1);
+ //}
+ } else if (profile != null) {
+ offset = profile.processAdditionalOptions(info, offset, result, r);
+ }
+ offset = Replacer.insertSubstitution(result, offset, info, "");
+ }
+ }
+
+ replacementInfo.variableMap = (HashMap<String, MatchResult>)matchMap.clone();
+ matchMap.clear();
+ return result.toString();
+ }
+
+ private String generateReplacement(ParameterInfo info, MatchResult match) {
+ ScriptSupport scriptSupport = replacementVarsMap.get(info.getName());
+
+ if (scriptSupport == null) {
+ String constraint = options.getVariableDefinition(info.getName()).getScriptCodeConstraint();
+ scriptSupport = new ScriptSupport(StringUtil.stripQuotesAroundValue(constraint), info.getName());
+ replacementVarsMap.put(info.getName(), scriptSupport);
+ }
+ return scriptSupport.evaluate((MatchResultImpl)match, null);
+ }
+
+ @Nullable
+ public ParameterInfo findParameterization(String name) {
+ if (parameterizations==null) return null;
+
+ for (final ParameterInfo info : parameterizations) {
+
+ if (info.getName().equals(name)) {
+ return info;
+ }
+ }
+
+ return null;
+ }
+
+ public void clear() {
+ replacement = null;
+
+ if (parameterizations!=null) {
+ parameterizations.clear();
+ parameterizations = null;
+ }
+ }
+
+ public void addParametrization(@NotNull ParameterInfo e) {
+ assert parameterizations != null;
+ parameterizations.add(e);
+ }
+}