diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java index 6ab29bc2d0..96159741ac 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java @@ -13,6 +13,7 @@ import com.tngtech.archunit.junit.ArchUnitRunner; import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.lang.CompositeArchRule; import com.tngtech.archunit.lang.ConditionEvents; import com.tngtech.archunit.lang.SimpleConditionEvent; import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; @@ -101,6 +102,16 @@ public class PublicAPIRules { .and().doNotHaveName("adhereToPlantUmlDiagram") .should().haveRawParameterTypes(thatArePublic()); + @ArchTest + public static final ArchRule Guava_should_not_leak_into_public_API = + CompositeArchRule.of( + classes().that(publicAPI()).should().notBeAssignableTo(guavaClass())) + .and(codeUnits() + .that().arePublic() + .and().areDeclaredInClassesThat(are(publicAPI())) + .should().haveRawParameterTypes(withoutGuava()) + .andShould().haveRawReturnType(not(guavaClass()).as("that are no Guava types"))); + private static DescribedPredicate publicAPI() { return annotatedWith(PublicAPI.class).forSubType() .or(haveMemberThatBelongsToPublicApi()) @@ -316,4 +327,28 @@ public boolean apply(List input) { } }; } + + private static DescribedPredicate guavaClass() { + return JavaClass.Functions.GET_PACKAGE_NAME.is( + new DescribedPredicate("") { + @Override + public boolean apply(String input) { + return input.contains(".google."); + } + }).as("Guava Class"); + } + + private static DescribedPredicate> withoutGuava() { + return new DescribedPredicate>("without Guava") { + @Override + public boolean apply(List input) { + for (JavaClass parameterType : input) { + if (guavaClass().apply(parameterType)) { + return false; + } + } + return true; + } + }; + } } diff --git a/archunit/src/main/java/com/tngtech/archunit/base/ForwardingCollection.java b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingCollection.java new file mode 100644 index 0000000000..f174a450e9 --- /dev/null +++ b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingCollection.java @@ -0,0 +1,125 @@ +/* + * Copyright 2019 TNG Technology Consulting GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tngtech.archunit.base; + +import java.util.Collection; +import java.util.Iterator; + +import com.tngtech.archunit.PublicAPI; + +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + +@PublicAPI(usage = ACCESS) +public abstract class ForwardingCollection implements Collection { + protected ForwardingCollection() { + } + + protected abstract Collection delegate(); + + @Override + @PublicAPI(usage = ACCESS) + public int size() { + return delegate().size(); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean isEmpty() { + return delegate().isEmpty(); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean contains(Object o) { + return delegate().contains(o); + } + + @Override + @PublicAPI(usage = ACCESS) + public Iterator iterator() { + return delegate().iterator(); + } + + @Override + @PublicAPI(usage = ACCESS) + public Object[] toArray() { + return delegate().toArray(); + } + + @Override + @PublicAPI(usage = ACCESS) + @SuppressWarnings("SuspiciousToArrayCall") + public T1[] toArray(T1[] a) { + return delegate().toArray(a); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean add(T t) { + return delegate().add(t); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean remove(Object o) { + return delegate().remove(o); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean containsAll(Collection c) { + return delegate().containsAll(c); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean addAll(Collection c) { + return delegate().addAll(c); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean removeAll(Collection c) { + return delegate().removeAll(c); + } + + @Override + @PublicAPI(usage = ACCESS) + public boolean retainAll(Collection c) { + return delegate().retainAll(c); + } + + @Override + @PublicAPI(usage = ACCESS) + public void clear() { + delegate().clear(); + } + + @Override + public int hashCode() { + return delegate().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj == this || delegate().equals(obj); + } + + @Override + public String toString() { + return delegate().toString(); + } +} diff --git a/archunit/src/main/java/com/tngtech/archunit/base/ForwardingList.java b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingList.java new file mode 100644 index 0000000000..76ec8903e7 --- /dev/null +++ b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingList.java @@ -0,0 +1,93 @@ +/* + * Copyright 2019 TNG Technology Consulting GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tngtech.archunit.base; + +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +import com.tngtech.archunit.PublicAPI; + +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + +@PublicAPI(usage = ACCESS) +public abstract class ForwardingList extends ForwardingCollection implements List { + protected ForwardingList() { + } + + @Override + protected abstract List delegate(); + + @Override + @PublicAPI(usage = ACCESS) + public boolean addAll(int index, Collection c) { + return delegate().addAll(index, c); + } + + @Override + @PublicAPI(usage = ACCESS) + public T get(int index) { + return delegate().get(index); + } + + @Override + @PublicAPI(usage = ACCESS) + public T set(int index, T element) { + return delegate().set(index, element); + } + + @Override + @PublicAPI(usage = ACCESS) + public void add(int index, T element) { + delegate().add(index, element); + } + + @Override + @PublicAPI(usage = ACCESS) + public T remove(int index) { + return delegate().remove(index); + } + + @Override + @PublicAPI(usage = ACCESS) + public int indexOf(Object o) { + return delegate().indexOf(o); + } + + @Override + @PublicAPI(usage = ACCESS) + public int lastIndexOf(Object o) { + return delegate().lastIndexOf(o); + } + + @Override + @PublicAPI(usage = ACCESS) + public ListIterator listIterator() { + return delegate().listIterator(); + } + + @Override + @PublicAPI(usage = ACCESS) + public ListIterator listIterator(int index) { + return delegate().listIterator(index); + } + + @Override + @PublicAPI(usage = ACCESS) + public List subList(int fromIndex, int toIndex) { + return delegate().subList(fromIndex, toIndex); + } +} diff --git a/archunit/src/main/java/com/tngtech/archunit/base/ForwardingSet.java b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingSet.java new file mode 100644 index 0000000000..e28753a277 --- /dev/null +++ b/archunit/src/main/java/com/tngtech/archunit/base/ForwardingSet.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 TNG Technology Consulting GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tngtech.archunit.base; + +import java.util.Set; + +import com.tngtech.archunit.PublicAPI; + +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + +@PublicAPI(usage = ACCESS) +public abstract class ForwardingSet extends ForwardingCollection implements Set { + protected ForwardingSet() { + } + + @Override + protected abstract Set delegate(); +} diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java index 326dc8adc3..7e2a3edb25 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java @@ -80,16 +80,19 @@ public abstract class AccessTarget implements HasName.AndFullName, CanBeAnnotate } @Override + @PublicAPI(usage = ACCESS) public String getName() { return name; } @Override + @PublicAPI(usage = ACCESS) public JavaClass getOwner() { return owner; } @Override + @PublicAPI(usage = ACCESS) public String getFullName() { return fullName; } @@ -139,6 +142,7 @@ public String toString() { * @return true if one of the resolved targets is annotated with the given type */ @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(Class annotationType) { return isAnnotatedWith(annotationType.getName()); } @@ -147,6 +151,7 @@ public boolean isAnnotatedWith(Class annotationType) { * @see AccessTarget#isAnnotatedWith(Class) */ @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(final String annotationTypeName) { return anyMember(new Predicate() { @Override @@ -164,6 +169,7 @@ public boolean apply(JavaMember input) { * @return true if one of the resolved targets is annotated with an annotation matching the predicate */ @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(final DescribedPredicate predicate) { return anyMember(new Predicate() { @Override @@ -174,11 +180,13 @@ public boolean apply(JavaMember input) { } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(Class annotationType) { return isMetaAnnotatedWith(annotationType.getName()); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(final String annotationTypeName) { return anyMember(new Predicate() { @Override @@ -189,6 +197,7 @@ public boolean apply(JavaMember input) { } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(final DescribedPredicate predicate) { return anyMember(new Predicate() { @Override @@ -243,11 +252,13 @@ public static final class FieldAccessTarget extends AccessTarget implements HasT */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getType() { return getRawType(); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getRawType() { return type; } @@ -265,11 +276,13 @@ public Optional resolveField() { * @see #resolveField() */ @Override + @PublicAPI(usage = ACCESS) public Set resolve() { return resolveField().asSet(); } @Override + @PublicAPI(usage = ACCESS) String getDescription() { return "field <" + getFullName() + ">"; } @@ -310,11 +323,13 @@ public abstract static class CodeUnitCallTarget extends AccessTarget */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClassList getParameters() { return getRawParameterTypes(); } @Override + @PublicAPI(usage = ACCESS) public JavaClassList getRawParameterTypes() { return DomainObjectCreationContext.createJavaClassList(parameters); } @@ -324,16 +339,19 @@ public JavaClassList getRawParameterTypes() { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getReturnType() { return getRawReturnType(); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getRawReturnType() { return returnType; } @Override + @PublicAPI(usage = ACCESS) public ThrowsClause getThrowsClause() { List> resolvedThrowsClauses = FluentIterable.from(resolve()) .transform(toGuava(JavaCodeUnit.Functions.Get.throwsClause())) @@ -365,6 +383,7 @@ private List intersectTypesOf(List> throws * @see MethodCallTarget#resolve() */ @Override + @PublicAPI(usage = ACCESS) public abstract Set resolve(); public static final class Functions { @@ -405,11 +424,13 @@ public Optional resolveConstructor() { * @see #resolveConstructor() */ @Override + @PublicAPI(usage = ACCESS) public Set resolve() { return resolveConstructor().asSet(); } @Override + @PublicAPI(usage = ACCESS) String getDescription() { return "constructor <" + getFullName() + ">"; } @@ -477,11 +498,13 @@ public static final class MethodCallTarget extends CodeUnitCallTarget { * @return Set of matching methods, usually a single target */ @Override + @PublicAPI(usage = ACCESS) public Set resolve() { return methods.get(); } @Override + @PublicAPI(usage = ACCESS) String getDescription() { return "method <" + getFullName() + ">"; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java index b36ce89444..e7ce9261dc 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java @@ -116,11 +116,13 @@ public JavaClass getTargetClass() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return description; } @Override + @PublicAPI(usage = ACCESS) public SourceCodeLocation getSourceCodeLocation() { return sourceCodeLocation; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAccess.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAccess.java index e6b2e2a047..1e5c841502 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAccess.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAccess.java @@ -22,9 +22,9 @@ import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.base.HasDescription; import com.tngtech.archunit.core.domain.properties.HasName; -import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.domain.properties.HasOwner; import com.tngtech.archunit.core.domain.properties.HasOwner.Functions.Get; +import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.importer.DomainBuilders; import static com.google.common.base.Preconditions.checkNotNull; @@ -48,6 +48,7 @@ public abstract class JavaAccess } @Override + @PublicAPI(usage = ACCESS) public String getName() { return target.getName(); } @@ -78,11 +79,13 @@ public int getLineNumber() { } @Override + @PublicAPI(usage = ACCESS) public JavaCodeUnit getOwner() { return getOrigin(); } @Override + @PublicAPI(usage = ACCESS) public SourceCodeLocation getSourceCodeLocation() { return sourceCodeLocation; } @@ -117,6 +120,7 @@ String additionalToStringFields() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { String description = origin.getDescription() + " " + descriptionVerb() + " " + getTarget().getDescription(); return description + " in " + getSourceCodeLocation(); diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAnnotation.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAnnotation.java index 277f109fbd..687fce3e54 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAnnotation.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaAnnotation.java @@ -79,11 +79,13 @@ public final class JavaAnnotation implements HasType { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getType() { return getRawType(); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getRawType() { return type; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java index 205ebe57ba..c3bf2be13f 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java @@ -121,16 +121,19 @@ public SourceCodeLocation getSourceCodeLocation() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return "Class <" + getName() + ">"; } @Override + @PublicAPI(usage = ACCESS) public String getName() { return javaType.getName(); } @Override + @PublicAPI(usage = ACCESS) public String getFullName() { return getName(); } @@ -180,36 +183,43 @@ public boolean isInnerClass() { } @Override + @PublicAPI(usage = ACCESS) public Set getModifiers() { return modifiers; } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(Class annotationType) { return isAnnotatedWith(annotationType.getName()); } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(String annotationTypeName) { return annotations.get().containsKey(annotationTypeName); } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(DescribedPredicate predicate) { return CanBeAnnotated.Utils.isAnnotatedWith(annotations.get().values(), predicate); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(Class type) { return isMetaAnnotatedWith(type.getName()); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(String typeName) { return isMetaAnnotatedWith(GET_RAW_TYPE.then(GET_NAME).is(equalTo(typeName))); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(DescribedPredicate predicate) { return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.get().values(), predicate); } @@ -222,17 +232,20 @@ public boolean isMetaAnnotatedWith(DescribedPredicate pr * @see #tryGetAnnotationOfType(Class) */ @Override + @PublicAPI(usage = ACCESS) public A getAnnotationOfType(Class type) { return getAnnotationOfType(type.getName()).as(type); } @Override + @PublicAPI(usage = ACCESS) public JavaAnnotation getAnnotationOfType(String typeName) { return tryGetAnnotationOfType(typeName).getOrThrow(new IllegalArgumentException( String.format("Type %s is not annotated with @%s", getSimpleName(), Formatters.ensureSimpleName(typeName)))); } @Override + @PublicAPI(usage = ACCESS) public Set getAnnotations() { return ImmutableSet.copyOf(annotations.get().values()); } @@ -245,6 +258,7 @@ public Set getAnnotations() { * @see #getAnnotationOfType(Class) */ @Override + @PublicAPI(usage = ACCESS) public Optional tryGetAnnotationOfType(Class type) { return tryGetAnnotationOfType(type.getName()).transform(toAnnotationOfType(type)); } @@ -253,6 +267,7 @@ public Optional tryGetAnnotationOfType(Class type) * Same as {@link #tryGetAnnotationOfType(Class)}, but takes the type name. */ @Override + @PublicAPI(usage = ACCESS) public Optional tryGetAnnotationOfType(String typeName) { return Optional.fromNullable(annotations.get().get(typeName)); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassList.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassList.java index 7c17fb4764..44f803673c 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassList.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassList.java @@ -17,9 +17,9 @@ import java.util.List; -import com.google.common.collect.ForwardingList; import com.google.common.collect.ImmutableList; import com.tngtech.archunit.PublicAPI; +import com.tngtech.archunit.base.ForwardingList; import com.tngtech.archunit.base.Function; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClasses.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClasses.java index 6952565234..841aa81982 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClasses.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClasses.java @@ -18,24 +18,25 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.DescribedIterable; import com.tngtech.archunit.base.DescribedPredicate; +import com.tngtech.archunit.base.ForwardingCollection; import com.tngtech.archunit.base.Guava; import com.tngtech.archunit.core.domain.DomainObjectCreationContext.AccessContext; import com.tngtech.archunit.core.domain.properties.CanOverrideDescription; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Iterables.isEmpty; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; -public final class JavaClasses implements DescribedIterable, CanOverrideDescription { +public final class JavaClasses extends ForwardingCollection implements DescribedIterable, CanOverrideDescription { private final ImmutableMap classes; private final JavaPackage defaultPackage; private final String description; @@ -76,11 +77,6 @@ public String toString() { return getClass().getSimpleName() + "{classes=" + classes + '}'; } - @Override - public Iterator iterator() { - return classes.values().iterator(); - } - /** * @param reflectedType a Java {@link Class} object * @return true, if an equivalent {@link JavaClass} is contained, false otherwise @@ -155,9 +151,27 @@ public JavaPackage getDefaultPackage() { return defaultPackage; } - @PublicAPI(usage = ACCESS) - public int size() { - return classes.size(); + @Override + public int hashCode() { + return Objects.hash(classes.keySet(), description); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final JavaClasses other = (JavaClasses) obj; + return Objects.equals(this.classes.keySet(), other.classes.keySet()) + && Objects.equals(this.description, other.description); + } + + @Override + protected Collection delegate() { + return classes.values(); } static JavaClasses of(Iterable classes) { @@ -165,7 +179,7 @@ static JavaClasses of(Iterable classes) { for (JavaClass clazz : classes) { mapping.put(clazz.getName(), clazz); } - JavaPackage defaultPackage = !isEmpty(classes) + JavaPackage defaultPackage = !Iterables.isEmpty(classes) ? getRoot(classes.iterator().next().getPackage()) : JavaPackage.from(classes); return new JavaClasses(defaultPackage, mapping); diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java index 3da7d5ae6b..f6441f4358 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java @@ -63,6 +63,7 @@ public abstract class JavaCodeUnit extends JavaMember implements HasParameterTyp } @Override + @PublicAPI(usage = ACCESS) public String getFullName() { return fullName; } @@ -72,16 +73,19 @@ public String getFullName() { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClassList getParameters() { return getRawParameterTypes(); } @Override + @PublicAPI(usage = ACCESS) public JavaClassList getRawParameterTypes() { return parameters; } @Override + @PublicAPI(usage = ACCESS) public abstract ThrowsClause getThrowsClause(); /** @@ -97,11 +101,13 @@ public JavaClassList getExceptionTypes() { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getReturnType() { return getRawReturnType(); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getRawReturnType() { return returnType; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaConstructor.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaConstructor.java index 1022ae7f2b..5c7d6621e7 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaConstructor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaConstructor.java @@ -47,11 +47,13 @@ public final class JavaConstructor extends JavaCodeUnit { } @Override + @PublicAPI(usage = ACCESS) public ThrowsClause getThrowsClause() { return throwsClause; } @Override + @PublicAPI(usage = ACCESS) public boolean isConstructor() { return true; } @@ -62,11 +64,13 @@ public Set getCallsOfSelf() { } @Override + @PublicAPI(usage = ACCESS) public Set getAccessesToSelf() { return callsToSelf; } @Override + @PublicAPI(usage = ACCESS) @ResolvesTypesViaReflection @MayResolveTypesViaReflection(reason = "This is not part of the import and a specific decision to rely on the classpath") public Constructor reflect() { @@ -74,6 +78,7 @@ public Constructor reflect() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return "Constructor <" + getFullName() + ">"; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java index 69c307a469..d4ec5b65a2 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java @@ -21,6 +21,7 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.ArchUnitException.InconsistentClassPathException; import com.tngtech.archunit.core.MayResolveTypesViaReflection; import com.tngtech.archunit.core.ResolvesTypesViaReflection; @@ -28,6 +29,7 @@ import com.tngtech.archunit.core.importer.DomainBuilders; import static com.google.common.base.Preconditions.checkNotNull; +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; public class JavaField extends JavaMember implements HasType { private final JavaClass type; @@ -41,6 +43,7 @@ public class JavaField extends JavaMember implements HasType { } @Override + @PublicAPI(usage = ACCESS) public String getFullName() { return getOwner().getName() + "." + getName(); } @@ -50,21 +53,25 @@ public String getFullName() { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getType() { return getRawType(); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getRawType() { return type; } @Override + @PublicAPI(usage = ACCESS) public Set getAccessesToSelf() { return accessesToSelf.get(); } @Override + @PublicAPI(usage = ACCESS) @ResolvesTypesViaReflection @MayResolveTypesViaReflection(reason = "This is not part of the import and a specific decision to rely on the classpath") public Field reflect() { @@ -72,6 +79,7 @@ public Field reflect() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return "Field <" + getFullName() + ">"; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java index 5353a72910..3c06f4e097 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java @@ -32,9 +32,9 @@ import com.tngtech.archunit.core.domain.properties.HasDescriptor; import com.tngtech.archunit.core.domain.properties.HasModifiers; import com.tngtech.archunit.core.domain.properties.HasName; -import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.domain.properties.HasOwner; import com.tngtech.archunit.core.domain.properties.HasOwner.Functions.Get; +import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.importer.DomainBuilders.JavaMemberBuilder; import static com.google.common.base.Preconditions.checkNotNull; @@ -64,6 +64,7 @@ public abstract class JavaMember implements } @Override + @PublicAPI(usage = ACCESS) public Set getAnnotations() { return ImmutableSet.copyOf(annotations.get().values()); } @@ -74,11 +75,13 @@ public Set getAnnotations() { * @throws IllegalArgumentException if there is no annotation of the respective reflection type */ @Override + @PublicAPI(usage = ACCESS) public A getAnnotationOfType(Class type) { return getAnnotationOfType(type.getName()).as(type); } @Override + @PublicAPI(usage = ACCESS) public JavaAnnotation getAnnotationOfType(String typeName) { return tryGetAnnotationOfType(typeName).getOrThrow(new IllegalArgumentException(String.format( "Member %s is not annotated with @%s", @@ -86,61 +89,73 @@ public JavaAnnotation getAnnotationOfType(String typeName) { } @Override + @PublicAPI(usage = ACCESS) public Optional tryGetAnnotationOfType(Class type) { return tryGetAnnotationOfType(type.getName()).transform(toAnnotationOfType(type)); } @Override + @PublicAPI(usage = ACCESS) public Optional tryGetAnnotationOfType(String typeName) { return Optional.fromNullable(annotations.get().get(typeName)); } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(Class type) { return isAnnotatedWith(type.getName()); } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(String typeName) { return annotations.get().containsKey(typeName); } @Override + @PublicAPI(usage = ACCESS) public boolean isAnnotatedWith(DescribedPredicate predicate) { return CanBeAnnotated.Utils.isAnnotatedWith(annotations.get().values(), predicate); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(Class type) { return isMetaAnnotatedWith(type.getName()); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(String typeName) { return isMetaAnnotatedWith(GET_RAW_TYPE.then(GET_NAME).is(equalTo(typeName))); } @Override + @PublicAPI(usage = ACCESS) public boolean isMetaAnnotatedWith(DescribedPredicate predicate) { return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.get().values(), predicate); } @Override + @PublicAPI(usage = ACCESS) public JavaClass getOwner() { return owner; } @Override + @PublicAPI(usage = ACCESS) public SourceCodeLocation getSourceCodeLocation() { return sourceCodeLocation; } @Override + @PublicAPI(usage = ACCESS) public Set getModifiers() { return modifiers; } @Override + @PublicAPI(usage = ACCESS) public String getName() { return name; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMethod.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMethod.java index bc6fc549fe..443dbc221e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMethod.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMethod.java @@ -46,6 +46,7 @@ public class JavaMethod extends JavaCodeUnit { } @Override + @PublicAPI(usage = ACCESS) public ThrowsClause getThrowsClause() { return throwsClause; } @@ -68,11 +69,13 @@ public Set getCallsOfSelf() { } @Override + @PublicAPI(usage = ACCESS) public Set getAccessesToSelf() { return callsToSelf.get(); } @Override + @PublicAPI(usage = ACCESS) @ResolvesTypesViaReflection @MayResolveTypesViaReflection(reason = "This is not part of the import and a specific decision to rely on the classpath") public Method reflect() { @@ -80,6 +83,7 @@ public Method reflect() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return "Method <" + getFullName() + ">"; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java index 9d833a9b90..170f064b5b 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java @@ -92,7 +92,7 @@ private void setParent(JavaPackage parent) { * @return all classes directly contained in this package, no classes in sub-packages (compare {@link #getAllClasses()}) */ @PublicAPI(usage = ACCESS) - public Iterable getClasses() { + public Set getClasses() { return classes; } @@ -100,7 +100,7 @@ public Iterable getClasses() { * @return all classes contained in this package or any sub-package (compare {@link #getClasses()}) */ @PublicAPI(usage = ACCESS) - public Iterable getAllClasses() { + public Set getAllClasses() { ImmutableSet.Builder result = ImmutableSet.builder().addAll(classes); for (JavaPackage subPackage : getSubPackages()) { result.addAll(subPackage.getAllClasses()); @@ -113,8 +113,8 @@ public Iterable getAllClasses() { * (compare {@link #getAllSubPackages()}) */ @PublicAPI(usage = ACCESS) - public Iterable getSubPackages() { - return subPackages.values(); + public Set getSubPackages() { + return ImmutableSet.copyOf(subPackages.values()); } /** @@ -123,7 +123,7 @@ public Iterable getSubPackages() { * (compare {@link #getSubPackages()}) */ @PublicAPI(usage = ACCESS) - public Iterable getAllSubPackages() { + public Set getAllSubPackages() { ImmutableSet.Builder result = ImmutableSet.builder(); for (JavaPackage subPackage : getSubPackages()) { result.add(subPackage); @@ -474,19 +474,19 @@ public String apply(JavaPackage javaPackage) { }; @PublicAPI(usage = ACCESS) - public static final ChainableFunction> GET_CLASSES = - new ChainableFunction>() { + public static final ChainableFunction> GET_CLASSES = + new ChainableFunction>() { @Override - public Iterable apply(JavaPackage javaPackage) { + public Set apply(JavaPackage javaPackage) { return javaPackage.getClasses(); } }; @PublicAPI(usage = ACCESS) - public static final ChainableFunction> GET_SUB_PACKAGES = - new ChainableFunction>() { + public static final ChainableFunction> GET_SUB_PACKAGES = + new ChainableFunction>() { @Override - public Iterable apply(JavaPackage javaPackage) { + public Set apply(JavaPackage javaPackage) { return javaPackage.getSubPackages(); } }; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaStaticInitializer.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaStaticInitializer.java index ec0463f3ab..7599df19c9 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaStaticInitializer.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaStaticInitializer.java @@ -33,21 +33,25 @@ public class JavaStaticInitializer extends JavaCodeUnit { } @Override + @PublicAPI(usage = ACCESS) public Set> getAccessesToSelf() { return emptySet(); } @Override + @PublicAPI(usage = ACCESS) public Member reflect() { throw new UnsupportedOperationException("Can't reflect on a static initializer"); } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return "Static Initializer <" + getFullName() + ">"; } @Override + @PublicAPI(usage = ACCESS) public ThrowsClause getThrowsClause() { return ThrowsClause.empty(this); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/ThrowsDeclaration.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/ThrowsDeclaration.java index 191e8d74d3..44d46735ef 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/ThrowsDeclaration.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/ThrowsDeclaration.java @@ -98,6 +98,7 @@ public JavaClass getDeclaringClass() { */ @Override @Deprecated + @PublicAPI(usage = ACCESS) public JavaClass getType() { return getRawType(); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileSource.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileSource.java index cdfadba997..630f4774ab 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileSource.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileSource.java @@ -37,6 +37,7 @@ import com.google.common.collect.FluentIterable; import com.tngtech.archunit.Internal; +@Internal interface ClassFileSource extends Iterable { @Internal class FromFilePath extends SimpleFileVisitor implements ClassFileSource { @@ -60,7 +61,7 @@ public Iterator iterator() { } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (shouldBeConsidered(file)) { classFileLocations.add(new InputStreamSupplierClassFileLocation(file.toUri(), newInputStreamSupplierFor(file))); } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/CompositeArchRule.java b/archunit/src/main/java/com/tngtech/archunit/lang/CompositeArchRule.java index 6f2bed5e5f..6761c62952 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/CompositeArchRule.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/CompositeArchRule.java @@ -56,16 +56,19 @@ public CompositeArchRule and(ArchRule rule) { } @Override + @PublicAPI(usage = ACCESS) public void check(JavaClasses classes) { Assertions.check(this, classes); } @Override + @PublicAPI(usage = ACCESS) public CompositeArchRule because(String reason) { return new CompositeArchRule(priority, rules, createBecauseDescription(this, reason)); } @Override + @PublicAPI(usage = ACCESS) public EvaluationResult evaluate(JavaClasses classes) { EvaluationResult result = new EvaluationResult(this, priority); for (ArchRule rule : rules) { @@ -75,11 +78,13 @@ public EvaluationResult evaluate(JavaClasses classes) { } @Override + @PublicAPI(usage = ACCESS) public CompositeArchRule as(String newDescription) { return new CompositeArchRule(priority, rules, newDescription); } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return description; } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenConstructorsConjunction.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenConstructorsConjunction.java index 8df606c306..e0af4301f5 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenConstructorsConjunction.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenConstructorsConjunction.java @@ -15,14 +15,19 @@ */ package com.tngtech.archunit.lang.syntax.elements; +import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaConstructor; +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + public interface GivenConstructorsConjunction extends GivenCodeUnitsConjunction { @Override + @PublicAPI(usage = ACCESS) GivenConstructorsConjunction and(DescribedPredicate predicate); @Override + @PublicAPI(usage = ACCESS) GivenConstructorsConjunction or(DescribedPredicate predicate); } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenFieldsConjunction.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenFieldsConjunction.java index 32e2d71d35..6c22ca1a9c 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenFieldsConjunction.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenFieldsConjunction.java @@ -41,8 +41,10 @@ public interface GivenFieldsConjunction extends GivenMembersConjunction predicate); @Override + @PublicAPI(usage = ACCESS) FieldsShouldConjunction should(ArchCondition condition); @Override + @PublicAPI(usage = ACCESS) FieldsShould should(); } diff --git a/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java b/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java index 28df8f8671..d94f785796 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java @@ -129,6 +129,7 @@ public LayerDefinition layer(String name) { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { if (overriddenDescription.isPresent()) { return overriddenDescription.get(); @@ -145,6 +146,7 @@ public String getDescription() { } @Override + @PublicAPI(usage = ACCESS) public EvaluationResult evaluate(JavaClasses classes) { EvaluationResult result = new EvaluationResult(this, Priority.MEDIUM); for (LayerDependencySpecification specification : dependencySpecifications) { @@ -171,16 +173,19 @@ private DescribedPredicate originPackageMatchesIfDependencyIsRelevan } @Override + @PublicAPI(usage = ACCESS) public void check(JavaClasses classes) { Assertions.check(this, classes); } @Override + @PublicAPI(usage = ACCESS) public ArchRule because(String reason) { return ArchRule.Factory.withBecause(this, reason); } @Override + @PublicAPI(usage = ACCESS) public LayeredArchitecture as(String newDescription) { return new LayeredArchitecture( layerDefinitions, dependencySpecifications, diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/Slice.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/Slice.java index bef2ee2344..43b48678af 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/Slice.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/Slice.java @@ -21,9 +21,9 @@ import java.util.Set; import com.google.common.base.Joiner; -import com.google.common.collect.ForwardingSet; import com.google.common.collect.ImmutableSet; import com.tngtech.archunit.PublicAPI; +import com.tngtech.archunit.base.ForwardingSet; import com.tngtech.archunit.base.HasDescription; import com.tngtech.archunit.core.domain.Dependency; import com.tngtech.archunit.core.domain.JavaClass; @@ -81,6 +81,7 @@ protected Set delegate() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return description.format(matchingGroups); } @@ -95,6 +96,7 @@ public String getDescription() { * @return Same slice with different description */ @Override + @PublicAPI(usage = ACCESS) public Slice as(String pattern) { return new Slice(sliceAssignment, matchingGroups, new Description(pattern), classes); } diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceDependency.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceDependency.java index 3ce06ae9b5..3bdfd5f5bc 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceDependency.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceDependency.java @@ -65,6 +65,7 @@ public Slice getTarget() { } @Override + @PublicAPI(usage = ACCESS) public String getDescription() { return String.format("%s calls %s:%n%s", origin.getDescription(), diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceRule.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceRule.java index 942c98f93b..3896831e61 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceRule.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/SliceRule.java @@ -59,26 +59,31 @@ private SliceRule(Slices.Transformer inputTransformer, Priority priority, List, CanOverrideDescri SlicesShould should(); @Override + @PublicAPI(usage = ACCESS) GivenNamedSlices as(String newDescription); @Override + @PublicAPI(usage = ACCESS) GivenSlicesConjunction that(DescribedPredicate predicate); } \ No newline at end of file diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlices.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlices.java index 208eed4c76..37bab49013 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlices.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlices.java @@ -24,5 +24,6 @@ public interface GivenSlices extends GivenNamedSlices { GivenNamedSlices namingSlices(String pattern); @Override + @PublicAPI(usage = ACCESS) GivenSlices as(String newDescription); } \ No newline at end of file diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlicesConjunction.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlicesConjunction.java index 0e50740fea..d23f320397 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlicesConjunction.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/syntax/GivenSlicesConjunction.java @@ -28,9 +28,11 @@ public interface GivenSlicesConjunction extends GivenConjunction { SlicesShould should(); @Override + @PublicAPI(usage = ACCESS) GivenSlicesConjunction and(DescribedPredicate predicate); @Override + @PublicAPI(usage = ACCESS) GivenSlicesConjunction or(DescribedPredicate predicate); @PublicAPI(usage = ACCESS) diff --git a/build.gradle b/build.gradle index 1583f036e7..08a6b77d70 100644 --- a/build.gradle +++ b/build.gradle @@ -112,7 +112,7 @@ wrapper { allprojects { group = 'com.tngtech.archunit' - version = '0.10.1' + version = '0.10.2-SNAPSHOT' repositories { mavenCentral()