diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunction.java index df1d1ebfb1d803..b0f1e618115177 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunction.java @@ -50,6 +50,7 @@ import java.util.Optional; import java.util.SequencedSet; import java.util.Set; +import java.util.regex.Pattern; import javax.annotation.Nullable; /** @@ -392,10 +393,24 @@ protected Code getDetailedCode() { private static String getMessage( PlatformInfo targetPlatformInfo, SequencedSet missingToolchainTypes) { + // All characters with special meaning anywhere in a regex (':' for example is only special within brackets). + List regexSpecialChars = "+.|([{^$?\\*".codePoints() + .mapToObj(c -> (char) c) + .toList(); ImmutableList labelStrings = missingToolchainTypes.stream() .map(ToolchainTypeInfo::typeLabel) .map(Label::toString) + .map(label -> { + // Regex-quote if label contains special characters. + for (char c : regexSpecialChars) { + if (label.indexOf(c) >= 0) { + return Pattern.quote(label); + } + } + + return label; + }) .collect(toImmutableList()); ImmutableList missingToolchainRows = missingToolchainTypes.stream() diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/BUILD index a4386fb222c4ff..91367dbff46603 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/BUILD +++ b/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/BUILD @@ -139,11 +139,13 @@ java_test( "//src/main/java/com/google/devtools/build/lib/analysis:platform_options", "//src/main/java/com/google/devtools/build/lib/analysis/config:build_options", "//src/main/java/com/google/devtools/build/lib/analysis/config:toolchain_type_requirement", + "//src/main/java/com/google/devtools/build/lib/analysis/platform", "//src/main/java/com/google/devtools/build/lib/cmdline", "//src/main/java/com/google/devtools/build/lib/skyframe/config", "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:constraint_value_lookup_util", "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:platform_lookup_util", "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:toolchain_context_key", + "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:toolchain_resolution_function", "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:toolchain_type_lookup_util", "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:unloaded_toolchain_context", "//src/main/java/com/google/devtools/build/skyframe", diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunctionTest.java index e1a6bf79e6f642..cd1dfb3feaabc7 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/toolchains/ToolchainResolutionFunctionTest.java @@ -18,9 +18,11 @@ import static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult; import com.google.common.collect.ImmutableList; -import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement; +import com.google.devtools.build.lib.analysis.platform.PlatformInfo; +import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo; +import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.rules.platform.ToolchainTestCase; import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey; @@ -30,6 +32,7 @@ import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils; import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.SkyKey; +import java.util.LinkedHashSet; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -396,6 +399,29 @@ public void resolve_mandatory_missing() throws Exception { """); } + @Test + public void unresolved_toolchain_message_regex_quotes() throws Exception { + PlatformInfo platformInfo = PlatformInfo.builder() + .setLabel(Label.parseCanonicalUnchecked("//platforms:test_platform")) + .build(); + ToolchainTypeInfo toolchainTypeInfo = ToolchainTypeInfo.create( + Label.parseCanonicalUnchecked("@@repo+//toolchain:test_toolchain")); + LinkedHashSet missingToolchainTypes = new LinkedHashSet<>(); + missingToolchainTypes.add(toolchainTypeInfo); + + var exception = new ToolchainResolutionFunction.UnresolvedToolchainsException(platformInfo, missingToolchainTypes); + + assertThat(exception) + .hasMessageThat() + .isEqualTo( +""" +No matching toolchains found for types: + @@repo+//toolchain:test_toolchain +To debug, rerun with --toolchain_resolution_debug='\\Q@@repo+//toolchain:test_toolchain\\E' +""" + ); + } + @Test public void resolve_mandatory_missing_customPlatformMessage() throws Exception { scratch.appendFile(