diff --git a/detekt.yml b/detekt.yml index e91611876..1101ae6f0 100644 --- a/detekt.yml +++ b/detekt.yml @@ -66,7 +66,7 @@ comments: endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' KDocReferencesNonPublicProperty: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] OutdatedDocumentation: active: false matchTypeParameters: true @@ -74,7 +74,7 @@ comments: allowParamOnConstructorProperties: false UndocumentedPublicClass: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] searchInNestedClass: true searchInInnerClass: true searchInInnerObject: true @@ -82,11 +82,11 @@ comments: searchInProtectedClass: false UndocumentedPublicFunction: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] searchProtectedFunction: false UndocumentedPublicProperty: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] searchProtectedProperty: false complexity: @@ -155,14 +155,14 @@ complexity: active: false StringLiteralDuplication: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] threshold: 3 ignoreAnnotation: true excludeStringsWithLessThan5Characters: true ignoreStringsRegex: '$^' TooManyFunctions: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**', '**/konsist/api/ext/sequence/**' ] + excludes: [ '**/test/**', '**/**Test/**', '**/konsist/api/ext/sequence/**' ] thresholdInFiles: 25 thresholdInClasses: 25 thresholdInInterfaces: 25 @@ -238,7 +238,7 @@ exceptions: - 'toString' InstanceOfCheckForException: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] NotImplementedDeclaration: active: false ObjectExtendsThrowable: @@ -264,7 +264,7 @@ exceptions: active: false ThrowingExceptionsWithoutMessageOrCause: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] exceptions: - 'ArrayIndexOutOfBoundsException' - 'Exception' @@ -279,7 +279,7 @@ exceptions: active: true TooGenericExceptionCaught: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] exceptionNames: - 'ArrayIndexOutOfBoundsException' - 'Error' @@ -325,7 +325,7 @@ naming: minimumFunctionNameLength: 3 FunctionNaming: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**', '**/apiTest/**', '**/snippet/**', '**/jvmTest/**' ] + excludes: [ '**/test/**', '**/**Test/**', '**/apiTest/**', '**/snippet/**', '**/jvmTest/**' ] functionPattern: '[a-z][a-zA-Z0-9]*' excludeClassPattern: '$^' ignoreAnnotated: [ 'Composable' ] @@ -385,10 +385,10 @@ performance: threshold: 3 ForEachOnRange: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] SpreadOperator: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] UnnecessaryPartOfBinaryExpression: active: false UnnecessaryTemporaryInstantiation: @@ -455,7 +455,7 @@ potential-bugs: active: true LateinitUsage: active: false - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] ignoreOnClassesPattern: '' MapGetWithNotNullAssertionOperator: active: true @@ -478,7 +478,7 @@ potential-bugs: active: true UnsafeCallOnNullableType: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] UnsafeCast: active: true UnusedUnaryOperator: @@ -551,7 +551,7 @@ style: maxJumpCount: 1 MagicNumber: active: true - excludes: [ '**/test/**', '**/integrationTest/**', '**/konsistTest/**', '**/*.kts' ] + excludes: [ '**/test/**', '**/**Test/**', '**/*.kts' ] ignoreNumbers: - '-1' - '0' diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/Architecture1Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/Architecture1Test.kt index b3fdfb5a4..0a501f32a 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/Architecture1Test.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/Architecture1Test.kt @@ -24,9 +24,9 @@ class Architecture1Test { "com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.presentation..", ) - // region passes when dependency is set that layers are independent + // region passes when layers are independent @Test - fun `passes when dependency is set that layers are independent (lambda scope)`() { + fun `passes when layers are independent (lambda scope)`() { // then scope .assertArchitecture { @@ -36,7 +36,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that layers are independent (lambda files)`() { + fun `passes when layers are independent (lambda files)`() { // then scope .files @@ -47,7 +47,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that layers are independent (parameter scope)`() { + fun `passes when layers are independent (parameter scope)`() { // given val layerDependencies = architecture { @@ -60,7 +60,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that layers are independent (parameter files)`() { + fun `passes when layers are independent (parameter files)`() { // given val layerDependencies = architecture { @@ -76,10 +76,10 @@ class Architecture1Test { // endregion - //region passes when dependency is set that Domain not depends on Presentation + //region passes when Domain not depends on Presentation @Test - fun `passes when dependency is set that Domain not depends on Presentation (lambda scope)`() { + fun `passes when domain not depends on presentation (lambda scope)`() { // then scope .assertArchitecture { @@ -89,7 +89,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that Domain not depends on Presentation (lambda files)`() { + fun `passes when Domain not depends on presentation (lambda files)`() { // then scope .files @@ -100,7 +100,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that Domain not depends on Presentation (parameter scope)`() { + fun `passes when domain not depends on presentation (parameter scope)`() { // given val layerDependencies = architecture { @@ -113,7 +113,7 @@ class Architecture1Test { } @Test - fun `passes when dependency is set that Domain not depends on Presentation (parameter files)`() { + fun `passes when domain not depends on presentation (parameter files)`() { // given val layerDependencies = architecture { @@ -126,6 +126,5 @@ class Architecture1Test { .files .assertArchitecture(layerDependencies) } - // endregion } diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture2/Architecture2Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture2/Architecture2Test.kt index 603051d7f..9e578a032 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture2/Architecture2Test.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture2/Architecture2Test.kt @@ -98,7 +98,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that domain layer depend on presentation domain layer (lambda scope)' test has failed. \n" + + "'fails when dependency is set that domain layer depend on presentation domain layer (lambda scope)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.", ) } @@ -119,7 +120,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that domain layer depend on presentation domain layer (lambda files)' test has failed. \n" + + "'fails when dependency is set that domain layer depend on presentation domain layer (lambda files)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.", ) } @@ -142,7 +144,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set to domain layer depends on presentation layer (parameter scope)' test has failed. \n" + + "'fails when dependency is set to domain layer depends on presentation layer (parameter scope)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.", ) } @@ -266,7 +269,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that domain layer is depend on presentation layer (parameter files)' test has failed. \n" + + "'fails when dependency is set that domain layer is depend on presentation layer (parameter files)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + @@ -296,7 +300,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that domain layer is depend on presentation layer (lambda scope)' test has failed. \n" + + "'fails when dependency is set that domain layer is depend on presentation layer (lambda scope)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + @@ -328,7 +333,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that domain layer is depend on presentation layer (lambda files)' test has failed. \n" + + "'fails when dependency is set that domain layer is depend on presentation layer (lambda files)' " + + "test has failed. \n" + "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + @@ -355,7 +361,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that presentation layer not depends on domain (lambda scope)' test has failed. \n" + + "'fails when dependency is set that presentation layer not depends on domain (lambda scope)' " + + "test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -381,7 +388,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that presentation layer not depends on domain (lambda files)' test has failed. \n" + + "'fails when dependency is set that presentation layer not depends on domain (lambda files)' " + + "test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -410,7 +418,8 @@ class Architecture2Test { result .message .shouldBeEqualTo( - "'fails when dependency is set that presentation layer not depends on domain (parameter scope)' test has failed. \n" + + "'fails when dependency is set that presentation layer not depends on domain (parameter scope)' " + + "test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -438,17 +447,204 @@ class Architecture2Test { } // then - result .message .shouldBeEqualTo( - "'fails when dependency is set that presentation layer not depends on domain (parameter files)' test has failed. \n" + + "'fails when dependency is set that presentation layer not depends on domain (parameter files)' " + + "test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + - " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project.domain.DomainFirstClass", + " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2." + + "project.domain.DomainFirstClass", ) } // endregion + + // region Layer dependency tests with include + @Test + fun `passes when dependency is set that domain layer depends on presentation layer and presentation layer include (lambda scope)`() { + // then + scope.assertArchitecture { + domain.doesNotDependOn(presentation) + presentation.include() + } + } + + @Test + fun `passes when dependency is set that domain layer depends on presentation layer and presentation layer include (lambda files)`() { + // then + scope.files.assertArchitecture { + domain.doesNotDependOn(presentation) + presentation.include() + } + } + + @Test + fun `passes when dependency is set that domain layer depends on presentation layer and presentation layer include (parameter scope)`() { + // given + val layerDependencies = + architecture { + domain.doesNotDependOn(presentation) + presentation.include() + } + + // then + scope.assertArchitecture(layerDependencies) + } + + @Test + fun `passes when dependency is set that domain layer depends on presentation layer and presentation layer include (parameter files)`() { + // given + val layerDependencies = + architecture { + domain.doesNotDependOn(presentation) + presentation.include() + } + + // then + scope.files.assertArchitecture(layerDependencies) + } + // endregion + + // region Layer dependency tests with dependsOnNothing + @Test + fun `fails when dependency is set that presentation layer depends on nothing and domain layer is included (lambda scope)`() { + // when + val result = + shouldThrow { + scope.assertArchitecture { + presentation.dependsOnNothing() + domain.include() + } + } + + // then + result.message.shouldBeEqualTo( + "'fails when dependency is set that presentation layer depends on nothing and domain layer is included (lambda scope)' " + + "test has failed. \n" + + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + + " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project.domain.DomainFirstClass", + ) + } + + @Test + fun `fails when dependency is set that presentation layer depends on nothing and domain layer is included (lambda files)`() { + // when + val result = + shouldThrow { + scope.files.assertArchitecture { + presentation.dependsOnNothing() + domain.include() + } + } + + // then + result.message.shouldBeEqualTo( + "'fails when dependency is set that presentation layer depends on nothing and domain layer is included (lambda files)' " + + "test has failed. \n" + + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + + " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project.domain.DomainFirstClass", + ) + } + + @Test + fun `fails when dependency is set that presentation layer depends on nothing and domain layer is included (parameter scope)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOnNothing() + domain.include() + } + + // when + val result = + shouldThrow { + scope.assertArchitecture(layerDependencies) + } + + // then + result.message.shouldBeEqualTo( + "'fails when dependency is set that presentation layer depends on nothing and domain layer is included (parameter scope)' " + + "test has failed. \n" + + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + + " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project.domain.DomainFirstClass", + ) + } + + @Test + fun `fails when dependency is set that presentation layer depends on nothing and domain layer is included (parameter files)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOnNothing() + domain.include() + } + + // when + val result = + shouldThrow { + scope.files.assertArchitecture(layerDependencies) + } + + // then + result.message.shouldBeEqualTo( + "'fails when dependency is set that presentation layer depends on nothing and domain layer is included (parameter files)' " + + "test has failed. \n" + + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + + "assertarchitecture/architecture2/project/presentation/sample/PresentationThirdClass.kt\n" + + " └── import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project.domain.DomainFirstClass", + ) + } + // endregion + + // region Layer dependency tests with dependsOnNothing + @Test + fun `passes when dependency is set that presentation layer depends on nothing and domain layer is not included (lambda scope)`() { + // then + scope.assertArchitecture { + presentation.dependsOnNothing() + } + } + + @Test + fun `passes when dependency is set that presentation layer depends on nothing and domain layer is not included (lambda files)`() { + // then + scope.files.assertArchitecture { + presentation.dependsOnNothing() + } + } + + @Test + fun `passes when dependency is set that presentation layer depends on nothing and domain layer is not included (parameter scope)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOnNothing() + } + + // then + scope.assertArchitecture(layerDependencies) + } + + @Test + fun `passes when dependency is set that presentation layer depends on nothing and domain layer is not included (parameter files)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOnNothing() + } + + // then + scope.files.assertArchitecture(layerDependencies) + } + // endregion } diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture4/Architecture4Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture4/Architecture4Test.kt index ebcaa4a9c..2e0c85f64 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture4/Architecture4Test.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture4/Architecture4Test.kt @@ -36,9 +36,9 @@ class Architecture4Test { "com.lemonappdev.konsist.architecture.assertarchitecture.architecture4.project.data..", ) - // region passes when dependency is set that presentation and data layers are depend on domain layer + // region passes when presentation and data layers are depend on domain layer @Test - fun `passes when dependency is set that presentation and data layers are depend on domain layer (lambda scope)`() { + fun `passes when presentation and data layers are depend on domain layer (lambda scope)`() { // then scope .assertArchitecture { @@ -49,7 +49,7 @@ class Architecture4Test { } @Test - fun `passes when dependency is set that presentation and data layers are depend on domain layer (lambda files)`() { + fun `passes when presentation and data layers are depend on domain layer (lambda files)`() { // then scope .files @@ -61,7 +61,7 @@ class Architecture4Test { } @Test - fun `passes when dependency is set that presentation and data layers are depend on domain layer (parameter scope)`() { + fun `passes when presentation and data layers are depend on domain layer (parameter scope)`() { // given val layerDependencies = architecture { @@ -75,7 +75,7 @@ class Architecture4Test { } @Test - fun `passes when dependency is set that presentation and data layers are depend on domain layer (parameter files)`() { + fun `passes when presentation and data layers are depend on domain layer (parameter files)`() { // given val layerDependencies = architecture { @@ -138,7 +138,7 @@ class Architecture4Test { // region fails when bad dependency is set @Test - fun `fails when bad dependency is set (lambda scope)`() { + fun `fails when (lambda scope)`() { // when val result = shouldThrow { @@ -154,7 +154,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set (lambda scope)' test has failed. \n" + + "'fails when (lambda scope)' test has failed. \n" + "Layer 'Presentation' does not depends on 'Data' layer.\n" + "Layer 'Domain' does not depends on 'Data' layer.\n" + "'Data' layer should not depend on anything but has dependencies in files:\n" + @@ -166,7 +166,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set (lambda files)`() { + fun `fails when (lambda files)`() { // when val result = shouldThrow { @@ -183,7 +183,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set (lambda files)' test has failed. \n" + + "'fails when (lambda files)' test has failed. \n" + "Layer 'Presentation' does not depends on 'Data' layer.\n" + "Layer 'Domain' does not depends on 'Data' layer.\n" + "'Data' layer should not depend on anything but has dependencies in files:\n" + @@ -195,7 +195,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set (parameter scope)`() { + fun `fails when (parameter scope)`() { // given val layerDependencies = architecture { @@ -214,7 +214,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set (parameter scope)' test has failed. \n" + + "'fails when (parameter scope)' test has failed. \n" + "Layer 'Presentation' does not depends on 'Data' layer.\n" + "Layer 'Domain' does not depends on 'Data' layer.\n" + "'Data' layer should not depend on anything but has dependencies in files:\n" + @@ -226,7 +226,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set (parameter files)`() { + fun `fails when (parameter files)`() { // given val layerDependencies = architecture { @@ -247,7 +247,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set (parameter files)' test has failed. \n" + + "'fails when (parameter files)' test has failed. \n" + "Layer 'Presentation' does not depends on 'Data' layer.\n" + "Layer 'Domain' does not depends on 'Data' layer.\n" + "'Data' layer should not depend on anything but has dependencies in files:\n" + @@ -260,9 +260,9 @@ class Architecture4Test { // endregion - // region fails when bad dependency is set using doesNotDependsOn + // region fails when using doesNotDependsOn @Test - fun `fails when bad dependency is set using doesNotDependsOn (lambda scope)`() { + fun `fails when using doesNotDependsOn (lambda scope)`() { // when val result = shouldThrow { @@ -275,7 +275,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set using doesNotDependsOn (lambda scope)' test has failed. \n" + + "'fails when using doesNotDependsOn (lambda scope)' test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture4/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -285,7 +285,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set using doesNotDependsOn (lambda files)`() { + fun `fails when using doesNotDependsOn (lambda files)`() { // when val result = shouldThrow { @@ -300,7 +300,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set using doesNotDependsOn (lambda files)' test has failed. \n" + + "'fails when using doesNotDependsOn (lambda files)' test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture4/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -310,7 +310,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set using doesNotDependsOn (parameter scope)`() { + fun `fails when using doesNotDependsOn (parameter scope)`() { // given val layerDependencies = architecture { @@ -328,7 +328,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set using doesNotDependsOn (parameter scope)' test has failed. \n" + + "'fails when using doesNotDependsOn (parameter scope)' test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture4/project/presentation/sample/PresentationThirdClass.kt\n" + @@ -338,7 +338,7 @@ class Architecture4Test { } @Test - fun `fails when bad dependency is set using doesNotDependsOn (parameter files)`() { + fun `fails when using doesNotDependsOn (parameter files)`() { // given val layerDependencies = architecture { @@ -357,7 +357,7 @@ class Architecture4Test { result .message .shouldBeEqualTo( - "'fails when bad dependency is set using doesNotDependsOn (parameter files)' test has failed. \n" + + "'fails when using doesNotDependsOn (parameter files)' test has failed. \n" + "'Presentation' layer does not depends on 'Domain' layer failed. Files that depend on 'Domain' layer:\n" + "└── file $rootPath/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/" + "assertarchitecture/architecture4/project/presentation/sample/PresentationThirdClass.kt\n" + diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture5/Architecture5Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture5/Architecture5Test.kt index b825406f6..04c64d458 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture5/Architecture5Test.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture5/Architecture5Test.kt @@ -38,9 +38,9 @@ class Architecture5Test { "com.lemonappdev.konsist.architecture.assertarchitecture.architecture5.project.infrastructure..", ) - // region passes when good dependency is set + // region passes when @Test - fun `passes when good dependency is set (lambda scope)`() { + fun `passes when (lambda scope)`() { // then scope .assertArchitecture { @@ -52,7 +52,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set (lambda files)`() { + fun `passes when (lambda files)`() { // then scope .files @@ -65,7 +65,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set (parameter scope)`() { + fun `passes when (parameter scope)`() { // given val layerDependencies = architecture { @@ -81,7 +81,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set (parameter files)`() { + fun `passes when (parameter files)`() { // given val layerDependencies = architecture { @@ -99,9 +99,9 @@ class Architecture5Test { // endregion - // region passes when good dependency is set using doesNotDependsOn + // region passes when using doesNotDependsOn @Test - fun `passes when good dependency is set using doesNotDependsOn (lambda scope)`() { + fun `passes when using doesNotDependsOn (lambda scope)`() { // then scope.assertArchitecture { presentation.doesNotDependOn(domain, infrastructure) @@ -109,7 +109,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (lambda files)`() { + fun `passes when using doesNotDependsOn (lambda files)`() { // then scope .files @@ -119,7 +119,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (parameter scope)`() { + fun `passes when using doesNotDependsOn (parameter scope)`() { // given val layerDependencies = architecture { @@ -131,7 +131,7 @@ class Architecture5Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (parameter files)`() { + fun `passes when using doesNotDependsOn (parameter files)`() { // given val layerDependencies = architecture { @@ -148,7 +148,7 @@ class Architecture5Test { // region fails when bad dependency is set @Test - fun `fails when bad dependency is set (lambda scope)`() { + fun `fails when (lambda scope)`() { // given val sut = { scope @@ -165,7 +165,7 @@ class Architecture5Test { } @Test - fun `fails when bad dependency is set (lambda files)`() { + fun `fails when (lambda files)`() { // given val sut = { scope @@ -183,7 +183,7 @@ class Architecture5Test { } @Test - fun `fails when bad dependency is set (parameter scope)`() { + fun `fails when (parameter scope)`() { // given val architecture = architecture { @@ -202,7 +202,7 @@ class Architecture5Test { } @Test - fun `fails when bad dependency is set (parameter files)`() { + fun `fails when (parameter files)`() { // given val architecture = architecture { diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture7/Architecture7Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture7/Architecture7Test.kt index d24510f09..9dacc4e4e 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture7/Architecture7Test.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture7/Architecture7Test.kt @@ -38,9 +38,9 @@ class Architecture7Test { "com.lemonappdev.konsist.architecture.assertarchitecture.architecture7.project.port..", ) - // region passes when good dependency is set + // region passes when @Test - fun `passes when good dependency is set (lambda scope)`() { + fun `passes when (lambda scope)`() { // then scope .assertArchitecture { @@ -53,7 +53,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set (lambda files)`() { + fun `passes when (lambda files)`() { // then scope .files @@ -67,7 +67,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set (parameter scope)`() { + fun `passes when (parameter scope)`() { // then val layerDependencies = architecture { @@ -82,7 +82,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set (parameter files)`() { + fun `passes when (parameter files)`() { // then val layerDependencies = architecture { @@ -101,7 +101,7 @@ class Architecture7Test { // region fails when bad dependency is set @Test - fun `passes when good dependency is set using doesNotDependsOn (lambda scope)`() { + fun `passes when using doesNotDependsOn (lambda scope)`() { // then scope .assertArchitecture { @@ -110,7 +110,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (lambda files)`() { + fun `passes when using doesNotDependsOn (lambda files)`() { // then scope .files @@ -120,7 +120,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (parameter scope)`() { + fun `passes when using doesNotDependsOn (parameter scope)`() { // then val layerDependencies = architecture { @@ -131,7 +131,7 @@ class Architecture7Test { } @Test - fun `passes when good dependency is set using doesNotDependsOn (parameter files)`() { + fun `passes when using doesNotDependsOn (parameter files)`() { // then val layerDependencies = architecture { diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/LayerDependencies.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/LayerDependencies.kt index b1de4fa4d..41fe29131 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/LayerDependencies.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/LayerDependencies.kt @@ -50,6 +50,17 @@ interface LayerDependencies { * Specifies that the current layer does not depend on any other layer. * * @receiver The [Layer] that does not depend on any other layer. + * + * @see include */ fun Layer.dependsOnNothing(): Unit + + /** + * This function is used to include a Layer in the architecture without specifying any dependencies. + * It can be used in combination with dependsOnNothing() to specify that a layer does not depend on any other layer. + * + * @receiver LayerDependenciesCore The core dependencies container + * @return The LayerDependenciesCore instance for chaining + */ + fun Layer.include(): Unit } diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCore.kt index 6a2cfa8b2..389702a50 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCore.kt @@ -151,6 +151,11 @@ internal class LayerDependenciesCore( layerValidatorManager.validateLayerDependencies(layerDependencies) } + override fun Layer.include() { + layers.add(this) + layerDependencies.add(LayerDependency(this, LayerDependencyType.NONE, null)) + } + private fun getLayerWithDependOnNothingDependency(layer: Layer): LayerDependency? { val dependOnLayerDependency = layerDependencies.firstOrNull { diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependencyType.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependencyType.kt index 1a1e95167..594e40a91 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependencyType.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependencyType.kt @@ -4,4 +4,5 @@ internal enum class LayerDependencyType { DEPEND_ON_LAYER, DEPEND_ON_NOTHING, DOES_NOT_DEPEND_ON_LAYER, + NONE, } diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoArchitectureAssert.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoArchitectureAssert.kt index 4264e990c..5f1cc2848 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoArchitectureAssert.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoArchitectureAssert.kt @@ -265,7 +265,7 @@ private fun getFailedDependsOnNothing( layerDependencies .dependsOnNothingDependencies .forEach { layer -> - val dependentFiles = layer.getDependentOnAnythingFiles(files) + val dependentFiles = layer.getDependentOnAnyLayerFiles(files, layerDependencies) if (dependentFiles.isNotEmpty()) { failedLayerDependencies += @@ -316,7 +316,10 @@ private fun Layer.getDependentOnFiles( return dependOnFiles } -private fun Layer.getDependentOnAnythingFiles(files: List): List { +private fun Layer.getDependentOnAnyLayerFiles( + files: List, + layerDependencies: LayerDependenciesCore, +): List { val layerFiles = files.withPackage(rootPackage) return layerFiles @@ -324,7 +327,14 @@ private fun Layer.getDependentOnAnythingFiles(files: List): L val imports = koFile .imports + // Import is not part of layer .filterNot { LocationUtil.resideInLocation(rootPackage, it.name) } + // Import is part of other layer + .filter { + layerDependencies.layers.any { layer -> + LocationUtil.resideInLocation(layer.rootPackage, it.name) + } + } if (imports.isNotEmpty()) { koFile diff --git a/lib/src/test/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCoreTest.kt b/lib/src/test/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCoreTest.kt index 586a7635a..48ef09d74 100644 --- a/lib/src/test/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCoreTest.kt +++ b/lib/src/test/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependenciesCoreTest.kt @@ -9,6 +9,7 @@ import io.mockk.mockk import io.mockk.verify import org.amshove.kluent.shouldBeEmpty import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldContain import org.amshove.kluent.shouldContainAll import org.amshove.kluent.shouldThrow import org.amshove.kluent.withMessage @@ -763,4 +764,58 @@ class LayerDependenciesCoreTest { verify { layerValidatorManager.validateLayerDependencies(sut.layerDependencies) } } //endregion + + // region include + @Test + fun `include adds layer to layers collection`() { + // given + val sut = LayerDependenciesCore() + val layer = Layer("Domain", "com.example.domain..") + + // when + with(sut) { + layer.include() + } + + // then + sut.layers shouldContain layer + } + + @Test + fun `include creates dependency with NONE type and null target`() { + // given + val sut = LayerDependenciesCore() + val layer = Layer("Domain", "com.example.domain..") + val expectedDependency = LayerDependency(layer, LayerDependencyType.NONE, null) + + // when + with(sut) { + layer.include() + } + + // then + sut.layerDependencies shouldContain expectedDependency + sut.layerDependencies.first() shouldBeEqualTo expectedDependency + } + + @Test + fun `include can be called multiple times for different layers`() { + // given + val sut = LayerDependenciesCore() + val layer1 = Layer("Domain", "com.example.domain..") + val layer2 = Layer("Presentation", "com.example.presentation..") + + // when + with(sut) { + layer1.include() + layer2.include() + } + + // then + sut.layers shouldContain layer1 + sut.layers shouldContain layer2 + sut.layerDependencies shouldContain LayerDependency(layer1, LayerDependencyType.NONE, null) + sut.layerDependencies shouldContain LayerDependency(layer2, LayerDependencyType.NONE, null) + } + // endregion }