From ca18b17df44fe0d73720c4a6bc763e29366d1a78 Mon Sep 17 00:00:00 2001 From: Manfred Hanke Date: Sun, 24 Mar 2019 23:58:52 +0100 Subject: [PATCH] add methods().should().{be,notBe}{Static,Final} syntax Signed-off-by: Manfred Hanke --- .../lang/syntax/MethodsShouldInternal.java | 30 ++++++++- .../lang/syntax/elements/GivenMethods.java | 9 +++ .../elements/GivenMethodsConjunction.java | 9 +++ .../lang/syntax/elements/MethodsShould.java | 55 ++++++++++++++++ .../elements/MethodsShouldConjunction.java | 41 ++++++++++++ .../syntax/elements/MethodsShouldTest.java | 63 +++++++++++++++++++ 6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShould.java create mode 100644 archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldConjunction.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldTest.java diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MethodsShouldInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MethodsShouldInternal.java index dc47b41723..a9662efced 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MethodsShouldInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MethodsShouldInternal.java @@ -17,11 +17,19 @@ import com.tngtech.archunit.base.Function; import com.tngtech.archunit.core.domain.JavaMethod; +import com.tngtech.archunit.core.domain.JavaModifier; import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ClassesTransformer; import com.tngtech.archunit.lang.Priority; +import com.tngtech.archunit.lang.conditions.ArchConditions; +import com.tngtech.archunit.lang.syntax.elements.MethodsShould; +import com.tngtech.archunit.lang.syntax.elements.MethodsShouldConjunction; -class MethodsShouldInternal extends AbstractCodeUnitsShouldInternal { +import static com.tngtech.archunit.lang.conditions.ArchConditions.not; + +class MethodsShouldInternal + extends AbstractCodeUnitsShouldInternal + implements MethodsShould, MethodsShouldConjunction { MethodsShouldInternal( ClassesTransformer classesTransformer, @@ -53,4 +61,24 @@ private MethodsShouldInternal( MethodsShouldInternal copyWithNewCondition(ConditionAggregator newCondition) { return new MethodsShouldInternal(classesTransformer, priority, newCondition, prepareCondition); } + + @Override + public MethodsShouldInternal beStatic() { + return addCondition(ArchConditions.haveModifier(JavaModifier.STATIC).as("be static")); + } + + @Override + public MethodsShouldInternal notBeStatic() { + return addCondition(not(ArchConditions.haveModifier(JavaModifier.STATIC)).as("not be static")); + } + + @Override + public MethodsShouldInternal beFinal() { + return addCondition(ArchConditions.haveModifier(JavaModifier.FINAL).as("be final")); + } + + @Override + public MethodsShouldInternal notBeFinal() { + return addCondition(not(ArchConditions.haveModifier(JavaModifier.FINAL)).as("not be final")); + } } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethods.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethods.java index f7e5ff5577..de861b1414 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethods.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethods.java @@ -18,6 +18,7 @@ import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaMethod; +import com.tngtech.archunit.lang.ArchCondition; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; @@ -30,4 +31,12 @@ public interface GivenMethods extends GivenCodeUnits { @Override @PublicAPI(usage = ACCESS) GivenMethodsConjunction that(DescribedPredicate predicate); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShould should(); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShouldConjunction should(ArchCondition condition); } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethodsConjunction.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethodsConjunction.java index f0267dc493..1bb4574dd4 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethodsConjunction.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/GivenMethodsConjunction.java @@ -18,6 +18,7 @@ import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaMethod; +import com.tngtech.archunit.lang.ArchCondition; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; @@ -38,4 +39,12 @@ public interface GivenMethodsConjunction extends GivenCodeUnitsConjunction predicate); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShould should(); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShouldConjunction should(ArchCondition condition); } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShould.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShould.java new file mode 100644 index 0000000000..fd2c9c3462 --- /dev/null +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShould.java @@ -0,0 +1,55 @@ +/* + * 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.lang.syntax.elements; + +import com.tngtech.archunit.PublicAPI; + +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + +public interface MethodsShould extends CodeUnitsShould { + + /** + * Asserts that methods are static. + * + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION beStatic(); + + /** + * Asserts that methods are non-static. + * + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION notBeStatic(); + + /** + * Asserts that methods are final. + * + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION beFinal(); + + /** + * Asserts that methods are non-final. + * + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION notBeFinal(); +} diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldConjunction.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldConjunction.java new file mode 100644 index 0000000000..9865df6038 --- /dev/null +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldConjunction.java @@ -0,0 +1,41 @@ +/* + * 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.lang.syntax.elements; + +import com.tngtech.archunit.PublicAPI; +import com.tngtech.archunit.core.domain.JavaMethod; +import com.tngtech.archunit.lang.ArchCondition; + +import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; + +public interface MethodsShouldConjunction extends CodeUnitsShouldConjunction { + + @Override + @PublicAPI(usage = ACCESS) + MethodsShouldConjunction andShould(ArchCondition condition); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShould andShould(); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShouldConjunction orShould(ArchCondition condition); + + @Override + @PublicAPI(usage = ACCESS) + MethodsShould orShould(); +} diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldTest.java new file mode 100644 index 0000000000..d33b8f1eb0 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MethodsShouldTest.java @@ -0,0 +1,63 @@ +package com.tngtech.archunit.lang.syntax.elements; + +import com.google.common.collect.ImmutableSet; +import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.lang.EvaluationResult; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Collection; +import java.util.Set; + +import static com.tngtech.archunit.core.domain.TestUtils.importClasses; +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods; +import static com.tngtech.archunit.lang.syntax.elements.MembersShouldTest.parseMembers; +import static com.tngtech.java.junit.dataprovider.DataProviders.$; +import static com.tngtech.java.junit.dataprovider.DataProviders.$$; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(DataProviderRunner.class) +public class MethodsShouldTest { + + @DataProvider + public static Object[][] restricted_property_rule_ends() { + return $$( + $(methods().should().beFinal(), ImmutableSet.of(METHOD_C, METHOD_D)), + $(methods().should().notBeFinal(), ImmutableSet.of(METHOD_A, METHOD_B)), + $(methods().should().beStatic(), ImmutableSet.of(METHOD_A, METHOD_C)), + $(methods().should().notBeStatic(), ImmutableSet.of(METHOD_B, METHOD_D)), + $(methods().should().notBeFinal().andShould().notBeStatic(), ImmutableSet.of(METHOD_A, METHOD_B, METHOD_D)), + $(methods().should().notBeFinal().orShould().notBeStatic(), ImmutableSet.of(METHOD_B)) + ); + } + + @Test + @UseDataProvider("restricted_property_rule_ends") + public void property_predicates(ArchRule ruleStart, Collection expectedMembers) { + EvaluationResult result = ruleStart.evaluate(importClasses(ClassWithVariousMembers.class)); + + Set actualMethods = parseMembers(ClassWithVariousMembers.class, result.getFailureReport().getDetails()); + assertThat(actualMethods).containsOnlyElementsOf(expectedMembers); + } + + private static final String METHOD_A = "methodA([I)"; + private static final String METHOD_B = "methodB(boolean)"; + private static final String METHOD_C = "methodC(char)"; + private static final String METHOD_D = "methodD()"; + + @SuppressWarnings({"unused"}) + private static class ClassWithVariousMembers { + public final void methodA(int[] array) { + } + protected static final void methodB(boolean flag) { + } + private void methodC(char ch) { + } + static int methodD() { + return 0; + } + } +}