diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/instrumentation/JacocoInstrumentationProcessor.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/instrumentation/JacocoInstrumentationProcessor.java index 97ff75512e75d6..301b62ac992592 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/instrumentation/JacocoInstrumentationProcessor.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/instrumentation/JacocoInstrumentationProcessor.java @@ -34,6 +34,7 @@ import java.util.List; import org.jacoco.core.instr.Instrumenter; import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator; +import org.jacoco.core.runtime.WildcardMatcher; /** Instruments compiled java classes using Jacoco instrumentation library. */ public final class JacocoInstrumentationProcessor { @@ -48,14 +49,22 @@ public static JacocoInstrumentationProcessor create(List args) + ": pathsForCoverageFile"); } - return new JacocoInstrumentationProcessor(args.getFirst()); + String coverageIncludes = args.size() >= 2 ? args.get(1) : ""; + String coverageExcludes = args.size() >= 3 ? args.get(2) : ""; + + return new JacocoInstrumentationProcessor(args.getFirst(), coverageIncludes, coverageExcludes); } private Path instrumentedClassesDirectory; private final String coverageInformation; + private final WildcardMatcher includeMatcher; + private final WildcardMatcher excludeMatcher; - private JacocoInstrumentationProcessor(String coverageInfo) { + private JacocoInstrumentationProcessor(String coverageInfo, String coverageIncludes, + String coverageExcludes) { this.coverageInformation = coverageInfo; + this.includeMatcher = new WildcardMatcher(coverageIncludes.isBlank() ? "*" : coverageIncludes); + this.excludeMatcher = new WildcardMatcher(coverageExcludes); } /** @@ -110,6 +119,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) // it only once during recursive directory traversal while also mutating the directory. Path instrumentedCopy = file; Path absoluteUninstrumentedCopy = Path.of(file + ".uninstrumented"); + Path relativeClassFile = root.relativize(file); + String className = relativeClassFile.toString().replace(".class", ""); + if (!includeMatcher.matches(className) || excludeMatcher.matches(className)) { + return FileVisitResult.CONTINUE; + } + Path uninstrumentedCopy = instrumentedClassesDirectory.resolve(root.relativize(absoluteUninstrumentedCopy)); Files.createDirectories(uninstrumentedCopy.getParent()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java index 6ab3027d946006..7de04ba284b460 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java @@ -74,6 +74,8 @@ public final class JavaCompilationHelper { private boolean enableJspecify = true; private boolean enableDirectClasspath = true; private final String execGroup; + private ImmutableList coverageIncludes; + private ImmutableList coverageExcludes; public JavaCompilationHelper( RuleContext ruleContext, @@ -104,6 +106,14 @@ public void enableJspecify(boolean enableJspecify) { this.enableJspecify = enableJspecify; } + public void setCoverageIncludes(ImmutableList coverageIncludes) { + this.coverageIncludes = coverageIncludes; + } + + public void setCoverageExcludes(ImmutableList coverageExcludes) { + this.coverageExcludes = coverageExcludes; + } + JavaTargetAttributes getAttributes() { if (builtAttributes == null) { builtAttributes = attributes.build(); @@ -247,6 +257,8 @@ && getJavaConfiguration().experimentalEnableJspecify() builder.setTargetLabel(label); Artifact coverageArtifact = maybeCreateCoverageArtifact(outputs.output()); builder.setCoverageArtifact(coverageArtifact); + builder.setCoverageIncludes(coverageIncludes); + builder.setCoverageExcludes(coverageExcludes); BootClassPathInfo bootClassPathInfo = getBootclasspathOrDefault(); builder.setBootClassPath(bootClassPathInfo); NestedSet classpath = diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java index 5b0d37636ee5be..753d79565cce54 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java @@ -137,6 +137,8 @@ public void extend(ExtraActionInfo.Builder builder, ImmutableList argume private final String execGroup; private ImmutableSet additionalOutputs = ImmutableSet.of(); private Artifact coverageArtifact; + private ImmutableList coverageIncludes; + private ImmutableList coverageExcludes; private ImmutableSet sourceFiles = ImmutableSet.of(); private ImmutableList sourceJars = ImmutableList.of(); private StrictDepsMode strictJavaDeps = StrictDepsMode.ERROR; @@ -326,6 +328,8 @@ private CustomCommandLine buildParamFileContents(ImmutableList javacOpts if (coverageArtifact != null) { result.add("--post_processor"); result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, coverageArtifact); + result.addDynamicString(String.join(":", coverageIncludes)); + result.addDynamicString(String.join(":", coverageExcludes)); } return result.build(); } @@ -455,6 +459,18 @@ public JavaCompileActionBuilder setCoverageArtifact(Artifact coverageArtifact) { return this; } + @CanIgnoreReturnValue + public JavaCompileActionBuilder setCoverageIncludes(ImmutableList coverageIncludes) { + this.coverageIncludes = coverageIncludes; + return this; + } + + @CanIgnoreReturnValue + public JavaCompileActionBuilder setCoverageExcludes(ImmutableList coverageExcludes) { + this.coverageExcludes = coverageExcludes; + return this; + } + @CanIgnoreReturnValue public JavaCompileActionBuilder setTargetLabel(Label targetLabel) { this.targetLabel = targetLabel; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java index 18b18494682ec7..7f1e8fc3bb4942 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java @@ -201,7 +201,9 @@ public void createCompilationAction( boolean enableJSpecify, boolean enableDirectClasspath, Sequence additionalInputs, - Sequence additionalOutputs) + Sequence additionalOutputs, + Sequence coverageIncludes, + Sequence coverageExcludes) throws EvalException, TypeException, RuleErrorException, @@ -261,6 +263,10 @@ public void createCompilationAction( Depset.cast(javaBuilderJvmFlags, String.class, "javabuilder_jvm_flags")); compilationHelper.enableJspecify(enableJSpecify); compilationHelper.enableDirectClasspath(enableDirectClasspath); + compilationHelper.setCoverageIncludes( + Sequence.cast(coverageIncludes, String.class, "coverage_includes").getImmutableList()); + compilationHelper.setCoverageExcludes( + Sequence.cast(coverageExcludes, String.class, "coverage_excludes").getImmutableList()); compilationHelper.createCompileAction(outputs); } diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java index 8867bf9b446f0e..9adee6047adc3e 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java @@ -524,6 +524,8 @@ void createHeaderCompilationAction( @Param(name = "enable_direct_classpath", defaultValue = "True", named = true), @Param(name = "additional_inputs", defaultValue = "[]", named = true), @Param(name = "additional_outputs", defaultValue = "[]", named = true), + @Param(name = "coverage_includes", defaultValue = "[]", named = true), + @Param(name = "coverage_excludes", defaultValue = "[]", named = true) }) void createCompilationAction( StarlarkRuleContextT ctx, @@ -553,7 +555,9 @@ void createCompilationAction( boolean enableJSpecify, boolean enableDirectClasspath, Sequence additionalInputs, - Sequence additionalOutputs) + Sequence additionalOutputs, + Sequence coverageIncludes, + Sequence coverageExcludes) throws EvalException, TypeException, RuleErrorException,