Skip to content

Commit

Permalink
First draft of a rule to deny access to upper packages. At the moment…
Browse files Browse the repository at this point in the history
… 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
codecholeric committed Jun 17, 2019
1 parent 812f3c3 commit 5f7fadc
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
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);
}
}
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;
}
}
}

0 comments on commit 5f7fadc

Please sign in to comment.