mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Prohibit use of APIs that prevent task configuration avoidance
Closes gh-29809
This commit is contained in:
parent
865a829d29
commit
03352b0a8c
@ -27,6 +27,7 @@ dependencies {
|
||||
}
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation("com.tngtech.archunit:archunit-junit5:0.22.0")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
@ -45,10 +45,12 @@ final class MavenPluginAction implements PluginApplicationAction {
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
project.getTasks().withType(Upload.class, (upload) -> {
|
||||
if (this.uploadTaskName.equals(upload.getName())) {
|
||||
project.afterEvaluate((evaluated) -> clearConfigurationMappings(upload));
|
||||
}
|
||||
project.afterEvaluate((evaluated) -> {
|
||||
project.getTasks().withType(Upload.class).configureEach((upload) -> {
|
||||
if (this.uploadTaskName.equals(upload.getName())) {
|
||||
clearConfigurationMappings(upload);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.springframework.boot.gradle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.tngtech.archunit.base.DescribedPredicate;
|
||||
import com.tngtech.archunit.base.Predicate;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.domain.JavaMethodCall;
|
||||
import com.tngtech.archunit.core.domain.JavaType;
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
import com.tngtech.archunit.core.importer.Location;
|
||||
import com.tngtech.archunit.junit.AnalyzeClasses;
|
||||
import com.tngtech.archunit.junit.ArchTest;
|
||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.tasks.TaskCollection;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
|
||||
/**
|
||||
* Tests that verify the plugin's compliance with task configuration avoidance.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@AnalyzeClasses(packages = "org.springframework.boot.gradle",
|
||||
importOptions = TaskConfigurationAvoidanceTests.DoNotIncludeTests.class)
|
||||
class TaskConfigurationAvoidanceTests {
|
||||
|
||||
@ArchTest
|
||||
void noApisThatCauseEagerTaskConfigurationShouldBeCalled(JavaClasses classes) {
|
||||
ProhibitedMethods prohibited = new ProhibitedMethods();
|
||||
prohibited.on(TaskContainer.class).methodsNamed("create", "findByPath, getByPath").method("withType",
|
||||
Class.class, Action.class);
|
||||
prohibited.on(TaskCollection.class).methodsNamed("findByName", "getByName");
|
||||
ArchRuleDefinition.noClasses().should()
|
||||
.callMethodWhere(DescribedPredicate.describe("it would cause eager task configuration", prohibited))
|
||||
.check(classes);
|
||||
}
|
||||
|
||||
static class DoNotIncludeTests implements ImportOption {
|
||||
|
||||
@Override
|
||||
public boolean includes(Location location) {
|
||||
return !location.matches(Pattern.compile(".*Tests\\.class"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ProhibitedMethods implements Predicate<JavaMethodCall> {
|
||||
|
||||
private final List<Predicate<JavaMethodCall>> prohibited = new ArrayList<>();
|
||||
|
||||
private ProhibitedConfigurer on(Class<?> type) {
|
||||
return new ProhibitedConfigurer(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(JavaMethodCall methodCall) {
|
||||
for (Predicate<JavaMethodCall> spec : this.prohibited) {
|
||||
if (spec.apply(methodCall)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final class ProhibitedConfigurer {
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private ProhibitedConfigurer(Class<?> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private ProhibitedConfigurer methodsNamed(String... names) {
|
||||
for (String name : names) {
|
||||
ProhibitedMethods.this.prohibited.add(new ProhibitMethodsNamed(this.type, name));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private ProhibitedConfigurer method(String name, Class<?>... parameterTypes) {
|
||||
ProhibitedMethods.this.prohibited
|
||||
.add(new ProhibitMethod(this.type, name, Arrays.asList(parameterTypes)));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ProhibitMethodsNamed implements Predicate<JavaMethodCall> {
|
||||
|
||||
private final Class<?> owner;
|
||||
|
||||
private final String name;
|
||||
|
||||
ProhibitMethodsNamed(Class<?> owner, String name) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(JavaMethodCall methodCall) {
|
||||
return methodCall.getTargetOwner().isEquivalentTo(this.owner) && methodCall.getName().equals(this.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ProhibitMethod extends ProhibitMethodsNamed {
|
||||
|
||||
private final List<Class<?>> parameterTypes;
|
||||
|
||||
private ProhibitMethod(Class<?> owner, String name, List<Class<?>> parameterTypes) {
|
||||
super(owner, name);
|
||||
this.parameterTypes = parameterTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(JavaMethodCall methodCall) {
|
||||
return super.apply(methodCall) && match(methodCall.getTarget().getParameterTypes());
|
||||
}
|
||||
|
||||
private boolean match(List<JavaType> callParameterTypes) {
|
||||
if (this.parameterTypes.size() != callParameterTypes.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < this.parameterTypes.size(); i++) {
|
||||
if (!callParameterTypes.get(i).toErasure().isEquivalentTo(this.parameterTypes.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user