From 428d97f73d8da129da928fa6021bd2c5d47bd91f Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 5 Nov 2018 20:12:52 +0100 Subject: [PATCH] SSR: lenient comment and string literal matching --- .../impl/matcher/JavaMatchingVisitor.java | 6 ++-- .../StructuralSearchUtil.java | 32 +++++++++++++++++++ .../impl/matcher/CompiledPattern.java | 1 - .../StructuralReplaceTest.java | 2 -- .../StructuralSearchTest.java | 5 +++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index ec287e5a89f9..bd3db5560bc9 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -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)); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java index 80211a035fec..7cfd9c38caa8 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java @@ -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 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)); + } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java index 6202880c2dbc..ce9d42a5622f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java @@ -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; diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 8096548e6b10..19aac03acec8 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -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" + diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 26fd7228d8a7..8e5c54c9216e 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -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() {