Skip to content

Commit

Permalink
Provide new Java Rule checking Methods from not Throwing Specific Exc…
Browse files Browse the repository at this point in the history
…eptions in Specific Classes

Closes gh-76
  • Loading branch information
mnhock committed Jul 14, 2024
1 parent d2ec766 commit 671f552
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 27 deletions.
67 changes: 40 additions & 27 deletions docs/USERGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,34 +105,35 @@ Taikai's architecture rules cover a wide range of categories to enforce best pra

The default mode is `WITHOUT_TESTS`, which excludes test classes from the import check.

| Category | Method Name | Rule Description |
|----------|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|
| General | `classesShouldImplementHashCodeAndEquals` | Classes should implement `hashCode` and `equals` together. |
| General | `classesShouldResideInPackage` | Classes matching specific naming patterns should reside in a specified package. |
| General | `classesAnnotatedWithShouldResideInPackage` | Classes annotated with a specific annotation should reside in a specified package. |
| General | `classesShouldResideOutsidePackage` | Classes matching specific naming patterns should reside outside a specified package. |
| General | `classesShouldBeAnnotatedWith` | Classes matching specific naming patterns should be annotated with a specified annotation. |
| General | `fieldsShouldNotBePublic` | Fields should not be `public`, except constants. |
| General | `methodsShouldNotDeclareGenericExceptions` | Methods should not declare generic exceptions, like `Exception` or `RuntimeException`. |
| General | `noUsageOf` | Disallow usage of specific classes. |
| General | `noUsageOf` | Disallow usage of specific classes by class reference. |
| General | `noUsageOfDeprecatedAPIs` | No usage of deprecated APIs annotated with `@Deprecated`. |
| General | `noUsageOfSystemOutOrErr` | Disallow usage of `System.out` or `System.err`. |
| Category | Method Name | Rule Description |
|----------|--------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| General | `classesShouldImplementHashCodeAndEquals` | Classes should implement `hashCode` and `equals` together. |
| General | `classesShouldResideInPackage` | Classes matching specific naming patterns should reside in a specified package. |
| General | `classesAnnotatedWithShouldResideInPackage` | Classes annotated with a specific annotation should reside in a specified package. |
| General | `classesShouldResideOutsidePackage` | Classes matching specific naming patterns should reside outside a specified package. |
| General | `classesShouldBeAnnotatedWith` | Classes matching specific naming patterns should be annotated with a specified annotation. |
| General | `fieldsShouldNotBePublic` | Fields should not be `public`, except constants. |
| General | `methodsShouldNotDeclareGenericExceptions` | Methods should not declare generic exceptions, like `Exception` or `RuntimeException`. |
| General | `methodsShouldNotDeclareException` | Methods with names matching a specified pattern should not declare a specified exception type. |
| General | `noUsageOf` | Disallow usage of specific classes. |
| General | `noUsageOf` | Disallow usage of specific classes by class reference. |
| General | `noUsageOfDeprecatedAPIs` | No usage of deprecated APIs annotated with `@Deprecated`. |
| General | `noUsageOfSystemOutOrErr` | Disallow usage of `System.out` or `System.err`. |
| General | `utilityClassesShouldBeFinalAndHavePrivateConstructor` | Utility classes with only `static` methods (except `main`) should be `final` and have a private constructor. |
| General | `finalClassesShouldNotHaveProtectedMembers` | Classes declared as `final` should not contain any `protected` members. |
| General | `serialVersionUIDShouldBeStaticFinalLong` | Fields named `serialVersionUID` should be declared as `static final long`. |
| Imports | `shouldHaveNoCycles` | No cyclic dependencies in imports. |
| Imports | `shouldNotImport` | Disallow specific imports (e.g., `..shaded..`). |
| Naming | `packagesShouldMatch` | Packages should match the specified regex pattern (e.g., `com.company.yourproject..`). |
| Naming | `classesShouldNotMatch` | Classes should not match specific naming patterns (e.g., `.*Impl`). |
| Naming | `classesAnnotatedWithShouldMatch` | Classes annotated with a specific annotation should match specific naming patterns. |
| Naming | `methodsShouldNotMatch` | Methods should not match specific naming patterns. |
| Naming | `methodsAnnotatedWithShouldMatch` | Methods annotated with a specific annotation should match specific naming patterns. |
| Naming | `fieldsShouldNotMatch` | Fields should not match specific naming patterns. |
| Naming | `fieldsShouldMatch` | Fields should match specific naming patterns for specific classes. |
| Naming | `fieldsAnnotatedWithShouldMatch` | Fields annotated with a specific annotation should match specific naming patterns. |
| Naming | `constantsShouldFollowConventions` | Constants should follow naming conventions, except `serialVersionUID`. |
| Naming | `interfacesShouldNotHavePrefixI` | Interfaces should not have the prefix `I`. |
| General | `finalClassesShouldNotHaveProtectedMembers` | Classes declared as `final` should not contain any `protected` members. |
| General | `serialVersionUIDShouldBeStaticFinalLong` | Fields named `serialVersionUID` should be declared as `static final long`. |
| Imports | `shouldHaveNoCycles` | No cyclic dependencies in imports. |
| Imports | `shouldNotImport` | Disallow specific imports (e.g., `..shaded..`). |
| Naming | `packagesShouldMatch` | Packages should match the specified regex pattern (e.g., `com.company.yourproject..`). |
| Naming | `classesShouldNotMatch` | Classes should not match specific naming patterns (e.g., `.*Impl`). |
| Naming | `classesAnnotatedWithShouldMatch` | Classes annotated with a specific annotation should match specific naming patterns. |
| Naming | `methodsShouldNotMatch` | Methods should not match specific naming patterns. |
| Naming | `methodsAnnotatedWithShouldMatch` | Methods annotated with a specific annotation should match specific naming patterns. |
| Naming | `fieldsShouldNotMatch` | Fields should not match specific naming patterns. |
| Naming | `fieldsShouldMatch` | Fields should match specific naming patterns for specific classes. |
| Naming | `fieldsAnnotatedWithShouldMatch` | Fields annotated with a specific annotation should match specific naming patterns. |
| Naming | `constantsShouldFollowConventions` | Constants should follow naming conventions, except `serialVersionUID`. |
| Naming | `interfacesShouldNotHavePrefixI` | Interfaces should not have the prefix `I`. |

### Logging Rules

Expand Down Expand Up @@ -268,6 +269,18 @@ Taikai.builder()
.check();
```

- **Methods Should Not Declare Specific Exception**: Ensure that methods with names matching a specified pattern do not declare a specified exception type.

```java
Taikai.builder()
.namespace("com.company.yourproject")
.java(java -> java
.methodsShouldNotDeclareException("should*", SpecificException.class)
.methodsShouldNotDeclareException("should*", "com.company.yourproject.SpecificException"))
.build()
.check();
```

- **Utility Classes Should Be Final and Have Private Constructor**: Ensure that utility classes with only `static` methods except `main` should be declared as `final` and have `private` constructors to prevent instantiation.

```java
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/enofex/taikai/java/JavaConfigurer.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ public JavaConfigurer methodsShouldNotDeclareGenericExceptions(Configuration con
.as("Methods should not declare generic Exception or RuntimeException"), configuration));
}

public JavaConfigurer methodsShouldNotDeclareException(String regex,
Class<? extends Throwable> clazz) {
return methodsShouldNotDeclareException(regex, clazz, Configuration.defaultConfiguration());
}

public JavaConfigurer methodsShouldNotDeclareException(String regex,
Class<? extends Throwable> clazz, Configuration configuration) {
return addRule(TaikaiRule.of(methods()
.that().haveNameMatching(regex)
.should().notDeclareThrowableOfType(clazz)
.as("Methods have name matching %s should not declare %s".formatted(regex, clazz)),
configuration));
}

public JavaConfigurer methodsShouldNotDeclareException(String regex, String typeName) {
return methodsShouldNotDeclareException(regex, typeName, Configuration.defaultConfiguration());
}

public JavaConfigurer methodsShouldNotDeclareException(String regex, String typeName,
Configuration configuration) {
return addRule(TaikaiRule.of(methods()
.that().haveNameMatching(regex)
.should().notDeclareThrowableOfType(typeName)
.as("Methods have name matching %s should not declare %s".formatted(regex, typeName)),
configuration));
}

public JavaConfigurer noUsageOfDeprecatedAPIs() {
return noUsageOfDeprecatedAPIs(Configuration.defaultConfiguration());
}
Expand Down
1 change: 1 addition & 0 deletions src/test/java/com/enofex/taikai/Usage.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public static void main(String[] args) {
.classesShouldBeAnnotatedWith("regex", DisplayName.class)
.classesAnnotatedWithShouldResideInPackage(DisplayName.class, "com.enofex.taikai")
.methodsShouldNotDeclareGenericExceptions()
.methodsShouldNotDeclareException("regex", RuntimeException.class)
.finalClassesShouldNotHaveProtectedMembers()
.utilityClassesShouldBeFinalAndHavePrivateConstructor()
.serialVersionUIDFieldsShouldBeStaticFinalLong()
Expand Down

0 comments on commit 671f552

Please sign in to comment.