diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 00000000..ca75f5dd --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2026-05-09 - Avoid Pre-compiled Regex for Literal Replacements +**Learning:** In modern JDKs (Java 21 used here), `String.replace()` without regex compilation overhead is significantly faster and cleaner for exact string matches than `Pattern.compile().matcher().replaceAll()`. +**Action:** When finding micro-optimizations, look for regex replacements that use literal escaping (e.g., `\Q...\E` or literal `.*` replacements) and convert them to simple `String.replace()`. diff --git a/org.moreunit.core.test/test/org/moreunit/core/matching/FileNameEvaluationTest.java b/org.moreunit.core.test/test/org/moreunit/core/matching/FileNameEvaluationTest.java index 88be55cf..68431673 100644 --- a/org.moreunit.core.test/test/org/moreunit/core/matching/FileNameEvaluationTest.java +++ b/org.moreunit.core.test/test/org/moreunit/core/matching/FileNameEvaluationTest.java @@ -42,4 +42,25 @@ public void should_convert_regex_to_eclipse_search_pattern() throws Exception // then assertThat(eval.getAllCorrespondingFileEclipsePatterns()).containsExactly("Pre*File*Suf", "Pre*File", "File*Suf"); } + + @Test + public void should_identify_as_test_file() throws Exception + { + // given + FileNameEvaluation eval = new FileNameEvaluation("IrrelevantTest", true, "Irrelevant", NO_PATTERNS, NO_PATTERNS); + + // then + assertThat(eval.isTestFile()).isTrue(); + assertThat(eval.getPreferredCorrespondingFileName()).isEqualTo("Irrelevant"); + } + + @Test + public void should_generate_to_string() throws Exception + { + // given + FileNameEvaluation eval = new FileNameEvaluation("IrrelevantTest", true, "Irrelevant", NO_PATTERNS, NO_PATTERNS); + + // then + assertThat(eval.toString()).contains("IrrelevantTest"); + } } diff --git a/org.moreunit.core/src/org/moreunit/core/matching/FileNameEvaluation.java b/org.moreunit.core/src/org/moreunit/core/matching/FileNameEvaluation.java index 47c8533f..40b6d674 100644 --- a/org.moreunit.core/src/org/moreunit/core/matching/FileNameEvaluation.java +++ b/org.moreunit.core/src/org/moreunit/core/matching/FileNameEvaluation.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.regex.Pattern; import org.moreunit.core.util.StringConstants; @@ -21,10 +20,6 @@ */ public final class FileNameEvaluation { - private static final Pattern QUOTE_SEPARATORS = Pattern.compile("(?:\\\\Q|\\\\E)"); - private static final Pattern SUCCESSIVE_QUOTE_SEPARATORS = Pattern.compile("\\\\E\\\\Q"); - private static final Pattern WILDCARDS = Pattern.compile("\\.\\*"); - private final String evaluatedFileName; private final boolean testFile; private final Collection otherCorrespondingFilePatterns; @@ -42,10 +37,11 @@ public FileNameEvaluation(String evaluatedFileName, boolean testFile, String pre private static Collection simplify(Collection patterns) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (String pattern : patterns) { - result.add(SUCCESSIVE_QUOTE_SEPARATORS.matcher(pattern).replaceAll("")); + // Replaces regex matching of \E\Q with literal replacement + result.add(pattern.replace("\\E\\Q", "")); } return result; } @@ -83,7 +79,8 @@ public List getAllCorrespondingFileEclipsePatterns() private String convertWildcards(String str) { - return WILDCARDS.matcher(str).replaceAll("*"); + // Replaces regex matching of .* with literal replacement + return str.replace(".*", "*"); } /** @@ -126,7 +123,8 @@ public String getPreferredCorrespondingFileName() private String removeQuotes(String str) { - return QUOTE_SEPARATORS.matcher(str).replaceAll(""); + // Replaces regex matching of (?:\\Q|\\E) with literal replacement + return str.replace("\\Q", "").replace("\\E", ""); } @Override