/* * Copyright 2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gradle.testing.jacoco.plugins; import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.internal.TaskInternal; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import org.gradle.api.provider.PropertyState; import org.gradle.api.provider.Provider; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.TaskCollection; import org.gradle.internal.Cast; import org.gradle.internal.jacoco.JacocoAgentJar; import org.gradle.process.JavaForkOptions; import java.io.File; import java.util.concurrent.Callable; /** * Extension including common properties and methods for Jacoco. */ @Incubating public class JacocoPluginExtension { public static final String TASK_EXTENSION_NAME = "jacoco"; private static final Logger LOGGER = Logging.getLogger(JacocoPluginExtension.class); protected final Project project; private final JacocoAgentJar agent; private String toolVersion; private final PropertyState<File> reportsDir; /** * Creates a Jacoco plugin extension. * * @param project the project the extension is attached to * @param agent the agent JAR to be used by Jacoco */ public JacocoPluginExtension(Project project, JacocoAgentJar agent) { this.project = project; this.agent = agent; reportsDir = project.property(File.class); } /** * Version of Jacoco JARs to use. */ public String getToolVersion() { return toolVersion; } public void setToolVersion(String toolVersion) { this.toolVersion = toolVersion; } /** * The directory where reports will be generated. */ public File getReportsDir() { return reportsDir.get(); } /** * Set the provider for calculating the report directory. * * @param reportsDir Reports directory provider * @since 4.0 */ public void setReportsDir(Provider<File> reportsDir) { this.reportsDir.set(reportsDir); } public void setReportsDir(File reportsDir) { this.reportsDir.set(reportsDir); } /** * Applies Jacoco to the given task. * Configuration options will be provided on a task extension named 'jacoco'. * Jacoco will be run as an agent during the execution of the task. * * @param task the task to apply Jacoco to. * @see JacocoPluginExtension#TASK_EXTENSION_NAME */ public <T extends Task & JavaForkOptions> void applyTo(final T task) { final String taskName = task.getName(); LOGGER.debug("Applying Jacoco to " + taskName); final JacocoTaskExtension extension = task.getExtensions().create(TASK_EXTENSION_NAME, JacocoTaskExtension.class, project, agent, task); extension.setDestinationFile(project.provider(new Callable<File>() { @Override public File call() throws Exception { return project.file(String.valueOf(project.getBuildDir()) + "/jacoco/" + taskName + ".exec"); } })); // Capture some of the JaCoCo contributed inputs to the task task.getInputs().property("jacoco.jvmArg", new Callable<String>() { @Override public String call() throws Exception { return extension.isEnabled() ? extension.getAsJvmArg() : null; } }); task.getOutputs().file(new Callable<File>() { @Override public File call() throws Exception { return extension.isEnabled() ? extension.getDestinationFile() : null; } }).optional().withPropertyName("jacoco.destinationFile"); task.getOutputs().dir(new Callable<File>() { @Override public File call() throws Exception { return extension.isEnabled() ? extension.getClassDumpDir() : null; } }).optional().withPropertyName("jacoco.classDumpDir"); // Do not cache the task if we are not writing execution data to a file task.getOutputs().doNotCacheIf("JaCoCo configured to not produce its output as a file", new Spec<Task>() { @Override public boolean isSatisfiedBy(Task element) { // Do not cache Test task if Jacoco doesn't produce its output as files return extension.isEnabled() && extension.getOutput() != JacocoTaskExtension.Output.FILE; } }); // Do not cache the Test task if we are appending to the Jacoco output task.getOutputs().doNotCacheIf("JaCoCo agent configured with `append = true`", new Spec<Task>() { @Override public boolean isSatisfiedBy(Task element) { return extension.isEnabled() && extension.isAppend(); } }); TaskInternal taskInternal = (TaskInternal) task; taskInternal.prependParallelSafeAction(new Action<Task>() { @Override public void execute(Task input) { if (extension.isEnabled()) { task.jvmArgs(extension.getAsJvmArg()); } } }); } /** * Applies Jacoco to all of the given tasks. * * @param tasks the tasks to apply Jacoco to */ public <T extends Task & JavaForkOptions> void applyTo(TaskCollection tasks) { tasks.withType(JavaForkOptions.class, new Action<JavaForkOptions>() { @Override public void execute(JavaForkOptions task) { applyTo(Cast.<T>uncheckedCast(task)); } }); } }