SSR: lenient comment and string literal matching

This commit is contained in:
Bas Leijdekkers
2018-11-07 21:07:58 +01:00
parent 6ddc5f1c23
commit 428d97f73d
5 changed files with 41 additions and 5 deletions
@@ -82,7 +82,8 @@ public class JavaMatchingVisitor extends JavaElementVisitor {
myMatchingVisitor.setResult(handler.match(comment, comment2, myMatchingVisitor.getMatchContext()));
}
else {
myMatchingVisitor.setResult(myMatchingVisitor.matchText(comment, comment2));
myMatchingVisitor.setResult(myMatchingVisitor.matchText(StructuralSearchUtil.normalize(JavaMatchUtil.getCommentText(comment)),
StructuralSearchUtil.normalize(JavaMatchUtil.getCommentText(comment2))));
}
}
@@ -1108,7 +1109,8 @@ public class JavaMatchingVisitor extends JavaElementVisitor {
final Object value1 = const1.getValue();
final Object value2 = const2.getValue();
if ((value1 instanceof String || value1 instanceof Character) && (value2 instanceof String || value2 instanceof Character)) {
myMatchingVisitor.setResult(myMatchingVisitor.matchText(value1.toString(), value2.toString()));
myMatchingVisitor.setResult(myMatchingVisitor.matchText(StructuralSearchUtil.normalize(value1.toString()),
StructuralSearchUtil.normalize(value2.toString())));
}
else if (value1 != null && value2 != null) {
myMatchingVisitor.setResult(value1.equals(value2));
@@ -7,6 +7,7 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.structuralsearch.plugin.ui.Configuration;
import org.jetbrains.annotations.Contract;
@@ -14,7 +15,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.text.Normalizer;
import java.util.*;
import java.util.regex.Pattern;
/**
* @author Eugene.Kudelevsky
@@ -22,6 +25,7 @@ import java.util.*;
public class StructuralSearchUtil {
private static final String REG_EXP_META_CHARS = ".$|()[]{}^?*+\\";
private static final Key<StructuralSearchProfile> STRUCTURAL_SEARCH_PROFILE_KEY = new Key<>("Structural Search Profile");
private static final Pattern ACCENTS = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
private static LanguageFileType ourDefaultFileType = null;
public static boolean ourUseUniversalMatchingAlgorithm = false;
@@ -189,4 +193,32 @@ public class StructuralSearchUtil {
final StructuralSearchProfile profile = getProfileByPsiElement(matchedNode);
return profile != null ? profile.getAlternativeText(matchedNode, previousText) : null;
}
public static String normalizeWhiteSpace(@NotNull String text) {
text = text.trim();
final StringBuilder result = new StringBuilder();
boolean white = false;
for (int i = 0, length = text.length(); i < length; i++) {
char c = text.charAt(i);
if (StringUtil.isWhiteSpace(c)) {
if (!white) {
result.append(' ');
white = true;
}
}
else {
white = false;
result.append(c);
}
}
return result.toString();
}
public static String stripAccents(@NotNull String input) {
return ACCENTS.matcher(Normalizer.normalize(input, Normalizer.Form.NFD)).replaceAll("");
}
public static String normalize(@NotNull String text) {
return stripAccents(normalizeWhiteSpace(text));
}
}
@@ -18,7 +18,6 @@ import com.intellij.util.containers.MultiMap;
import gnu.trove.THashMap;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
@@ -1505,8 +1505,6 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
String expectedResult2 = "class A {\n" +
" void a() {\n" +
" }\n" +
" /*\n" +
" */\n" +
" int b = 1;\n" +
" /*\n" +
" *\n" +
@@ -1458,6 +1458,11 @@ public class StructuralSearchTest extends StructuralSearchTestCase {
" }\n" +
"}";
assertEquals("statement match with comment", 1, findMatchesCount(s18,s19));
String s20 = "class X {" +
" /* H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ */" +
"}";
assertEquals("match comments ignoring accents and differences in whitespace", 1, findMatchesCount(s20, "/*he\ncomes*/"));
}
public void testOther() {