Skip to content

Commit

Permalink
Release 0.23.1 #818
Browse files Browse the repository at this point in the history
No description provided.
  • Loading branch information
codecholeric authored Feb 28, 2022
2 parents 8f56568 + a333f1f commit 40c15c6
Show file tree
Hide file tree
Showing 57 changed files with 722 additions and 171 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ framework.
###### Gradle

```
testImplementation 'com.tngtech.archunit:archunit:0.22.0'
testImplementation 'com.tngtech.archunit:archunit:0.23.1'
```

###### Maven
Expand All @@ -26,7 +26,7 @@ testImplementation 'com.tngtech.archunit:archunit:0.22.0'
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
<version>0.22.0</version>
<version>0.23.1</version>
<scope>test</scope>
</dependency>
```
Expand Down
3 changes: 2 additions & 1 deletion archunit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ dependencies {
runtimeOnly sourceSets.jdk9main.output
}

compileJdk9mainJava.with {
compileJdk9mainJava {
dependsOn(compileJava)
ext.minimumJavaVersion = JavaVersion.VERSION_1_9

destinationDir = compileJava.destinationDir
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public abstract class JavaCodeUnit
extends JavaMember
implements HasParameterTypes, HasReturnType, HasTypeParameters<JavaCodeUnit>, HasThrowsClause<JavaCodeUnit> {

private final JavaType returnType;
private final ReturnType returnType;
private final Parameters parameters;
private final String fullName;
private final List<JavaTypeVariable<JavaCodeUnit>> typeParameters;
Expand All @@ -71,7 +71,7 @@ public abstract class JavaCodeUnit
JavaCodeUnit(JavaCodeUnitBuilder<?, ?> builder) {
super(builder);
typeParameters = builder.getTypeParameters(this);
returnType = builder.getReturnType(this);
returnType = new ReturnType(this, builder);
parameters = new Parameters(this, builder);
fullName = formatMethod(getOwner().getName(), getName(), namesOf(getRawParameterTypes()));
referencedClassObjects = ImmutableSet.copyOf(builder.getReferencedClassObjects(this));
Expand Down Expand Up @@ -157,13 +157,13 @@ public List<JavaClass> getExceptionTypes() {
@Override
@PublicAPI(usage = ACCESS)
public JavaType getReturnType() {
return returnType;
return returnType.get();
}

@Override
@PublicAPI(usage = ACCESS)
public JavaClass getRawReturnType() {
return returnType.toErasure();
return returnType.getRaw();
}

@PublicAPI(usage = ACCESS)
Expand Down Expand Up @@ -323,6 +323,24 @@ protected List<JavaParameter> delegate() {
}
}

private static class ReturnType {
private final JavaClass rawReturnType;
private final JavaType returnType;

ReturnType(JavaCodeUnit owner, JavaCodeUnitBuilder<?, ?> builder) {
rawReturnType = builder.getRawReturnType();
returnType = builder.getGenericReturnType(owner);
}

JavaClass getRaw() {
return rawReturnType;
}

JavaType get() {
return returnType;
}
}

public static final class Predicates {
private Predicates() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ void resolve(ImportedClasses classes) {
}

private void logConfiguration() {
log.info("Automatically resolving transitive class dependencies with the following configuration:{}{}{}{}{}{}",
log.debug("Automatically resolving transitive class dependencies with the following configuration:{}{}{}{}{}{}",
formatConfigProperty(MAX_ITERATIONS_FOR_MEMBER_TYPES_PROPERTY_NAME, maxRunsForMemberTypes),
formatConfigProperty(MAX_ITERATIONS_FOR_ACCESSES_TO_TYPES_PROPERTY_NAME, maxRunsForAccessesToTypes),
formatConfigProperty(MAX_ITERATIONS_FOR_SUPERTYPES_PROPERTY_NAME, maxRunsForSupertypes),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,14 @@ boolean hasNoParameters() {
return rawParameterTypes.isEmpty();
}

public JavaType getReturnType(JavaCodeUnit codeUnit) {
public JavaClass getRawReturnType() {
return get(rawReturnType.getFullyQualifiedClassName());
}

public JavaType getGenericReturnType(JavaCodeUnit codeUnit) {
return genericReturnType.isPresent()
? genericReturnType.get().finish(codeUnit, allTypeParametersInContextOf(codeUnit), importedClasses)
: get(rawReturnType.getFullyQualifiedClassName());
: getRawReturnType();
}

private Iterable<JavaTypeVariable<?>> allTypeParametersInContextOf(JavaCodeUnit codeUnit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.tngtech.archunit.core.domain.JavaClassDescriptor;
import com.tngtech.archunit.core.domain.JavaCodeUnit;
import com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType;
import com.tngtech.archunit.core.domain.properties.HasName;

import static com.google.common.base.Preconditions.checkNotNull;

Expand Down Expand Up @@ -139,8 +138,7 @@ public String toString() {

public boolean is(JavaCodeUnit method) {
return getName().equals(method.getName())
&& getRawParameterTypeNames().equals(HasName.Utils.namesOf(method.getRawParameterTypes()))
&& returnType.getFullyQualifiedClassName().equals(method.getRawReturnType().getName())
&& descriptor.equals(method.getDescriptor())
&& getDeclaringClassName().equals(method.getOwner().getName());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2014-2022 TNG Technology Consulting GmbH
*
* 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.tngtech.archunit.lang;

import com.tngtech.archunit.ArchConfiguration;

enum AllowEmptyShould {
TRUE {
@Override
public boolean isAllowed() {
return true;
}
},
FALSE {
@Override
public boolean isAllowed() {
return false;
}
},
AS_CONFIGURED {
@Override
public boolean isAllowed() {
return ArchConfiguration.get().getPropertyOrDefault(FAIL_ON_EMPTY_SHOULD_PROPERTY_NAME, TRUE.toString())
.equalsIgnoreCase(FALSE.toString());
}
};

private static final String FAIL_ON_EMPTY_SHOULD_PROPERTY_NAME = "archRule.failOnEmptyShould";

abstract boolean isAllowed();

static AllowEmptyShould fromBoolean(boolean allow) {
return allow ? TRUE : FALSE;
}
}
47 changes: 31 additions & 16 deletions archunit/src/main/java/com/tngtech/archunit/lang/ArchRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.tngtech.archunit.ArchConfiguration;
import com.tngtech.archunit.Internal;
import com.tngtech.archunit.PublicAPI;
import com.tngtech.archunit.base.Optional;
Expand All @@ -41,7 +40,6 @@
import static com.google.common.io.Resources.readLines;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.base.ClassLoaders.getCurrentClassLoader;
import static java.lang.Boolean.TRUE;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
Expand All @@ -68,6 +66,18 @@ public interface ArchRule extends CanBeEvaluated, CanOverrideDescription<ArchRul
@PublicAPI(usage = ACCESS)
ArchRule because(String reason);

/**
* If set to {@code true} allows the should-clause of this rule to be checked against an empty set of elements.
* Otherwise, the rule will fail with a respective message. This is to prevent possible implementation errors,
* like filtering for a non-existing package in the that-clause causing an always-passing rule.<br>
* Note that this method will override the configuration property {@code archRule.failOnEmptyShould}.
*
* @param allowEmptyShould Whether the rule fails if the should-clause is evaluated with an empty set of elements
* @return A (new) {@link ArchRule} with adjusted {@code allowEmptyShould} behavior
*/
@PublicAPI(usage = ACCESS)
ArchRule allowEmptyShould(boolean allowEmptyShould);

@PublicAPI(usage = ACCESS)
final class Assertions {
private static final ArchUnitExtensions extensions = new ArchUnitExtensions();
Expand Down Expand Up @@ -166,7 +176,7 @@ public EvaluationResult getResult() {
@Internal
class Factory {
public static <T> ArchRule create(final ClassesTransformer<T> classesTransformer, final ArchCondition<T> condition, final Priority priority) {
return new SimpleArchRule<>(priority, classesTransformer, condition, Optional.<String>empty());
return new SimpleArchRule<>(priority, classesTransformer, condition, Optional.<String>empty(), AllowEmptyShould.AS_CONFIGURED);
}

public static ArchRule withBecause(ArchRule rule, String reason) {
Expand All @@ -184,18 +194,20 @@ private static class SimpleArchRule<T> implements ArchRule {
private final ClassesTransformer<T> classesTransformer;
private final ArchCondition<T> condition;
private final Optional<String> overriddenDescription;
private final AllowEmptyShould allowEmptyShould;

private SimpleArchRule(Priority priority, ClassesTransformer<T> classesTransformer, ArchCondition<T> condition,
Optional<String> overriddenDescription) {
Optional<String> overriddenDescription, AllowEmptyShould allowEmptyShould) {
this.priority = priority;
this.classesTransformer = classesTransformer;
this.condition = condition;
this.overriddenDescription = overriddenDescription;
this.allowEmptyShould = allowEmptyShould;
}

@Override
public ArchRule as(String newDescription) {
return new SimpleArchRule<>(priority, classesTransformer, condition, Optional.of(newDescription));
return new SimpleArchRule<>(priority, classesTransformer, condition, Optional.of(newDescription), allowEmptyShould);
}

@Override
Expand All @@ -208,6 +220,11 @@ public ArchRule because(String reason) {
return withBecause(this, reason);
}

@Override
public ArchRule allowEmptyShould(boolean allowEmptyShould) {
return new SimpleArchRule<>(priority, classesTransformer, condition, overriddenDescription, AllowEmptyShould.fromBoolean(allowEmptyShould));
}

@Override
public EvaluationResult evaluate(JavaClasses classes) {
Iterable<T> allObjects = classesTransformer.transform(classes);
Expand All @@ -223,20 +240,18 @@ public EvaluationResult evaluate(JavaClasses classes) {
}

private void verifyNoEmptyShouldIfEnabled(Iterable<T> allObjects) {
if (isEmpty(allObjects) && isFailOnEmptyShouldEnabled()) {
throw new AssertionError("Rule failed to check any classes. " +
"This means either that no classes have been passed to the rule at all, " +
"or that no classes passed to the rule matched the `that()` clause. " +
"To allow rules being evaluated without checking any classes you can set the ArchUnit property " +
FAIL_ON_EMPTY_SHOULD_PROPERTY_NAME + " = " + false);
if (isEmpty(allObjects) && !allowEmptyShould.isAllowed()) {
throw new AssertionError(String.format(
"Rule '%s' failed to check any classes. "
+ "This means either that no classes have been passed to the rule at all, "
+ "or that no classes passed to the rule matched the `that()` clause. "
+ "To allow rules being evaluated without checking any classes you can either "
+ "use `%s.allowEmptyShould(true)` on a single rule or set the configuration property `%s = false` "
+ "to change the behavior globally.",
getDescription(), ArchRule.class.getSimpleName(), FAIL_ON_EMPTY_SHOULD_PROPERTY_NAME));
}
}

private boolean isFailOnEmptyShouldEnabled() {
return ArchConfiguration.get().getPropertyOrDefault(FAIL_ON_EMPTY_SHOULD_PROPERTY_NAME, TRUE.toString())
.equals(TRUE.toString());
}

@Override
public String getDescription() {
return overriddenDescription.isPresent() ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ public CompositeArchRule because(String reason) {
return new CompositeArchRule(priority, rules, createBecauseDescription(this, reason));
}

@Override
@PublicAPI(usage = ACCESS)
public ArchRule allowEmptyShould(boolean allowEmptyShould) {
ImmutableList.Builder<ArchRule> rulesWithOverriddenAllowEmptyShould = ImmutableList.builder();
for (ArchRule rule : rules) {
rulesWithOverriddenAllowEmptyShould.add(rule.allowEmptyShould(allowEmptyShould));
}
return new CompositeArchRule(priority, rulesWithOverriddenAllowEmptyShould.build(), description);
}

@Override
@PublicAPI(usage = ACCESS)
public EvaluationResult evaluate(JavaClasses classes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public ArchRule because(String reason) {
return ArchRule.Factory.withBecause(this, reason);
}

@Override
public ArchRule allowEmptyShould(boolean allowEmptyShould) {
return finishedRule.get().allowEmptyShould(allowEmptyShould);
}

@Override
public ArchRule as(String newDescription) {
return finishedRule.get().as(newDescription);
Expand Down
Loading

0 comments on commit 40c15c6

Please sign in to comment.