/*
* Copyright 2016 DiffPlug
*
* 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 com.diffplug.gradle.spotless;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.execution.TaskExecutionGraph;
import org.gradle.api.plugins.JavaBasePlugin;
import com.diffplug.common.base.Errors;
import com.diffplug.spotless.SpotlessCache;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import groovy.lang.Closure;
public class SpotlessPlugin implements Plugin<Project> {
Project project;
SpotlessExtension spotlessExtension;
static final String EXTENSION = "spotless";
static final String CHECK = "Check";
static final String APPLY = "Apply";
private static final String TASK_GROUP = "Verification";
private static final String CHECK_DESCRIPTION = "Checks that sourcecode satisfies formatting steps.";
private static final String APPLY_DESCRIPTION = "Applies code formatting steps to sourcecode in-place.";
@Override
public void apply(Project project) {
this.project = project;
// setup the extension
spotlessExtension = project.getExtensions().create(EXTENSION, SpotlessExtension.class, project);
// after the project has been evaluated, configure the check and format tasks per source set
project.afterEvaluate(unused -> Errors.rethrow().run(this::createTasks));
}
/** The extension for this plugin. */
public SpotlessExtension getExtension() {
return spotlessExtension;
}
@SuppressWarnings("rawtypes")
void createTasks() throws Exception {
Task rootCheckTask = project.task(EXTENSION + CHECK);
rootCheckTask.setGroup(TASK_GROUP);
rootCheckTask.setDescription(CHECK_DESCRIPTION);
Task rootApplyTask = project.task(EXTENSION + APPLY);
rootApplyTask.setGroup(TASK_GROUP);
rootApplyTask.setDescription(APPLY_DESCRIPTION);
spotlessExtension.formats.forEach((key, value) -> {
// create the task that does the work
String taskName = EXTENSION + capitalize(key);
SpotlessTask spotlessTask = project.getTasks().create(taskName, SpotlessTask.class);
value.setupTask(spotlessTask);
// create the check and apply control tasks
Task checkTask = project.getTasks().create(taskName + CHECK);
Task applyTask = project.getTasks().create(taskName + APPLY);
// the root tasks depend on them
rootCheckTask.dependsOn(checkTask);
rootApplyTask.dependsOn(applyTask);
// and they depend on the work task
checkTask.dependsOn(spotlessTask);
applyTask.dependsOn(spotlessTask);
// when the task graph is ready, we'll configure the spotlessTask appropriately
project.getGradle().getTaskGraph().whenReady(new Closure(null) {
private static final long serialVersionUID = 1L;
// called by gradle
@SuppressFBWarnings("UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS")
public Object doCall(TaskExecutionGraph graph) {
if (graph.hasTask(checkTask)) {
spotlessTask.setCheck();
}
if (graph.hasTask(applyTask)) {
spotlessTask.setApply();
}
return Closure.DONE;
}
});
});
// Add our check task as a dependency on the global check task
// getTasks() returns a "live" collection, so this works even if the
// task doesn't exist at the time this call is made
if (spotlessExtension.enforceCheck) {
project.getTasks()
.matching(task -> task.getName().equals(JavaBasePlugin.CHECK_TASK_NAME))
.all(task -> task.dependsOn(rootCheckTask));
}
// clear spotless' cache when the user does a clean
project.getTasks()
.matching(task -> task.getName().equals("clean"))
.all(task -> task.doLast(unused -> SpotlessCache.clear()));
}
static String capitalize(String input) {
return Character.toUpperCase(input.charAt(0)) + input.substring(1);
}
}