Skip to content

Commit 54fae8d

Browse files
authored
General Coding rule to detect usages of old time and date classes (#1384 / #1385)
With this commit new general rules are added which detect the usages of old time and date classes, e.g. java.util.Date.
2 parents 2d80ef6 + c4372b2 commit 54fae8d

File tree

7 files changed

+111
-0
lines changed

7 files changed

+111
-0
lines changed

archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,4 +509,18 @@ public void check(JavaClass implementationClass, ConditionEvents events) {
509509
.should(accessTargetWhere(JavaAccess.Predicates.target(annotatedWith(Deprecated.class))).as("access @Deprecated members"))
510510
.orShould(dependOnClassesThat(annotatedWith(Deprecated.class)).as("depend on @Deprecated classes"))
511511
.because("there should be a better alternative");
512+
513+
/**
514+
* A rule checking that no classes uses old date and time classes and point out to use the Java 8 time API.
515+
*/
516+
@PublicAPI(usage = ACCESS)
517+
public static final ArchRule OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED =
518+
noClasses()
519+
.should().dependOnClassesThat().haveFullyQualifiedName("java.sql.Date")
520+
.orShould().dependOnClassesThat().haveFullyQualifiedName("java.sql.Time")
521+
.orShould().dependOnClassesThat().haveFullyQualifiedName("java.sql.Timestamp")
522+
.orShould().dependOnClassesThat().haveFullyQualifiedName("java.util.Calendar")
523+
.orShould().dependOnClassesThat().haveFullyQualifiedName("java.util.Date")
524+
.as("java.time API should be used")
525+
.because("legacy date/time APIs have been replaced since Java 8 (JSR 310)");
512526
}

archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@
1010
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.customsuffix.subdir.ImplementationClassWithWrongTestClassPackageCustomSuffixTestingScenario;
1111
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.defaultsuffix.ImplementationClassWithWrongTestClassPackage;
1212
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.defaultsuffix.subdir.ImplementationClassWithWrongTestClassPackageTest;
13+
import com.tngtech.archunit.library.testclasses.timeapi.incorrect.UsesJavaSqlDate;
14+
import com.tngtech.archunit.library.testclasses.timeapi.incorrect.UsesJavaSqlTime;
15+
import com.tngtech.archunit.library.testclasses.timeapi.incorrect.UsesJavaSqlTimestamp;
16+
import com.tngtech.archunit.library.testclasses.timeapi.incorrect.UsesJavaUtilCalender;
17+
import com.tngtech.archunit.library.testclasses.timeapi.incorrect.UsesJavaUtilDate;
1318
import org.junit.Test;
1419

1520
import static com.tngtech.archunit.core.domain.JavaConstructor.CONSTRUCTOR_NAME;
1621
import static com.tngtech.archunit.library.GeneralCodingRules.ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE;
1722
import static com.tngtech.archunit.library.GeneralCodingRules.DEPRECATED_API_SHOULD_NOT_BE_USED;
23+
import static com.tngtech.archunit.library.GeneralCodingRules.OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED;
1824
import static com.tngtech.archunit.library.GeneralCodingRules.testClassesShouldResideInTheSamePackageAsImplementation;
1925
import static com.tngtech.archunit.testutil.Assertions.assertThatRule;
2026

@@ -180,4 +186,44 @@ void origin() {
180186
@SuppressWarnings("DeprecatedIsStillUsed")
181187
private @interface DeprecatedAnnotation {
182188
}
189+
190+
@Test
191+
public void OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED_should_fail_when_class_uses_java_util_date() {
192+
assertThatRule(OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED)
193+
.hasDescription("java.time API should be used, because legacy date/time APIs have been replaced since Java 8 (JSR 310)")
194+
.checking(new ClassFileImporter().importClasses(UsesJavaUtilDate.class))
195+
.hasViolationContaining("calls method <java.util.Date");
196+
}
197+
198+
@Test
199+
public void OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED_should_fail_when_class_uses_java_sql_timestamp() {
200+
assertThatRule(OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED)
201+
.hasDescription("java.time API should be used, because legacy date/time APIs have been replaced since Java 8 (JSR 310)")
202+
.checking(new ClassFileImporter().importClasses(UsesJavaSqlTimestamp.class))
203+
.hasViolationContaining("calls constructor <java.sql.Timestamp");
204+
}
205+
206+
@Test
207+
public void OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED_should_fail_when_class_uses_java_sql_time() {
208+
assertThatRule(OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED)
209+
.hasDescription("java.time API should be used, because legacy date/time APIs have been replaced since Java 8 (JSR 310)")
210+
.checking(new ClassFileImporter().importClasses(UsesJavaSqlTime.class))
211+
.hasViolationContaining("calls constructor <java.sql.Time");
212+
}
213+
214+
@Test
215+
public void OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED_should_fail_when_class_uses_java_sql_date() {
216+
assertThatRule(OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED)
217+
.hasDescription("java.time API should be used, because legacy date/time APIs have been replaced since Java 8 (JSR 310)")
218+
.checking(new ClassFileImporter().importClasses(UsesJavaSqlDate.class))
219+
.hasViolationContaining("calls constructor <java.sql.Date");
220+
}
221+
222+
@Test
223+
public void OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED_should_fail_when_class_uses_java_util_calender() {
224+
assertThatRule(OLD_DATE_AND_TIME_CLASSES_SHOULD_NOT_BE_USED)
225+
.hasDescription("java.time API should be used, because legacy date/time APIs have been replaced since Java 8 (JSR 310)")
226+
.checking(new ClassFileImporter().importClasses(UsesJavaUtilCalender.class))
227+
.hasViolationContaining("calls method <java.util.Calendar");
228+
}
183229
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.tngtech.archunit.library.testclasses.timeapi.incorrect;
2+
3+
import java.sql.Date;
4+
5+
public class UsesJavaSqlDate {
6+
7+
void usesSqlDate() {
8+
Date badUsage = new Date(System.currentTimeMillis());
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.tngtech.archunit.library.testclasses.timeapi.incorrect;
2+
3+
import java.sql.Time;
4+
5+
public class UsesJavaSqlTime {
6+
7+
void usesSqlTimestamp() {
8+
Time badUsage = new Time(System.currentTimeMillis());
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.tngtech.archunit.library.testclasses.timeapi.incorrect;
2+
3+
import java.sql.Timestamp;
4+
5+
public class UsesJavaSqlTimestamp {
6+
7+
void usesSqlTimestamp() {
8+
Timestamp badUsage = new Timestamp(System.currentTimeMillis());
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.tngtech.archunit.library.testclasses.timeapi.incorrect;
2+
3+
import java.util.Calendar;
4+
5+
public class UsesJavaUtilCalender {
6+
7+
void usesJavaUtilCalender() {
8+
Calendar badUsage = Calendar.getInstance();
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.tngtech.archunit.library.testclasses.timeapi.incorrect;
2+
3+
import java.time.Instant;
4+
import java.util.Date;
5+
6+
public class UsesJavaUtilDate {
7+
8+
void usesJavaUtilDate() {
9+
Date badDate = Date.from(Instant.now());
10+
}
11+
}

0 commit comments

Comments
 (0)