Skip to content

Commit

Permalink
Support curly brace in PathUtils#matchesGlob
Browse files Browse the repository at this point in the history
commit a5bc3546a4dc8d6504b49242c84ef9ae2edb2cb5
Author: Jonathan Schneider <[email protected]>
Date:   Sun Mar 3 09:46:04 2024 -0500

    Maintain approximately same performance when negation or braces are not used in glob

commit f2af6f20da12e84b640c74f9bd9c47ee7593953a
Author: Yelan Tao <[email protected]>
Date:   Thu Feb 8 13:31:35 2024 +0100

    support cases where both negation and either or appear

commit 803a061bbf340c025262f94fa8106bd05cd9d717
Author: Yelan Tao <[email protected]>
Date:   Wed Feb 7 13:06:30 2024 +0100

    Support curly brace in glob matcher
  • Loading branch information
jkschneider committed Mar 3, 2024
1 parent 8de6df1 commit 3ad7163
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 11 deletions.
59 changes: 49 additions & 10 deletions rewrite-core/src/main/java/org/openrewrite/PathUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Collections.emptyList;

public class PathUtils {
private PathUtils() {
}
Expand Down Expand Up @@ -69,18 +73,27 @@ public static boolean matchesGlob(@Nullable Path path, @Nullable String globPatt
if ("**".equals(globPattern)) {
return true;
}
if (globPattern == null) {
return false;
}
if (path == null) {
if (globPattern == null || path == null) {
return false;
}

String relativePath = path.toString();
if (relativePath.isEmpty() && globPattern.isEmpty()) {
return true;
}

List<String> eitherOrPatterns = getEitherOrPatterns(globPattern);
List<String> excludedPatterns = getExcludedPatterns(globPattern);
if (!excludedPatterns.isEmpty()) {
if (eitherOrPatterns.isEmpty() && excludedPatterns.isEmpty()) {
return matchesGlob(globPattern, relativePath);
} else if (!eitherOrPatterns.isEmpty()) {
for (String eitherOrPattern : eitherOrPatterns) {
if (matchesGlob(Paths.get(relativePath), eitherOrPattern)) {
return true;
}
}
return false;
} else { // If eitherOrPatterns is empty and excludedPatterns is not
if (!matchesGlob(convertNegationToWildcard(globPattern), relativePath)) {
return false;
}
Expand All @@ -89,10 +102,8 @@ public static boolean matchesGlob(@Nullable Path path, @Nullable String globPatt
return false;
}
}
return true;
}

return matchesGlob(globPattern, relativePath);
return true;
}

private static boolean matchesGlob(String pattern, String path) {
Expand Down Expand Up @@ -142,7 +153,7 @@ private static boolean matchesGlob(String pattern, String path) {
return false;
}
if (pattIdxEnd == (pattTokens.length - 1)
&& (isFileSeparator(pattern.charAt(pattern.length() - 1)) ^ isFileSeparator(path.charAt(path.length() - 1)))) {
&& (isFileSeparator(pattern.charAt(pattern.length() - 1)) ^ isFileSeparator(path.charAt(path.length() - 1)))) {
return false;
}
pattIdxEnd--;
Expand Down Expand Up @@ -210,7 +221,11 @@ public static String convertNegationToWildcard(String globPattern) {
}

public static List<String> getExcludedPatterns(String globPattern) {
List<String> excludedPatterns = new ArrayList<>();
if (!globPattern.contains("!")) {
return emptyList();
}

List<String> excludedPatterns = new ArrayList<>(3);

// Regular expression to match !(...)
String negationPattern = "\\!\\((.*?)\\)";
Expand All @@ -229,6 +244,30 @@ public static List<String> getExcludedPatterns(String globPattern) {
return excludedPatterns;
}

public static List<String> getEitherOrPatterns(String globPattern) {
if (!globPattern.contains("{")) {
return emptyList();
}

List<String> eitherOrPatterns = new ArrayList<>(3);

// Regular expression to match {...}
String eitherOrPattern = "\\{(.*?)\\}";
Pattern pattern = Pattern.compile(eitherOrPattern);
Matcher matcher = pattern.matcher(globPattern);

// Find all possible patterns and generate patterns
while (matcher.find()) {
String eitherOrContent = matcher.group(1);
String[] options = eitherOrContent.split("\\,");
for (String option : options) {
eitherOrPatterns.add(globPattern.replace(matcher.group(), option));
}
}

return eitherOrPatterns;
}

private static String[] tokenize(String path) {
List<String> tokens = new ArrayList<>();
int pathIdxStart = 0;
Expand Down
16 changes: 15 additions & 1 deletion rewrite-core/src/test/java/org/openrewrite/PathUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ void globMatching() {

@Test
@Issue("https://github.com/openrewrite/rewrite/pull/3758")
@Disabled("{} syntax not supported yet")
void eitherOr() {
// matches with {}'s, used in for instance `"**/{application,application-*,bootstrap,bootstrap-*}.{yml,yaml}"`
assertThat(matchesGlob(path("test/"), "test/{foo,bar}")).isFalse();
Expand All @@ -122,6 +121,21 @@ void negation() {
assertThat(matchesGlob(path("test/bar"), "test/!(f*|b*)")).isFalse();
}

@Test
void combinedTest() {
assertThat(matchesGlob(path("a/b/java"), "{a,b}/!(c)/java")).isTrue();
assertThat(matchesGlob(path("a/c/java"), "{a,b}/!(c)/java")).isFalse();
assertThat(matchesGlob(path("b/d/java"), "{a,b}/!(c)/java")).isTrue();
assertThat(matchesGlob(path("b/c/java"), "{a,b}/!(c)/java")).isFalse();
assertThat(matchesGlob(path("a/b/java"), "{a,b}/!(c)/java")).isTrue();
assertThat(matchesGlob(path("a/java"), "!(a|b|c)/{java,txt}")).isFalse();
assertThat(matchesGlob(path("b/java"), "!(a|b|c)/{java,txt}")).isFalse();
assertThat(matchesGlob(path("c/java"), "!(a|b|c)/{java,txt}")).isFalse();
assertThat(matchesGlob(path("d/java"), "!(a|b|c)/{java,txt}")).isTrue();
assertThat(matchesGlob(path("d/txt"), "!(a|b|c)/{java,txt}")).isTrue();
assertThat(matchesGlob(path("d/xml"), "!(a|b|c)/{java,txt}")).isFalse();
}

private static Path path(String path) {
return Paths.get(path);
}
Expand Down

0 comments on commit 3ad7163

Please sign in to comment.