-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First draft of a rule to deny access to upper packages. At the moment…
… this makes it impossible to extend an abstract class in an upper package due to the constructor call -> discussion Issue: #151 Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
- Loading branch information
1 parent
812f3c3
commit 5f7fadc
Showing
2 changed files
with
67 additions
and
0 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
...ple/example-plain/src/test/java/com/tngtech/archunit/exampletest/DependencyRulesTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.tngtech.archunit.exampletest; | ||
|
||
import com.tngtech.archunit.core.domain.JavaClasses; | ||
import com.tngtech.archunit.core.importer.ClassFileImporter; | ||
import com.tngtech.archunit.example.ClassViolatingCodingRules; | ||
import org.junit.Test; | ||
import org.junit.experimental.categories.Category; | ||
|
||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; | ||
import static com.tngtech.archunit.library.DependencyRules.accessClassesThatResideInAnUpperPackage; | ||
|
||
@Category(Example.class) | ||
public class DependencyRulesTest { | ||
|
||
private final JavaClasses classes = new ClassFileImporter().importPackagesOf(ClassViolatingCodingRules.class); | ||
|
||
@Test | ||
public void no_accesses_to_upper_package() { | ||
noClasses().should(accessClassesThatResideInAnUpperPackage()) | ||
.check(classes); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
archunit/src/main/java/com/tngtech/archunit/library/DependencyRules.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.tngtech.archunit.library; | ||
|
||
import com.tngtech.archunit.PublicAPI; | ||
import com.tngtech.archunit.core.domain.JavaAccess; | ||
import com.tngtech.archunit.core.domain.JavaClass; | ||
import com.tngtech.archunit.lang.ArchCondition; | ||
import com.tngtech.archunit.lang.ConditionEvents; | ||
import com.tngtech.archunit.lang.SimpleConditionEvent; | ||
|
||
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; | ||
|
||
public class DependencyRules { | ||
|
||
@PublicAPI(usage = ACCESS) | ||
public static ArchCondition<JavaClass> accessClassesThatResideInAnUpperPackage() { | ||
return new AccessClassesThatResideInAnUpperPackageCondition(); | ||
} | ||
|
||
private static class AccessClassesThatResideInAnUpperPackageCondition extends ArchCondition<JavaClass> { | ||
AccessClassesThatResideInAnUpperPackageCondition() { | ||
super("access classes that reside in an upper package"); | ||
} | ||
|
||
@Override | ||
public void check(final JavaClass clazz, final ConditionEvents events) { | ||
for (JavaAccess<?> access : clazz.getAccessesFromSelf()) { | ||
boolean callToSuperPackage = isCallToSuperPackage(access.getOriginOwner(), access.getTargetOwner()); | ||
events.add(new SimpleConditionEvent(access, callToSuperPackage, access.getDescription())); | ||
} | ||
} | ||
|
||
private boolean isCallToSuperPackage(JavaClass origin, JavaClass target) { | ||
String originPackageName = getOutermostEnclosingClass(origin).getPackageName(); | ||
String targetSubPackagePrefix = getOutermostEnclosingClass(target).getPackageName() + "."; | ||
return originPackageName.startsWith(targetSubPackagePrefix); | ||
} | ||
|
||
private JavaClass getOutermostEnclosingClass(JavaClass javaClass) { | ||
while (javaClass.getEnclosingClass().isPresent()) { | ||
javaClass = javaClass.getEnclosingClass().get(); | ||
} | ||
return javaClass; | ||
} | ||
} | ||
} |