Skip to content

Commit

Permalink
Clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
mnhock authored and mnhock committed Jun 19, 2024
1 parent e05a3ef commit 47fb731
Show file tree
Hide file tree
Showing 22 changed files with 385 additions and 219 deletions.
76 changes: 0 additions & 76 deletions src/main/java/com/enofex/taikai/GeneralPredicates.java

This file was deleted.

59 changes: 59 additions & 0 deletions src/main/java/com/enofex/taikai/internal/ArchConditions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.enofex.taikai.internal;

import static com.enofex.taikai.internal.Modifiers.isFieldPublic;
import static com.enofex.taikai.internal.Modifiers.isFieldStatic;

import com.tngtech.archunit.core.domain.JavaField;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;

/**
* Internal utility class for defining general ArchCondition used in architectural rules.
* <p>
* This class is intended for internal use only and is not part of the public API. Developers should
* not rely on this class for any public API usage.
*/
public final class ArchConditions {

private ArchConditions() {
}

/**
* Creates a condition that checks if a method does not declare thrown exceptions.
*
* @return an architectural condition for checking thrown exceptions in methods
*/
public static ArchCondition<JavaMethod> notDeclareThrownExceptions() {
return new ArchCondition<>("not declare thrown exceptions") {
@Override
public void check(JavaMethod method, ConditionEvents events) {
if (!method.getThrowsClause().isEmpty()) {
events.add(SimpleConditionEvent.violated(method,
"Method %s declares thrown exceptions".formatted(
method.getFullName())));
}
}
};
}

/**
* Creates a condition that checks if a field is not public and not static.
*
* @return an architectural condition for checking public except static fields
*/
public static ArchCondition<JavaField> notBePublicButNotStatic() {
return new ArchCondition<>("not be public") {
@Override
public void check(JavaField field, ConditionEvents events) {
if (!isFieldStatic(field) && isFieldPublic(field)) {
events.add(SimpleConditionEvent.violated(field,
"Field %s in class %s is public".formatted(
field.getName(),
field.getOwner().getFullName())));
}
}
};
}
}
51 changes: 51 additions & 0 deletions src/main/java/com/enofex/taikai/internal/DescribedPredicates.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.enofex.taikai.internal;

import static com.enofex.taikai.internal.Modifiers.isClassFinal;

import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.properties.CanBeAnnotated;

/**
* Internal utility class for defining general DescribedPredicate used in architectural rules.
* <p>
* This class is intended for internal use only and is not part of the public API. Developers should
* not rely on this class for any public API usage.
*/
public final class DescribedPredicates {

private DescribedPredicates() {
}

/**
* Creates a predicate that checks if an element is annotated with a specific annotation.
*
* @param annotation the annotation to check for
* @param isMetaAnnotated true if the annotation should be meta-annotated, false otherwise
* @return a described predicate for the annotation check
*/
public static DescribedPredicate<CanBeAnnotated> annotatedWith(String annotation,
boolean isMetaAnnotated) {
return new DescribedPredicate<>("annotated with %s".formatted(annotation)) {
@Override
public boolean test(CanBeAnnotated canBeAnnotated) {
return isMetaAnnotated ? canBeAnnotated.isMetaAnnotatedWith(annotation)
: canBeAnnotated.isAnnotatedWith(annotation);
}
};
}

/**
* Creates a predicate that checks if a class is final.
*
* @return a described predicate for the final modifier check
*/
public static DescribedPredicate<JavaClass> areFinal() {
return new DescribedPredicate<>("are final") {
@Override
public boolean test(JavaClass javaClass) {
return isClassFinal(javaClass);
}
};
}
}
99 changes: 99 additions & 0 deletions src/main/java/com/enofex/taikai/internal/Modifiers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.enofex.taikai.internal;

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaConstructor;
import com.tngtech.archunit.core.domain.JavaField;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.domain.JavaModifier;

/**
* This class provides utility methods for checking Java modifiers.
* <p>
* This class is intended for internal use only and is not part of the public API. Developers should
* not rely on this class for any public API usage.
*/
public final class Modifiers {

private Modifiers() {
}

/**
* Checks if a class is final.
*
* @param javaClass the Java class to check
* @return true if the class is final, false otherwise
*/
public static boolean isClassFinal(JavaClass javaClass) {
return javaClass.getModifiers().contains(JavaModifier.FINAL);
}

/**
* Checks if a constructor is private.
*
* @param constructor the Java constructor to check
* @return true if the constructor is private, false otherwise
*/
public static boolean isConstructorPrivate(JavaConstructor constructor) {
return constructor.getModifiers().contains(JavaModifier.PRIVATE);
}

/**
* Checks if a method is protected.
*
* @param method the Java method to check
* @return true if the method is protected, false otherwise
*/
public static boolean isMethodProtected(JavaMethod method) {
return method.getModifiers().contains(JavaModifier.PROTECTED);
}

/**
* Checks if a method is static.
*
* @param method the Java method to check
* @return true if the method is static, false otherwise
*/
public static boolean isMethodStatic(JavaMethod method) {
return method.getModifiers().contains(JavaModifier.STATIC);
}

/**
* Checks if a field is static.
*
* @param field the Java field to check
* @return true if the field is static, false otherwise
*/
public static boolean isFieldStatic(JavaField field) {
return field.getModifiers().contains(JavaModifier.STATIC);
}

/**
* Checks if a field is public.
*
* @param field the Java field to check
* @return true if the field is public, false otherwise
*/
public static boolean isFieldPublic(JavaField field) {
return field.getModifiers().contains(JavaModifier.PUBLIC);
}

/**
* Checks if a field is protected.
*
* @param field the Java field to check
* @return true if the field is protected, false otherwise
*/
public static boolean isFieldProtected(JavaField field) {
return field.getModifiers().contains(JavaModifier.PROTECTED);
}

/**
* Checks if a field is final.
*
* @param field the Java field to check
* @return true if the field is final, false otherwise
*/
public static boolean isFieldFinal(JavaField field) {
return field.getModifiers().contains(JavaModifier.FINAL);
}
}
13 changes: 6 additions & 7 deletions src/main/java/com/enofex/taikai/java/ConstantNaming.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@

final class ConstantNaming {

private static final Pattern CONSTANT_NAME_PATTERN = Pattern.compile("^[A-Z][A-Z0-9_]*$");

private ConstantNaming() {
}

static ArchCondition<JavaField> shouldFollowConstantNamingConvention() {
return new ArchCondition<>("follow constant naming convention") {

private static final Pattern CONSTANT_NAME_PATTERN = Pattern.compile("^[A-Z][A-Z0-9_]*$");

@Override
public void check(JavaField field, ConditionEvents events) {
if (!field.getOwner().isEnum()
&& !"serialVersionUID".equals(field.getName())
&& !CONSTANT_NAME_PATTERN.matcher(field.getName()).matches()) {
String message = String.format(
"Constant %s in class %s does not follow the naming convention", field.getName(),
field.getOwner().getName());
events.add(SimpleConditionEvent.violated(field, message));
events.add(SimpleConditionEvent.violated(field,
"Constant %s in class %s does not follow the naming convention".formatted(
field.getName(),
field.getOwner().getName())));
}
}
};
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/com/enofex/taikai/java/Deprecations.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,38 @@ public void check(JavaClass javaClass, ConditionEvents events) {
javaClass.getFieldAccessesFromSelf().stream()
.filter(access -> access.getTarget().isAnnotatedWith(Deprecated.class))
.forEach(access -> events.add(SimpleConditionEvent.violated(access.getTarget(),
String.format("Field %s in class %s is deprecated and is being accessed by %s",
access.getTarget().getName(), access.getTarget().getOwner().getName(),
"Field %s in class %s is deprecated and is being accessed by %s".formatted(
access.getTarget().getName(),
access.getTarget().getOwner().getName(),
javaClass.getName()))));

javaClass.getMethodCallsFromSelf().stream()
.filter(method -> !method.getTarget().getName().equals(Object.class.getName()))
.filter(method -> !method.getTarget().getName().equals(Enum.class.getName()))
.filter(method -> method.getTarget().isAnnotatedWith(Deprecated.class) ||
method.getTarget().getRawReturnType().isAnnotatedWith(Deprecated.class) ||
method.getTarget().getParameterTypes().stream().anyMatch(Deprecations::isDeprecated))
method.getTarget().getParameterTypes().stream()
.anyMatch(Deprecations::isDeprecated))
.forEach(method -> events.add(SimpleConditionEvent.violated(method,
String.format("Method %s used in class %s is deprecated", method.getName(),
"Method %s used in class %s is deprecated".formatted(
method.getName(),
javaClass.getName()))));

javaClass.getConstructorCallsFromSelf().stream()
.filter(constructor -> constructor.getTarget().isAnnotatedWith(Deprecated.class) ||
constructor.getTarget().getParameterTypes().stream()
.anyMatch(Deprecations::isDeprecated))
.forEach(constructor -> events.add(SimpleConditionEvent.violated(constructor,
String.format("Constructor %s in class %s uses deprecated APIs",
constructor.getTarget().getFullName(), javaClass.getName()))));
"Constructor %s in class %s uses deprecated APIs".formatted(
constructor.getTarget().getFullName(),
javaClass.getName()))));

javaClass.getDirectDependenciesFromSelf().stream()
.filter(dependency -> dependency.getTargetClass().isAnnotatedWith(Deprecated.class))
.forEach(dependency -> events.add(
SimpleConditionEvent.violated(dependency.getTargetClass(),
String.format("Class %s depends on deprecated class %s", javaClass.getName(),
"Class %s depends on deprecated class %s".formatted(
javaClass.getName(),
dependency.getTargetClass().getName()))));
}
}.as("no usage of deprecated APIs");
Expand Down
Loading

0 comments on commit 47fb731

Please sign in to comment.