diff --git a/README.md b/README.md index 53dda647be..8fc1cf74f6 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ tests ([JUnit](https://junit.org/) / [Kotest](https://kotest.io/)). Gradle Kotlin: ```kotlin -testImplementation("com.lemonappdev:konsist:0.17.0") +testImplementation("com.lemonappdev:konsist:0.17.1") ``` Gradle Groovy: ```groovy -testImplementation "com.lemonappdev:konsist:0.17.0" +testImplementation "com.lemonappdev:konsist:0.17.1" ``` Maven: @@ -36,7 +36,7 @@ Maven: com.lemonappdev konsist -0.17.0 +0.17.1 test ``` diff --git a/detekt.yml b/detekt.yml index 1101ae6f0e..5d8f48c633 100644 --- a/detekt.yml +++ b/detekt.yml @@ -122,6 +122,7 @@ complexity: LargeClass: active: true threshold: 800 + excludes: [ '**/test/**', '**/**Test/**' ] LongMethod: active: true threshold: 60 @@ -162,7 +163,7 @@ complexity: ignoreStringsRegex: '$^' TooManyFunctions: active: true - excludes: [ '**/test/**', '**/**Test/**', '**/konsist/api/ext/sequence/**' ] + excludes: [ '**/test/**', '**/**Test/**' ] thresholdInFiles: 25 thresholdInClasses: 25 thresholdInInterfaces: 25 diff --git a/gradle.properties b/gradle.properties index e2b012b92d..d750bdef5b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xms512M -Xmx4g -Dkotlin.daemon.jvm.options="-Xmx1g" org.gradle.parallel=true org.gradle.daemon=true -konsist.version=0.17.0 +konsist.version=0.17.1 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 a350ff8f19..8f267eed8a 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 @@ -8,6 +8,7 @@ import com.lemonappdev.konsist.core.exception.KoAssertionFailedException import com.lemonappdev.konsist.core.filesystem.PathProvider import io.kotest.assertions.throwables.shouldThrow import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldNotThrow import org.junit.jupiter.api.Test class Architecture2Test { @@ -84,50 +85,36 @@ class Architecture2Test { // fails when dependency is set that domain layer depend on presentation domain layer @Test - fun `fails when dependency is set that domain layer depend on presentation domain layer (lambda scope)`() { + fun `passes when dependency is set that domain layer depend on presentation domain layer (lambda scope)`() { // when - val result = - shouldThrow { - scope - .assertArchitecture { - domain.dependsOn(presentation) - } - } + val func = { + scope + .assertArchitecture { + domain.dependsOn(presentation) + } + } // then - result - .message - .shouldBeEqualTo( - "'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.", - ) + func shouldNotThrow KoAssertionFailedException::class } @Test - fun `fails when dependency is set that domain layer depend on presentation domain layer (lambda files)`() { + fun `passes when dependency is set that domain layer depend on presentation domain layer (lambda files)`() { // when - val result = - shouldThrow { - scope - .files - .assertArchitecture { - domain.dependsOn(presentation) - } - } + val func = { + scope + .files + .assertArchitecture { + domain.dependsOn(presentation) + } + } // then - result - .message - .shouldBeEqualTo( - "'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.", - ) + func shouldNotThrow KoAssertionFailedException::class } @Test - fun `fails when dependency is set to domain layer depends on presentation layer (parameter scope)`() { + fun `passes when dependency is set to domain layer depends on presentation layer (parameter scope)`() { // given val layerDependencies = architecture { @@ -135,23 +122,16 @@ class Architecture2Test { } // when - val result = - shouldThrow { - scope.assertArchitecture(layerDependencies) - } + val func = { + scope.assertArchitecture(layerDependencies) + } // then - result - .message - .shouldBeEqualTo( - "'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.", - ) + func shouldNotThrow KoAssertionFailedException::class } @Test - fun `fails when dependency is set to domain layer depends on presentation layer (parameter files)`() { + fun `passes when dependency is set to domain layer depends on presentation layer (parameter files)`() { // given val layerDependencies = architecture { @@ -159,20 +139,14 @@ class Architecture2Test { } // when - val result = - shouldThrow { - scope - .files - .assertArchitecture(layerDependencies) - } + val func = { + scope + .files + .assertArchitecture(layerDependencies) + } // then - result - .message - .shouldBeEqualTo( - "'fails when dependency is set to domain layer depends on presentation layer (parameter files)' test has failed. \n" + - "Layer 'Domain' does not depends on 'Presentation' layer.", - ) + func shouldNotThrow KoAssertionFailedException::class } // endregion @@ -247,7 +221,6 @@ class Architecture2Test { .message .shouldBeEqualTo( "'fails when dependency is set that domain layer is depend on presentation layer (parameter 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2." + @@ -278,7 +251,6 @@ class Architecture2Test { .shouldBeEqualTo( "'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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2." + @@ -312,7 +284,6 @@ class Architecture2Test { .shouldBeEqualTo( "'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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2." + @@ -348,7 +319,6 @@ class Architecture2Test { .shouldBeEqualTo( "'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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture2.project." + 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 c63381e412..9a0ccc30ac 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 @@ -159,8 +159,6 @@ class Architecture4Test { .message .shouldBeEqualTo( "'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" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture4." + @@ -191,8 +189,6 @@ class Architecture4Test { .message .shouldBeEqualTo( "'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" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture4." + @@ -225,8 +221,6 @@ class Architecture4Test { .message .shouldBeEqualTo( "'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" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture4." + @@ -261,8 +255,6 @@ class Architecture4Test { .message .shouldBeEqualTo( "'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" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.assertarchitecture.architecture4." + 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 04c64d4584..6f9c91d520 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 @@ -5,6 +5,7 @@ import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.architectu import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.assertArchitecture import com.lemonappdev.konsist.api.architecture.Layer import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import org.amshove.kluent.shouldNotThrow import org.amshove.kluent.shouldThrow import org.junit.jupiter.api.Test @@ -161,7 +162,7 @@ class Architecture5Test { } // then - sut shouldThrow KoAssertionFailedException::class + sut shouldNotThrow KoAssertionFailedException::class } @Test @@ -179,7 +180,7 @@ class Architecture5Test { } // then - sut shouldThrow KoAssertionFailedException::class + sut shouldNotThrow KoAssertionFailedException::class } @Test @@ -198,7 +199,7 @@ class Architecture5Test { } // then - sut shouldThrow KoAssertionFailedException::class + sut shouldNotThrow KoAssertionFailedException::class } @Test @@ -219,7 +220,7 @@ class Architecture5Test { } // then - sut shouldThrow KoAssertionFailedException::class + sut shouldNotThrow KoAssertionFailedException::class } // endregion diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/Architecture8Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/Architecture8Test.kt new file mode 100644 index 0000000000..38801a5ed3 --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/Architecture8Test.kt @@ -0,0 +1,167 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture8 + +import com.lemonappdev.konsist.api.Konsist +import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.architecture +import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.assertArchitecture +import com.lemonappdev.konsist.api.architecture.Layer +import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import io.kotest.assertions.throwables.shouldThrow +import org.amshove.kluent.shouldBeEqualTo +import org.junit.jupiter.api.Test + +class Architecture8Test { + private val scope = + Konsist.scopeFromDirectory( + "lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/project", + ) + + private val domain = + Layer( + "Domain", + "com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.domain..", + ) + + private val presentation = + Layer( + "Presentation", + "com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.presentation..", + ) + + // region passes when domain depends on presentation (strict = false) + @Test + fun `passes when domain depends on presentation and strict is false (lambda scope)`() { + // then + scope + .assertArchitecture { + domain.dependsOn(presentation, strict = false) + } + } + + @Test + fun `passes when domain depends on presentation and strict is false (lambda files)`() { + // then + scope + .files + .assertArchitecture { + domain.dependsOn(presentation, strict = false) + } + } + + @Test + fun `passes when domain depends on presentation and strict is false (parameter scope)`() { + // given + val layerDependencies = + architecture { + domain.dependsOn(presentation, strict = false) + } + + // then + scope.assertArchitecture(layerDependencies) + } + + @Test + fun `passes when domain depends on presentation and strict is false (parameter files)`() { + // given + val layerDependencies = + architecture { + domain.dependsOn(presentation, strict = false) + } + + // then + scope + .files + .assertArchitecture(layerDependencies) + } + // endregion + + // region fails when domain depends on presentation (strict = true) + @Test + fun `fails when domain depends on presentation and strict is true (lambda scope)`() { + // when + val result = + shouldThrow { + scope + .assertArchitecture { + domain.dependsOn(presentation, strict = true) + } + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when domain depends on presentation and strict is true (lambda scope)' test has failed. \n" + + "Layer 'Domain' does not depends on 'Presentation' layer.", + ) + } + + @Test + fun `fails when domain depends on presentation and strict is true (lambda files)`() { + // when + val result = + shouldThrow { + scope + .files + .assertArchitecture { + domain.dependsOn(presentation, strict = true) + } + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when domain depends on presentation and strict is true (lambda files)' test has failed. \n" + + "Layer 'Domain' does not depends on 'Presentation' layer.", + ) + } + + @Test + fun `fails when domain depends on presentation and strict is true (parameter scope)`() { + // given + val layerDependencies = + architecture { + domain.dependsOn(presentation, strict = true) + } + + // when + val result = + shouldThrow { + scope.assertArchitecture(layerDependencies) + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when domain depends on presentation and strict is true (parameter scope)' test has failed. \n" + + "Layer 'Domain' does not depends on 'Presentation' layer.", + ) + } + + @Test + fun `fails when domain depends on presentation and strict is true (parameter files)`() { + // given + val layerDependencies = + architecture { + domain.dependsOn(presentation, strict = true) + } + + // when + val result = + shouldThrow { + scope + .files + .assertArchitecture(layerDependencies) + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when domain depends on presentation and strict is true (parameter files)' test has failed. \n" + + "Layer 'Domain' does not depends on 'Presentation' layer.", + ) + } + // endregion +} diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/README.md b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/README.md new file mode 100644 index 0000000000..885928f379 --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/README.md @@ -0,0 +1,11 @@ +# Architecture 8 + +Test `strict` parameter for `dependsOn` methods. + +Test scenario where `Presentation` layer depends on empty `Domain` one: + +```mermaid +%%{init: {'theme': 'forest'}}%% +flowchart LR + Presentation[Presentation empty] --> Domain +``` diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/DomainFirstClass.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/DomainFirstClass.kt new file mode 100644 index 0000000000..007c28150d --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/DomainFirstClass.kt @@ -0,0 +1,3 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture8.project.domain + +class DomainFirstClass diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/sample/DomainSecondClass.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/sample/DomainSecondClass.kt new file mode 100644 index 0000000000..99810e19e1 --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture8/project/domain/sample/DomainSecondClass.kt @@ -0,0 +1,7 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture8.project.domain.sample + +import com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.domain.DomainFirstClass + +class DomainSecondClass( + val sampleParameter: DomainFirstClass, +) diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/Architecture9Test.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/Architecture9Test.kt new file mode 100644 index 0000000000..44b2da03c0 --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/Architecture9Test.kt @@ -0,0 +1,169 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture9 + +import com.lemonappdev.konsist.api.Konsist +import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.architecture +import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.assertArchitecture +import com.lemonappdev.konsist.api.architecture.Layer +import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import io.kotest.assertions.throwables.shouldThrow +import org.amshove.kluent.shouldBeEqualTo +import org.junit.jupiter.api.Test + +class Architecture9Test { + private val scope = + Konsist.scopeFromDirectory( + "lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture1/project", + ) + + private val domain = + Layer( + "Domain", + "com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.domain..", + ) + + private val presentation = + Layer( + "Presentation", + "com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.presentation..", + ) + + // region passes when presentation depends on domain (strict = false) + @Test + fun `passes when presentation depends on domain and strict is false (lambda scope)`() { + // then + scope + .assertArchitecture { + presentation.dependsOn(domain, strict = false) + } + } + + @Test + fun `passes when presentation depends on domain and strict is false (lambda files)`() { + // then + scope + .files + .assertArchitecture { + presentation.dependsOn(domain, strict = false) + } + } + + @Test + fun `passes when presentation depends on domain and strict is false (parameter scope)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOn(domain, strict = false) + } + + // then + scope.assertArchitecture(layerDependencies) + } + + @Test + fun `passes when presentation depends on domain and strict is false (parameter files)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOn(domain, strict = false) + } + + // then + scope + .files + .assertArchitecture(layerDependencies) + } + + // endregion + + // region fails when presentation depends on domain (strict = true) + @Test + fun `fails when presentation depends on domain and strict is true (lambda scope)`() { + // when + val result = + shouldThrow { + scope + .assertArchitecture { + presentation.dependsOn(domain, strict = true) + } + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when presentation depends on domain and strict is true (lambda scope)' test has failed. \n" + + "Layer 'Presentation' does not depends on 'Domain' layer.", + ) + } + + @Test + fun `fails when presentation depends on domain and strict is true (lambda files)`() { + // when + val result = + shouldThrow { + scope + .files + .assertArchitecture { + presentation.dependsOn(domain, strict = true) + } + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when presentation depends on domain and strict is true (lambda files)' test has failed. \n" + + "Layer 'Presentation' does not depends on 'Domain' layer.", + ) + } + + @Test + fun `fails when presentation depends on domain and strict is true (parameter scope)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOn(domain, strict = true) + } + + // when + val result = + shouldThrow { + scope.assertArchitecture(layerDependencies) + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when presentation depends on domain and strict is true (parameter scope)' test has failed. \n" + + "Layer 'Presentation' does not depends on 'Domain' layer.", + ) + } + + @Test + fun `fails when presentation depends on domain and strict is true (parameter files)`() { + // given + val layerDependencies = + architecture { + presentation.dependsOn(domain, strict = true) + } + + // when + val result = + shouldThrow { + scope + .files + .assertArchitecture(layerDependencies) + } + + // then + result + .message + .shouldBeEqualTo( + "'fails when presentation depends on domain and strict is true (parameter files)' test has failed. \n" + + "Layer 'Presentation' does not depends on 'Domain' layer.", + ) + } + + // endregion +} diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/README.md b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/README.md new file mode 100644 index 0000000000..68cb3b1d6d --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/README.md @@ -0,0 +1,11 @@ +# Architecture 9 + +Test `strict` parameter for `dependsOn` methods. + +Test scenario where `Presentation` layer depends on empty `Domain` one: + +```mermaid +%%{init: {'theme': 'forest'}}%% +flowchart LR + Presentation --> Domain[Domain empty] +``` diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/PresentationFirstClass.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/PresentationFirstClass.kt new file mode 100644 index 0000000000..d7094a314a --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/PresentationFirstClass.kt @@ -0,0 +1,3 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture9.project.presentation + +class PresentationFirstClass diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/sample/PresentationSecondClass.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/sample/PresentationSecondClass.kt new file mode 100644 index 0000000000..4ccff3f001 --- /dev/null +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/assertarchitecture/architecture9/project/presentation/sample/PresentationSecondClass.kt @@ -0,0 +1,7 @@ +package com.lemonappdev.konsist.architecture.assertarchitecture.architecture9.project.presentation.sample + +import com.lemonappdev.konsist.architecture.assertarchitecture.architecture1.project.presentation.PresentationFirstClass + +class PresentationSecondClass( + val sampleParameter: PresentationFirstClass, +) diff --git a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/optionalparameters/OptionalParametersTest.kt b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/optionalparameters/OptionalParametersTest.kt index 652bf0b0cd..a39c9fb763 100644 --- a/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/optionalparameters/OptionalParametersTest.kt +++ b/lib/src/apiTest/kotlin/com/lemonappdev/konsist/architecture/optionalparameters/OptionalParametersTest.kt @@ -50,7 +50,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'error message when additionalMessage and testName parameters are not provided (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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -79,7 +78,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'error message when additionalMessage is provided and testName is not provided (scope)' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -107,7 +105,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -139,7 +136,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -169,7 +165,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'error message when additionalMessage and testName parameters are not provided (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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -200,7 +195,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'error message when additionalMessage is provided and testName is not provided (files)' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -230,7 +224,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -264,7 +257,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -297,7 +289,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'error message when additionalMessage and testName parameters are not provided and architecture is passed " + "as parameter (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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -334,7 +325,6 @@ class OptionalParametersTest { "'error message when additionalMessage is provided, testName is not provided and architecture is passed as " + "parameter (scope)' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -366,7 +356,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -403,7 +392,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -438,7 +426,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'error message when additionalMessage and testName parameters are not provided and architecture is passed " + "as 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -477,7 +464,6 @@ class OptionalParametersTest { "'error message when additionalMessage is provided, testName is not provided and architecture is passed " + "as parameter (files)' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -511,7 +497,6 @@ class OptionalParametersTest { .message .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' 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 $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + @@ -550,7 +535,6 @@ class OptionalParametersTest { .shouldBeEqualTo( "'SOME CUSTOM TEST NAME' test has failed. \n" + "SOME ADDITIONAL MESSAGE\n" + - "Layer 'Domain' does not depends on 'Presentation' layer.\n" + "'Presentation' layer should not depend on anything but has dependencies in files:\n" + "└── File $filepath\n" + " └── Import com.lemonappdev.konsist.architecture.optionalparameters.project.domain." + diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/KoParametersProviderExtTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/KoParametersProviderExtTest.kt index 71381dfd32..c39dc822a4 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/KoParametersProviderExtTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/KoParametersProviderExtTest.kt @@ -194,5 +194,17 @@ class KoParametersProviderExtTest { sut.hasValidKDocParamTags() shouldBeEqualTo true } + @Test + fun `declaration-with-non-tag-with-@-in-description-has-valid-kdoc`() { + // given + val sut = + getSnippetFile("declaration-with-non-tag-with-@-in-description-has-valid-kdoc") + .declarationsOf() + .first() + + // then + sut.hasValidKDocParamTags() shouldBeEqualTo true + } + private fun getSnippetFile(fileName: String) = TestSnippetProvider.getSnippetKoScope("api/ext/provider/koparameters/snippet/", fileName) } diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/snippet/declaration-with-non-tag-with-@-in-description-has-valid-kdoc.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/snippet/declaration-with-non-tag-with-@-in-description-has-valid-kdoc.kttest new file mode 100644 index 0000000000..24cb3f9d2c --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/api/ext/provider/koparameters/snippet/declaration-with-non-tag-with-@-in-description-has-valid-kdoc.kttest @@ -0,0 +1,6 @@ +/** + * Sample description(@value wrong value) + * + * @param sampleParameter + */ +fun sampleFunction(sampleParameter: Int) {} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/KoParentDeclarationForKoSourceDeclarationProviderTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/KoParentDeclarationForKoSourceDeclarationProviderTest.kt index f3f5806f39..18f380051f 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/KoParentDeclarationForKoSourceDeclarationProviderTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/KoParentDeclarationForKoSourceDeclarationProviderTest.kt @@ -302,6 +302,20 @@ class KoParentDeclarationForKoSourceDeclarationProviderTest { null, null, ), + arguments( + "class-with-parent-interface-with-the-same-name", + KoInterfaceDeclaration::class, + KoClassDeclaration::class, + null, + "com.samplepackage.SampleInterface.SampleName", + ), + arguments( + "class-with-parent-class-with-the-same-name", + KoClassDeclaration::class, + KoInterfaceDeclaration::class, + null, + "com.samplepackage.SampleInterface.SampleName", + ), ) @Suppress("unused", "detekt.LongMethod") @@ -364,6 +378,13 @@ class KoParentDeclarationForKoSourceDeclarationProviderTest { null, null, ), + arguments( + "interface-with-parent-interface-with-the-same-name", + KoInterfaceDeclaration::class, + KoClassDeclaration::class, + null, + "com.samplepackage.SampleInterface.SampleName", + ), ) @Suppress("unused", "detekt.LongMethod") @@ -510,6 +531,20 @@ class KoParentDeclarationForKoSourceDeclarationProviderTest { null, null, ), + arguments( + "object-with-parent-interface-with-the-same-name", + KoInterfaceDeclaration::class, + KoClassDeclaration::class, + null, + "com.samplepackage.SampleInterface.SampleName", + ), + arguments( + "object-with-parent-class-with-the-same-name", + KoClassDeclaration::class, + KoInterfaceDeclaration::class, + null, + "com.samplepackage.SampleInterface.SampleName", + ), ) } } diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-class-with-the-same-name.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-class-with-the-same-name.kttest new file mode 100644 index 0000000000..1ceef7ce92 --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-class-with-the-same-name.kttest @@ -0,0 +1,7 @@ +package com.samplepackage + +data class SampleName(val data: String) : SampleInterface.SampleName() + +interface SampleInterface { + open class SampleName +} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-interface-with-the-same-name.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-interface-with-the-same-name.kttest new file mode 100644 index 0000000000..8e333c8b55 --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/class-with-parent-interface-with-the-same-name.kttest @@ -0,0 +1,7 @@ +package com.samplepackage + +data class SampleName(val data: String) : SampleInterface.SampleName + +interface SampleInterface { + interface SampleName +} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/interface-with-parent-interface-with-the-same-name.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/interface-with-parent-interface-with-the-same-name.kttest new file mode 100644 index 0000000000..a40ce0d8d5 --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/interface-with-parent-interface-with-the-same-name.kttest @@ -0,0 +1,7 @@ +package com.samplepackage + +interface SampleName : SampleInterface.SampleName + +interface SampleInterface { + interface SampleName +} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-class-with-the-same-name.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-class-with-the-same-name.kttest new file mode 100644 index 0000000000..2667935b6f --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-class-with-the-same-name.kttest @@ -0,0 +1,7 @@ +package com.samplepackage + +object SampleName : SampleInterface.SampleName() + +interface SampleInterface { + open class SampleName +} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-interface-with-the-same-name.kttest b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-interface-with-the-same-name.kttest new file mode 100644 index 0000000000..65ee2139a6 --- /dev/null +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/declaration/koparent/snippet/forkosourcedeclarationprovider/object-with-parent-interface-with-the-same-name.kttest @@ -0,0 +1,7 @@ +package com.samplepackage + +object SampleName : SampleInterface.SampleName + +interface SampleInterface { + interface SampleName +} diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationListTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationListTest.kt index 3932c435c5..a6e6254795 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationListTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationListTest.kt @@ -1,15 +1,17 @@ package com.lemonappdev.konsist.core.verify.kodeclarationassert.assertempty import com.lemonappdev.konsist.TestSnippetProvider -import com.lemonappdev.konsist.api.ext.list.classes import com.lemonappdev.konsist.api.verify.assertEmpty import com.lemonappdev.konsist.api.verify.assertNotEmpty import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import com.lemonappdev.konsist.core.filesystem.PathProvider import org.amshove.kluent.shouldContain import org.amshove.kluent.shouldThrow import org.junit.jupiter.api.Test class AssertEmptyOnDeclarationListTest { + private val rootPath = PathProvider.rootProjectPath + @Test fun `declaration-assert-test-method-name-derived-from-junit-method-name`() { // given @@ -95,9 +97,15 @@ class AssertEmptyOnDeclarationListTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-on-list-containing-non-null-values.kt" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-on-list-containing-non-null-values' failed. " + - "Declaration list is not empty. It contains values:\nSampleClass1,\nSampleClass2.", + "Declaration list is not empty. It contains values:\n" + + "├── Class SampleClass1 $filepath:1:1\n" + + "└── Class SampleClass2 $filepath:3:1", ) ?: throw e } @@ -115,9 +123,14 @@ class AssertEmptyOnDeclarationListTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-on-list-containing-null-and-non-null-values.kt:1:24" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-on-list-containing-null-and-non-null-values' failed. " + - "Declaration list is not empty. It contains 1 null value and values:\nInt.", + "Declaration list is not empty. It contains 1 null value and values:\n" + + "└── Type Int $filepath", ) ?: throw e } @@ -135,9 +148,14 @@ class AssertEmptyOnDeclarationListTest { try { sut.assertEmpty(additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-with-custom-message.kt:1:1" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-with-custom-message' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } @@ -155,9 +173,14 @@ class AssertEmptyOnDeclarationListTest { try { sut.assertEmpty(strict = true, additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-with-custom-message-and-strict-set-to-true.kt:1:1" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-with-custom-message-and-strict-set-to-true' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationSequenceTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationSequenceTest.kt index 8e8aa30384..8ff3990a24 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationSequenceTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/assertempty/AssertEmptyOnDeclarationSequenceTest.kt @@ -1,15 +1,17 @@ package com.lemonappdev.konsist.core.verify.kodeclarationassert.assertempty import com.lemonappdev.konsist.TestSnippetProvider -import com.lemonappdev.konsist.api.ext.list.classes import com.lemonappdev.konsist.api.verify.assertEmpty import com.lemonappdev.konsist.api.verify.assertNotEmpty import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import com.lemonappdev.konsist.core.filesystem.PathProvider import org.amshove.kluent.shouldContain import org.amshove.kluent.shouldThrow import org.junit.jupiter.api.Test class AssertEmptyOnDeclarationSequenceTest { + private val rootPath = PathProvider.rootProjectPath + @Test fun `declaration-assert-test-method-name-derived-from-junit-method-name`() { // given @@ -100,9 +102,15 @@ class AssertEmptyOnDeclarationSequenceTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-on-list-containing-non-null-values.kt" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-on-list-containing-non-null-values' failed. " + - "Declaration list is not empty. It contains values:\nSampleClass1,\nSampleClass2.", + "Declaration list is not empty. It contains values:\n" + + "├── Class SampleClass1 $filepath:1:1\n" + + "└── Class SampleClass2 $filepath:3:1", ) ?: throw e } @@ -121,9 +129,14 @@ class AssertEmptyOnDeclarationSequenceTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-on-list-containing-null-and-non-null-values.kt:1:24" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-on-list-containing-null-and-non-null-values' failed. " + - "Declaration list is not empty. It contains 1 null value and values:\nInt.", + "Declaration list is not empty. It contains 1 null value and values:\n" + + "└── Type Int $filepath", ) ?: throw e } @@ -142,9 +155,14 @@ class AssertEmptyOnDeclarationSequenceTest { try { sut.assertEmpty(additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-with-custom-message.kt:1:1" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-with-custom-message' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } @@ -163,9 +181,14 @@ class AssertEmptyOnDeclarationSequenceTest { try { sut.assertEmpty(strict = true, additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/kodeclarationassert/" + + "assertempty/snippet/declaration-assert-empty-error-with-custom-message-and-strict-set-to-true.kt:1:1" + e.message?.shouldContain( "Assert 'declaration-assert-empty-error-with-custom-message-and-strict-set-to-true' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderListTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderListTest.kt index 83b952cb64..b097122ad5 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderListTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderListTest.kt @@ -8,11 +8,14 @@ import com.lemonappdev.konsist.api.provider.KoSourceAndAliasTypeProvider import com.lemonappdev.konsist.api.verify.assertEmpty import com.lemonappdev.konsist.api.verify.assertNotEmpty import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import com.lemonappdev.konsist.core.filesystem.PathProvider import org.amshove.kluent.shouldContain import org.amshove.kluent.shouldThrow import org.junit.jupiter.api.Test class AssertEmptyOnProviderListTest { + private val rootPath = PathProvider.rootProjectPath + @Test fun `provider-assert-test-method-name-derived-from-junit-method-name`() { // given @@ -101,9 +104,15 @@ class AssertEmptyOnProviderListTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-on-list-containing-non-null-values.kt" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-on-list-containing-non-null-values' failed. " + - "Declaration list is not empty. It contains values:\nSampleClass1,\nSampleClass2.", + "Declaration list is not empty. It contains values:\n" + + "├── Class SampleClass1 $filepath:1:1\n" + + "└── Class SampleClass2 $filepath:3:1", ) ?: throw e } @@ -122,9 +131,14 @@ class AssertEmptyOnProviderListTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-on-list-containing-null-and-non-null-values.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-on-list-containing-null-and-non-null-values' failed. " + - "Declaration list is not empty. It contains 1 null value and values:\nsampleFunction.", + "Declaration list is not empty. It contains 1 null value and values:\n" + + "└── Function sampleFunction $filepath", ) ?: throw e } @@ -144,9 +158,14 @@ class AssertEmptyOnProviderListTest { try { sut.assertEmpty(additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-with-custom-message.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-with-custom-message' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } @@ -166,9 +185,14 @@ class AssertEmptyOnProviderListTest { try { sut.assertEmpty(strict = true, additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-with-custom-message-and-strict-set-to-true.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-with-custom-message-and-strict-set-to-true' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } diff --git a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderSequenceTest.kt b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderSequenceTest.kt index 3df0ec7dc4..791fc540cf 100644 --- a/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderSequenceTest.kt +++ b/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/assertempty/AssertEmptyOnProviderSequenceTest.kt @@ -8,11 +8,14 @@ import com.lemonappdev.konsist.api.provider.KoSourceAndAliasTypeProvider import com.lemonappdev.konsist.api.verify.assertEmpty import com.lemonappdev.konsist.api.verify.assertNotEmpty import com.lemonappdev.konsist.core.exception.KoAssertionFailedException +import com.lemonappdev.konsist.core.filesystem.PathProvider import org.amshove.kluent.shouldContain import org.amshove.kluent.shouldThrow import org.junit.jupiter.api.Test class AssertEmptyOnProviderSequenceTest { + private val rootPath = PathProvider.rootProjectPath + @Test fun `provider-assert-test-method-name-derived-from-junit-method-name`() { // given @@ -106,9 +109,15 @@ class AssertEmptyOnProviderSequenceTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-on-list-containing-non-null-values.kt" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-on-list-containing-non-null-values' failed. " + - "Declaration list is not empty. It contains values:\nSampleClass1,\nSampleClass2.", + "Declaration list is not empty. It contains values:\n" + + "├── Class SampleClass1 $filepath:1:1\n" + + "└── Class SampleClass2 $filepath:3:1", ) ?: throw e } @@ -128,9 +137,14 @@ class AssertEmptyOnProviderSequenceTest { try { sut.assertEmpty() } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-on-list-containing-null-and-non-null-values.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-on-list-containing-null-and-non-null-values' failed. " + - "Declaration list is not empty. It contains 1 null value and values:\nsampleFunction.", + "Declaration list is not empty. It contains 1 null value and values:\n" + + "└── Function sampleFunction $filepath", ) ?: throw e } @@ -151,9 +165,14 @@ class AssertEmptyOnProviderSequenceTest { try { sut.assertEmpty(additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-with-custom-message.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-with-custom-message' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } @@ -174,9 +193,14 @@ class AssertEmptyOnProviderSequenceTest { try { sut.assertEmpty(strict = true, additionalMessage = message) } catch (e: Exception) { + val filepath = + "file://$rootPath/lib/src/integrationTest/kotlin/com/lemonappdev/konsist/core/verify/koproviderassert/" + + "assertempty/snippet/provider-assert-empty-error-with-custom-message-and-strict-set-to-true.kt:1:1" + e.message?.shouldContain( "Assert 'provider-assert-empty-error-with-custom-message-and-strict-set-to-true' failed.\n$message\n" + - "Declaration list is not empty. It contains values:\nSampleClass.", + "Declaration list is not empty. It contains values:\n" + + "└── Class SampleClass $filepath", ) ?: throw e } diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/Layer.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/Layer.kt index f92fa08622..e74b91e8f7 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/Layer.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/api/architecture/Layer.kt @@ -3,28 +3,36 @@ package com.lemonappdev.konsist.api.architecture /** * Represents an architectural layer within a software system. * - * A layer is defined by its name and a root package path that determines which code belongs to this layer. - * The root package path supports wildcards using ".." notation to include all subpackages. + * An architectural layer is defined by a name and a package path pattern that determines which code belongs to it. + * The package pattern supports wildcards using ".." to include all subpackages at that level. * - * Example usage: - * ``` + * Usage: + * ```kotlin + * // Standard layer definitions (wildcards at the end) * val domainLayer = Layer("Domain", "com.example.domain..") * val presentationLayer = Layer("Presentation", "com.example.presentation..") + * + * // Wildcards layer definitions (wildcards at the start and at the end) + * val specificDomainLayer = Layer("Domain", "..domain..") // matches any path ending with "domain" * ``` * - * Package naming rules: - * - Must end with ".." to indicate inclusion of all subpackages - * - Cannot be empty (just "..") - * - Cannot start with a dot - * - Each package segment must: - * - Start with a lowercase letter - * - Contain only lowercase letters, numbers, or underscores - * - Follow standard Java package naming conventions - * - Intermediate ".." wildcards are allowed (e.g., "com..domain..") + * Package Pattern Rules: + * 1. Basic Structure + * - Must end with ".." to indicate subpackage inclusion + * - Cannot be empty (just "..") + * - Can start with ".." for wildcard matching + * + * 2. Package Segments + * - Must start with a lowercase letter + * - Can contain: lowercase letters, numbers, underscores * - * @property name The name of the layer. Must not be blank. - * @property rootPackage The package path defining this layer. Must follow the package naming rules. - * @throws IllegalArgumentException If name or rootPackage is blank + * 3. Wildcard Usage + * - ".." is only allowed at start or end of pattern + * - No consecutive dots except for wildcard notation + * + * @property name Layer identifier (non-blank) + * @property rootPackage Package pattern defining layer scope (must follow pattern rules) + * @throws IllegalArgumentException If name is blank or rootPackage violates pattern rules */ @Suppress("detekt.ThrowsCount") data class Layer( @@ -52,39 +60,48 @@ data class Layer( ) } - // Check if there's more than one ".." in the package - if (countConsecutiveDoubleDots(rootPackage) > 1) { + // Remove the ending '..' for further validation + val packageWithoutEndingDots = rootPackage.removeSuffix("..") + + // Empty package (just ..) is not valid + if (packageWithoutEndingDots.isEmpty()) { throw IllegalArgumentException( - "Invalid package definition for layer '$name'. Package can only end with '..'. " + - "Current definition: $rootPackage", + "Invalid package definition for layer '$name'. " + + "Package name cannot be empty. Current definition: $rootPackage", ) } - val packageWithoutDoubleDot = rootPackage.removeSuffix("..") + // Special handling for packages starting with '..' + val effectivePackage = + if (packageWithoutEndingDots.startsWith("..")) { + packageWithoutEndingDots.substring(2) + } else { + packageWithoutEndingDots + } - // Empty package (just ..) is not valid - if (packageWithoutDoubleDot.isEmpty()) { + // Check for starting dot (but not ..) + if (effectivePackage.startsWith(".") && !packageWithoutEndingDots.startsWith("..")) { throw IllegalArgumentException( "Invalid package definition for layer '$name'. " + - "Package name cannot be empty. Current definition: $rootPackage", + "Package cannot start with a dot. Current definition: $rootPackage", ) } - // Check for starting dot - if (packageWithoutDoubleDot.startsWith(".")) { + // Check for consecutive dots in middle (excluding the start and end ..) + if (effectivePackage.contains("..")) { throw IllegalArgumentException( "Invalid package definition for layer '$name'. " + - "Package cannot start with a dot. Current definition: $rootPackage", + "Package can only end with '..'. Current definition: $rootPackage", ) } - // Validate each package segment + // Split and validate segments val segments = - packageWithoutDoubleDot + effectivePackage .split(".") - .filter { it.isNotEmpty() && it != "." } // Filter out empty segments and single dots - .map { if (it == ".") "" else it } // Handle any remaining dots + .filter { it.isNotEmpty() } + // Validate each segment segments.forEachIndexed { index, segment -> if (!segment.matches(REGEX_VALID_PACKAGE_SEGMENT)) { throw IllegalArgumentException( @@ -97,30 +114,6 @@ data class Layer( } } - /** - * Counts the number of ".." occurrences in the string. - * Looks for exactly two consecutive dots, not counting sequences of 3 or more dots. - * - * @param str The string to check - * @return The number of ".." occurrences - */ - private fun countConsecutiveDoubleDots(str: String): Int { - var count = 0 - var i = 0 - while (i < str.length - 1) { - if (str[i] == '.' && str[i + 1] == '.') { - // Check if it's exactly two dots (not three or more) - if (i + 2 >= str.length || str[i + 2] != '.') { - count++ - } - i += 2 - } else { - i++ - } - } - return count - } - private fun endsWithExactlyTwoDots(): Boolean { val lastIndex = rootPackage.length - 1 return lastIndex >= 1 && 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 d13cfb3e90..cc259bc951 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 @@ -7,146 +7,239 @@ package com.lemonappdev.konsist.api.architecture */ interface LayerDependencies { /** - * Adds dependencies between the current layer and the specified layers. + * Establishes dependency relationships between layers in the architecture. * - * @receiver The [Layer] that depends on other layers. - * @param layer The layer that the current layer depends on. - * @param layers The layers that the current layer depends on. + * Example: + * ```kotlin + * // Required dependency - Feature layer must depend on Domain layer + * featureLayer.dependsOn(domainLayer, strict = true) + * + * // Optional dependency - Feature layer may depend on both Domain and Data layers + * featureLayer.dependsOn(domainLayer, dataLayer, strict = false) + * ``` + * + * @receiver The source [Layer] that will have dependencies defined. + * @param layer The primary target layer that the source layer will depend on. + * @param layers Additional target layers that the source layer will depend on. + * @param strict Controls the dependency enforcement: + * - true: MUST have dependencies - The source layer is required to have actual dependencies + * on the target layer(s) in the codebase. If dependencies are missing, it will be reported as a violation. + * - false: MAY have dependencies (default) - The source layer is allowed to have dependencies + * on the target layer(s), but it's not mandatory. No violations will be reported if dependencies are missing. */ fun Layer.dependsOn( layer: Layer, vararg layers: Layer, + strict: Boolean = false, ): Unit /** - * Adds dependencies between the current layer and the specified list of layers. + * Establishes dependency relationships from a source layer to multiple target layers. + * + * This function allows defining dependencies from a single source layer to multiple target layers + * simultaneously using a Set of layers. * - * @receiver The [Layer] that depends on other layers. - * @param layers The list of layers that the current layer depends on. + * Example: + * ```kotlin + * // Makes Feature layer depend on both Domain and Data layers + * featureLayer.dependsOn(setOf(domainLayer, dataLayer)) + * + * // Makes Feature layer require dependencies on both Domain and Data layers + * featureLayer.dependsOn(setOf(domainLayer, dataLayer), strict = true) + * ``` + * + * @receiver The source [Layer] that will have dependencies defined. + * @param layers Set of target layers that the source layer will depend on. + * @param strict Controls the dependency enforcement: + * - true: MUST have dependencies - The source layer is required to have actual dependencies + * on all target layers in the codebase. If any dependencies are missing, it will be reported as a violation. + * - false: MAY have dependencies (default) - The source layer is allowed to have dependencies + * on the target layers, but it's not mandatory. No violations will be reported if dependencies are missing. */ - fun Layer.dependsOn(layers: Set): Unit + fun Layer.dependsOn( + layers: Set, + strict: Boolean = false, + ): Unit /** - * Specifies that the current layer does not depend on any given layer. + * Establishes dependency relationships from multiple source layers to target layer(s). + * + * This extension function allows defining dependencies for multiple layers at once, where each layer + * in the collection will depend on all specified target layer(s). * - * @param layer The layer that the current layer does not depend on. - * @param layers The layers that the current layer does not depend on. - * @receiver The [Layer] that does not depend on other layers. + * Example: + * ```kotlin + * // Makes both Feature and UI layers depend on Domain layer + * setOf(featureLayer, uiLayer).dependsOn(domainLayer) + * + * // Makes Feature and UI layers depend on both Domain and Data layers, with required dependencies + * setOf(featureLayer, uiLayer).dependsOn(domainLayer, dataLayer, strict = true) + * ``` + * + * @receiver The collection of source [Layer]s that will have dependencies defined. + * @param layers Target layer(s) that each source layer will depend on. + * @param strict Controls the dependency enforcement: + * - true: MUST have dependencies - Each source layer is required to have actual dependencies + * on the target layer(s) in the codebase. If dependencies are missing, it will be reported as a violation. + * - false: MAY have dependencies (default) - The source layers are allowed to have dependencies + * on the target layer(s), but it's not mandatory. No violations will be reported if dependencies are missing. */ - fun Layer.doesNotDependOn( - layer: Layer, + fun Collection.dependsOn( vararg layers: Layer, + strict: Boolean = false, ): Unit /** - * Adds dependencies between each layer in the collection and the specified layer. + * Establishes dependency relationships from multiple source layers to multiple target layers. * - * Example usage: - * ``` - * val layers = setOf(domainLayer, dataLayer) - * layers.dependsOn(presentationLayer) - * ``` + * This function creates dependency rules where each layer in the source collection will depend on + * all layers in the target set. This allows for defining multiple dependencies in bulk. + * + * Example: + * ```kotlin + * // Makes both Feature and UI layers depend on both Domain and Data layers + * val sourceLayers = setOf(featureLayer, uiLayer) + * val targetLayers = setOf(domainLayer, dataLayer) + * sourceLayers.dependsOn(targetLayers) * - * @receiver The collection of [Layer]s that depends on other layer. - * @param layer The layer that the collection of layers depends on. + * // With strict enforcement (required dependencies) + * sourceLayers.dependsOn(targetLayers, strict = true) + * ``` + * @receiver The collection of source [Layer]s that will have dependencies defined. + * @param layers Set of target layers that each source layer will depend on. + * @param strict Controls the dependency enforcement: + * - true: MUST have dependencies - Each source layer is required to have actual dependencies + * on all target layers in the codebase. If dependencies are missing, it will be reported as a violation. + * - false: MAY have dependencies (default) - The source layers are allowed to have dependencies + * on the target layers, but it's not mandatory. No violations will be reported if dependencies are missing. */ - fun Collection.dependsOn(layer: Layer): Unit + fun Collection.dependsOn( + layers: Set, + strict: Boolean = false, + ): Unit /** - * Specifies that the current layer does not depend on the given list of layers. + * Specifies forbidden dependencies between layers in the architecture. + * + * Example: + * ```kotlin + * // Domain layer must never depend on UI layer + * domainLayer.doesNotDependOn(uiLayer, strict = true) * - * @param layers The list of layers that the current layer does not depend on. - * @receiver The [Layer] that does not depend on other layers. + * // Domain layer should not depend on UI and Feature layers + * domainLayer.doesNotDependOn(uiLayer, featureLayer, strict = false) + * ``` + * + * @receiver The source [Layer] for which dependencies will be forbidden. + * @param layer The primary target layer that should not be depended on. + * @param layers Additional target layers that should not be depended on. */ - fun Layer.doesNotDependOn(layers: Set): Unit + fun Layer.doesNotDependOn( + layer: Layer, + vararg layers: Layer, + ): Unit /** - * Adds dependencies between each layer in the collection and the specified layers. + * Specifies forbidden dependencies from a source layer to multiple target layers. * - * Example usage: - * ``` - * val sourceLayers = setOf(domainLayer, dataLayer) - * val targetLayers = setOf(presentationLayer, infrastructureLayer) - * sourceLayers.dependsOn(targetLayers) + * Example: + * ```kotlin + * // Domain layer must never depend on UI or Feature layers + * domainLayer.doesNotDependOn(setOf(uiLayer, featureLayer)) * ``` * - * @receiver The collection of [Layer]s that depends on other layers. - * @param layers The set of layers that the collection of layers depends on. + * @receiver The source [Layer] for which dependencies will be forbidden. + * @param layers Set of target layers that should not be depended on. */ - fun Collection.dependsOn(layers: Set): Unit + fun Layer.doesNotDependOn(layers: Set): Unit /** - * Specifies that the current layer does not depend on any other layer. + * Specifies forbidden dependencies from multiple source layers to a target layer. * - * @receiver The [Layer] that does not depend on any other layer. + * Example: + * ```kotlin + * // Domain and Data layers must never depend on UI layer + * setOf(domainLayer, dataLayer).doesNotDependOn(uiLayer) + * ``` * - * @see include + * @receiver Collection of source [Layer]s for which dependencies will be forbidden. + * @param layer The target layer that should not be depended on. + * @param strict Controls the dependency enforcement: + * - true: MUST NOT have dependencies - Any dependencies between layers will be reported as violations. + * - false: SHOULD NOT have dependencies (default) - Dependencies are discouraged but allowed. */ - fun Layer.dependsOnNothing(): Unit + fun Collection.doesNotDependOn(layer: Layer): Unit /** - * Specifies that none of the layers in the collection depend on any other layer. + * Specifies forbidden dependencies from multiple source layers to multiple target layers. * - * Example usage: - * ``` - * val layers = setOf(domainLayer, dataLayer) - * layers.dependsOnNothing() + * Example: + * ```kotlin + * // Domain and Data layers must never depend on UI and Feature layers + * val sourceLayers = setOf(domainLayer, dataLayer) + * val targetLayers = setOf(uiLayer, featureLayer) + * sourceLayers.doesNotDependOn(targetLayers) * ``` - * - * @receiver The collection of [Layer]s that should not depend on any other layer. - * @see include + * @receiver Collection of source [Layer]s for which dependencies will be forbidden. + * @param layers Set of target layers that should not be depended on. */ - fun Collection.dependsOnNothing(): Unit + fun Collection.doesNotDependOn(layers: Set): Unit /** - * Specifies that none of the layers in the collection depend on the specified layer. + * Specifies that the current layer must not have any dependencies. * - * Example usage: - * ``` - * val layers = setOf(domainLayer, dataLayer) - * layers.doesNotDependOn(presentationLayer) + * Example: + * ```kotlin + * // Domain layer must be completely independent + * domainLayer.dependsOnNothing() * ``` * - * @receiver The collection of [Layer]s that do not depend on the specified layer. - * @param layer The layer that none of the collection layers should depend on. + * @receiver The [Layer] that should not have any dependencies. + * @see include */ - fun Collection.doesNotDependOn(layer: Layer): Unit + fun Layer.dependsOnNothing(): Unit /** - * Specifies that none of the layers in the collection depend on any of the specified layers. + * Specifies that none of the layers in the collection should have any dependencies. * - * Example usage: - * ``` - * val sourceLayers = setOf(domainLayer, dataLayer) - * val targetLayers = setOf(presentationLayer, infrastructureLayer) - * sourceLayers.doesNotDependOn(targetLayers) + * Example: + * ```kotlin + * // Domain and Core layers must be completely independent + * setOf(domainLayer, coreLayer).dependsOnNothing() * ``` * - * @receiver The collection of [Layer]s that do not depend on the specified layers. - * @param layers The set of layers that none of the collection layers should depend on. + * @receiver The collection of [Layer]s that should not have any dependencies. + * @see include */ - fun Collection.doesNotDependOn(layers: Set): Unit + fun Collection.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. + * Includes a Layer in the architecture without specifying any dependencies. + * Can be used in combination with dependsOnNothing() to specify that a layer + * should be isolated from other layers. + * + * Example: + * ```kotlin + * // Include domain layer in architecture checks + * domainLayer.include() + * ``` * - * @receiver LayerDependenciesCore The core dependencies container - * @return The LayerDependenciesCore instance for chaining + * @receiver The [Layer] to be included in architecture checks. */ fun Layer.include(): Unit /** - * Includes all layers from the collection in the architecture without specifying any dependencies. - * This can be used in combination with dependsOnNothing() to specify that multiple layers do not depend on any other layer. - * - * Example usage: - * ``` - * val layers = setOf(domainLayer, dataLayer) - * layers.include() + * Includes multiple layers in the architecture without specifying any dependencies. + * Can be used in combination with dependsOnNothing() to specify that layers + * should be isolated from other layers. + * + * Example: + * ```kotlin + * // Include domain and core layers in architecture checks + * setOf(domainLayer, coreLayer).include() * ``` * - * @receiver The collection of [Layer]s to be included in the architecture. + * @receiver The collection of [Layer]s to be included in architecture checks. */ fun Collection.include(): Unit } diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/api/ext/list/DeprecatedKoDeclarationCastProviderListExt.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/api/ext/list/DeprecatedKoDeclarationCastProviderListExt.kt new file mode 100644 index 0000000000..78933972eb --- /dev/null +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/api/ext/list/DeprecatedKoDeclarationCastProviderListExt.kt @@ -0,0 +1,1405 @@ +@file:Suppress("detekt.TooManyFunctions") + +package com.lemonappdev.konsist.api.ext.list + +import com.lemonappdev.konsist.api.declaration.KoClassDeclaration +import com.lemonappdev.konsist.api.declaration.KoExternalDeclaration +import com.lemonappdev.konsist.api.declaration.KoImportAliasDeclaration +import com.lemonappdev.konsist.api.declaration.KoInterfaceDeclaration +import com.lemonappdev.konsist.api.declaration.KoObjectDeclaration +import com.lemonappdev.konsist.api.declaration.KoTypeAliasDeclaration +import com.lemonappdev.konsist.api.declaration.KoTypeParameterDeclaration +import com.lemonappdev.konsist.api.declaration.combined.KoClassAndInterfaceAndObjectDeclaration +import com.lemonappdev.konsist.api.declaration.combined.KoClassAndInterfaceDeclaration +import com.lemonappdev.konsist.api.declaration.combined.KoClassAndObjectDeclaration +import com.lemonappdev.konsist.api.declaration.combined.KoInterfaceAndObjectDeclaration +import com.lemonappdev.konsist.api.declaration.type.KoKotlinTypeDeclaration +import com.lemonappdev.konsist.api.declaration.type.KoTypeDeclaration +import kotlin.reflect.KClass + +/** + * List containing class declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the class declaration. + * If null, all class declarations are included. + * @return A list of class declarations that match the provided predicate, or all class declarations if no predicate + * is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().classDeclarations()")) +fun List.classDeclarations(predicate: ((KoClassDeclaration) -> Boolean)? = null): List = + filter { it.hasClassDeclaration(predicate) } + .mapNotNull { it.asClassDeclaration() } + +/** + * List containing object declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the object declaration. + * If null, all object declarations are included. + * @return A list of object declarations that match the provided predicate, or all object declarations if no predicate + * is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().objectDeclarations()")) +fun List.objectDeclarations(predicate: ((KoObjectDeclaration) -> Boolean)? = null): List = + filter { it.hasObjectDeclaration(predicate) } + .mapNotNull { it.asObjectDeclaration() } + +/** + * List containing interface declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the interface declaration. + * If null, all interface declarations are included. + * @return A list of interface declarations that match the provided predicate, or all interface declarations if no + * predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().interfaceDeclarations()")) +fun List.interfaceDeclarations( + predicate: ((KoInterfaceDeclaration) -> Boolean)? = null, +): List = + filter { it.hasInterfaceDeclaration(predicate) } + .mapNotNull { it.asInterfaceDeclaration() } + +/** + * List containing class and object declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the class and object declaration. + * If null, all class and object declarations are included. + * @return A list of class and object declarations that match the provided predicate, or all class and object + * declarations if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().classAndObjectDeclarations()")) +fun List.classAndObjectDeclarations( + predicate: ((KoClassAndObjectDeclaration) -> Boolean)? = null, +): List = + filter { it.hasClassOrObjectDeclaration(predicate) } + .mapNotNull { it.asClassOrObjectDeclaration() } + +/** + * List containing class and interface declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the class and interface declaration. + * If null, all class and interface declarations are included. + * @return A list of class and interface declarations that match the provided predicate, or all class and interface + * declarations if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().classAndInterfaceDeclarations()")) +fun List.classAndInterfaceDeclarations( + predicate: ((KoClassAndInterfaceDeclaration) -> Boolean)? = null, +): List = + filter { it.hasClassOrInterfaceDeclaration(predicate) } + .mapNotNull { it.asClassOrInterfaceDeclaration() } + +/** + * List containing interface and object declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the interface and object declaration. + * If null, all interface and object declarations are included. + * @return A list of interface and object declarations that match the provided predicate, or all interface and object + * declarations if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().interfaceAndObjectDeclarations()")) +fun List.interfaceAndObjectDeclarations( + predicate: ((KoInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filter { it.hasInterfaceOrObjectDeclaration(predicate) } + .mapNotNull { it.asInterfaceOrObjectDeclaration() } + +/** + * List containing class, interface and object declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the class, interface and object declaration. + * If null, all class, interface and object declarations are included. + * @return A list of class, interface and object declarations that match the provided predicate, or all class, + * interface and object declarations if no predicate + * is provided. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().classAndInterfaceAndObjectDeclarations()"), +) +fun List.classAndInterfaceAndObjectDeclarations( + predicate: ((KoClassAndInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filter { it.hasClassOrInterfaceOrObjectDeclaration(predicate) } + .mapNotNull { it.asClassOrInterfaceOrObjectDeclaration() } + +/** + * List containing type alias declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the type alias declaration. + * If null, all type alias declarations are included. + * @return A list of type alias declarations that match the provided predicate, or all type alias declarations if no + * predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().typeAliasDeclarations()")) +fun List.typeAliasDeclarations( + predicate: ((KoTypeAliasDeclaration) -> Boolean)? = null, +): List = + filter { it.hasTypeAliasDeclaration(predicate) } + .mapNotNull { it.asTypeAliasDeclaration() } + +/** + * List containing import alias declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the import alias declaration. + * If null, all import alias declarations are included. + * @return A list of import alias declarations that match the provided predicate, or all import alias declarations if + * no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().importAliasDeclarations()")) +fun List.importAliasDeclarations( + predicate: ((KoImportAliasDeclaration) -> Boolean)? = null, +): List = + filter { it.hasImportAliasDeclaration(predicate) } + .mapNotNull { it.asImportAliasDeclaration() } + +/** + * List containing Kotlin type declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the Kotlin type declaration. + * If null, all Kotlin type declarations are included. + * @return A list of Kotlin type declarations that match the provided predicate, or all Kotlin type declarations if + * no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().kotlinTypeDeclarations()")) +fun List.kotlinTypeDeclarations( + predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null, +): List = + filter { it.hasKotlinTypeDeclaration(predicate) } + .mapNotNull { it.asKotlinTypeDeclaration() } + +/** + * List containing Kotlin basic type declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the Kotlin basic type declaration. + * If null, all Kotlin basic type declarations are included. + * @return A list of Kotlin basic type declarations that match the provided predicate, or all Kotlin basic type + * declarations if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().kotlinBasicTypeDeclarations()")) +fun List.kotlinBasicTypeDeclarations( + predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null, +): List = + filter { it.hasKotlinBasicTypeDeclaration(predicate) } + .mapNotNull { it.asKotlinBasicTypeDeclaration() } + +/** + * List containing Kotlin collection type declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the Kotlin collection type declaration. + * If null, all Kotlin collection type declarations are included. + * @return A list of Kotlin collection type declarations that match the provided predicate, or all Kotlin collection type + * declarations if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().kotlinCollectionTypeDeclarations()")) +fun List.kotlinCollectionTypeDeclarations( + predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null, +): List = + filter { it.hasKotlinCollectionTypeDeclaration(predicate) } + .mapNotNull { it.asKotlinCollectionTypeDeclaration() } + +/** + * List containing type parameter declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the type parameter declaration. + * If null, all type parameter declarations are included. + * @return A list of type parameter declarations that match the provided predicate, or all type parameter declarations + * if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().typeParameterDeclarations()")) +fun List.typeParameterDeclarations( + predicate: ((KoTypeParameterDeclaration) -> Boolean)? = null, +): List = + filter { it.hasTypeParameterDeclaration(predicate) } + .mapNotNull { it.asTypeParameterDeclaration() } + +/** + * List containing external declarations associated with declarations. + * + * @param predicate A function that defines the condition to be met by the external declaration. + * If null, all external declarations are included. + * @return A list of external declarations that match the provided predicate, or all external declarations + * if no predicate is provided. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().externalDeclarations()")) +fun List.externalDeclarations( + predicate: ((KoExternalDeclaration) -> Boolean)? = null, +): List = + filter { it.hasExternalDeclaration(predicate) } + .mapNotNull { it.asExternalDeclaration() } + +/** + * List containing declarations with the specified class declaration. + * + * @param predicate The predicate function to determine if a class declaration satisfies a condition. + * @return A list containing declarations with the specified class declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassDeclaration()")) +fun List.withClassDeclaration(predicate: ((KoClassDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isClass + else -> it.asClassDeclaration()?.let { classDeclaration -> predicate(classDeclaration) } == true + } + } + +/** + * List containing declarations without the specified class declaration. + * + * @param predicate The predicate function to determine if a class declaration satisfies a condition. + * @return A list containing declarations without the specified class declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutClassDeclaration()")) +fun List.withoutClassDeclaration(predicate: ((KoClassDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isClass + else -> it.asClassDeclaration()?.let { classDeclaration -> predicate(classDeclaration) } == true + } + } + +/** + * List containing declarations with class declaration of. + * + * @param kClass The Kotlin class representing the class declaration to include. + * @param kClasses The Kotlin class(es) representing the class declaration(s) to include. + * @return A list containing declarations with the class declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassDeclarationOf()")) +fun List.withClassDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withClassDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with class declaration of. + * + * @param kClasses The Kotlin class(es) representing the class declaration(s) to include. + * @return A list containing declarations with the class declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassDeclarationOf()")) +fun List.withClassDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasClassDeclaration() + else -> kClasses.any { kClass -> it.hasClassDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without class declaration of. + * + * @param kClass The Kotlin class representing the class declaration to exclude. + * @param kClasses The Kotlin class(es) representing the class declaration(s) to exclude. + * @return A list containing declarations without class declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutClassDeclarationOf()")) +fun List.withoutClassDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutClassDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without class declaration of. + * + * @param kClasses The Kotlin class(es) representing the class declaration(s) to exclude. + * @return A list containing declarations without class declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutClassDeclarationOf()")) +fun List.withoutClassDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasClassDeclaration() + else -> kClasses.any { kClass -> it.hasClassDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified object declaration. + * + * @param predicate The predicate function to determine if a object declaration satisfies a condition. + * @return A list containing declarations with the specified object declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withObjectDeclaration()")) +fun List.withObjectDeclaration(predicate: ((KoObjectDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isObject + else -> it.asObjectDeclaration()?.let { objectDeclaration -> predicate(objectDeclaration) } == true + } + } + +/** + * List containing declarations without the specified object declaration. + * + * @param predicate The predicate function to determine if a object declaration satisfies a condition. + * @return A list containing declarations without the specified object declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutObjectDeclaration()")) +fun List.withoutObjectDeclaration(predicate: ((KoObjectDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isObject + else -> it.asObjectDeclaration()?.let { objectDeclaration -> predicate(objectDeclaration) } == true + } + } + +/** + * List containing declarations with object declaration of. + * + * @param kClass The Kotlin class representing the object declaration to include. + * @param kClasses The Kotlin class(es) representing the object declaration(s) to include. + * @return A list containing declarations with the object declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withObjectDeclarationOf()")) +fun List.withObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with object declaration of. + * + * @param kClasses The Kotlin class(es) representing the object declaration(s) to include. + * @return A list containing declarations with the object declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withObjectDeclarationOf()")) +fun List.withObjectDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasObjectDeclaration() + else -> kClasses.any { kClass -> it.hasObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without object declaration of. + * + * @param kClass The Kotlin class representing the object declaration to exclude. + * @param kClasses The Kotlin class(es) representing the object declaration(s) to exclude. + * @return A list containing declarations without object declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutObjectDeclarationOf()")) +fun List.withoutObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without object declaration of. + * + * @param kClasses The Kotlin class(es) representing the object declaration(s) to exclude. + * @return A list containing declarations without object declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutObjectDeclarationOf()")) +fun List.withoutObjectDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasObjectDeclaration() + else -> kClasses.any { kClass -> it.hasObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified interface declaration. + * + * @param predicate The predicate function to determine if a interface declaration satisfies a condition. + * @return A list containing declarations with the specified interface declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withInterfaceDeclaration()")) +fun List.withInterfaceDeclaration(predicate: ((KoInterfaceDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isInterface + else -> + it.asInterfaceDeclaration()?.let { interfaceDeclaration -> predicate(interfaceDeclaration) } == true + } + } + +/** + * List containing declarations without the specified interface declaration. + * + * @param predicate The predicate function to determine if a interface declaration satisfies a condition. + * @return A list containing declarations without the specified interface declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutInterfaceDeclaration()")) +fun List.withoutInterfaceDeclaration(predicate: ((KoInterfaceDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isInterface + else -> + it.asInterfaceDeclaration()?.let { interfaceDeclaration -> predicate(interfaceDeclaration) } == true + } + } + +/** + * List containing declarations with interface declaration of. + * + * @param kClass The Kotlin class representing the interface declaration to include. + * @param kClasses The Kotlin class(es) representing the interface declaration(s) to include. + * @return A list containing declarations with the interface declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withInterfaceDeclarationOf()")) +fun List.withInterfaceDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withInterfaceDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with interface declaration of. + * + * @param kClasses The Kotlin class(es) representing the interface declaration(s) to include. + * @return A list containing declarations with the interface declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withInterfaceDeclarationOf()")) +fun List.withInterfaceDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasInterfaceDeclaration() + else -> kClasses.any { kClass -> it.hasInterfaceDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without interface declaration of. + * + * @param kClass The Kotlin class representing the interface declaration to exclude. + * @param kClasses The Kotlin class(es) representing the interface declaration(s) to exclude. + * @return A list containing declarations without interface declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutInterfaceDeclarationOf()")) +fun List.withoutInterfaceDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutInterfaceDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without interface declaration of. + * + * @param kClasses The Kotlin class(es) representing the interface declaration(s) to exclude. + * @return A list containing declarations without interface declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutInterfaceDeclarationOf()")) +fun List.withoutInterfaceDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasInterfaceDeclaration() + else -> kClasses.any { kClass -> it.hasInterfaceDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified class or object declaration. + * + * @param predicate The predicate function to determine if a class or object declaration satisfies a condition. + * @return A list containing declarations with the specified class or object declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassOrObjectDeclaration()")) +fun List.withClassOrObjectDeclaration(predicate: ((KoClassAndObjectDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isClassOrObject + else -> it.asClassOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations without the specified class or object declaration. + * + * @param predicate The predicate function to determine if a class or object declaration satisfies a condition. + * @return A list containing declarations without the specified class or object declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutClassOrObjectDeclaration()")) +fun List.withoutClassOrObjectDeclaration( + predicate: ((KoClassAndObjectDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isClassOrObject + else -> it.asClassOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations with class or object declaration of. + * + * @param kClass The Kotlin class representing the class or object declaration to include. + * @param kClasses The Kotlin class(es) representing the class or object declaration(s) to include. + * @return A list containing declarations with the class or object declaration of the specified Kotlin class(es). + */ + +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassOrObjectDeclarationOf()")) +fun List.withClassOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withClassOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with class or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the class or object declaration(s) to include. + * @return A list containing declarations with the class or object declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassOrObjectDeclarationOf()")) +fun List.withClassOrObjectDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasClassOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without class or object declaration of. + * + * @param kClass The Kotlin class representing the class or object declaration to exclude. + * @param kClasses The Kotlin class(es) representing the class or object declaration(s) to exclude. + * @return A list containing declarations without class or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrObjectDeclarationOf()"), +) +fun List.withoutClassOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutClassOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without class or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the class or object declaration(s) to exclude. + * @return A list containing declarations without class or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrObjectDeclarationOf()"), +) +fun List.withoutClassOrObjectDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasClassOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified class or interface declaration. + * + * @param predicate The predicate function to determine if a class or interface declaration satisfies a condition. + * @return A list containing declarations with the specified class or interface declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withClassOrInterfaceDeclaration()")) +fun List.withClassOrInterfaceDeclaration( + predicate: ((KoClassAndInterfaceDeclaration) -> Boolean)? = null, +): List = + filter { + when (predicate) { + null -> it.isClassOrInterface + else -> it.asClassOrInterfaceDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations without the specified class or interface declaration. + * + * @param predicate The predicate function to determine if a class or interface declaration satisfies a condition. + * @return A list containing declarations without the specified class or interface declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceDeclaration()"), +) +fun List.withoutClassOrInterfaceDeclaration( + predicate: ((KoClassAndInterfaceDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isClassOrInterface + else -> it.asClassOrInterfaceDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations with class or interface declaration of. + * + * @param kClass The Kotlin class representing the class or interface declaration to include. + * @param kClasses The Kotlin class(es) representing the class or interface declaration(s) to include. + * @return A list containing declarations with the class or interface declaration of the specified Kotlin class(es). + */ + +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withClassOrInterfaceDeclarationOf()"), +) +fun List.withClassOrInterfaceDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withClassOrInterfaceDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with class or interface declaration of. + * + * @param kClasses The Kotlin class(es) representing the class or interface declaration(s) to include. + * @return A list containing declarations with the class or interface declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withClassOrInterfaceDeclarationOf()"), +) +fun List.withClassOrInterfaceDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasClassOrInterfaceDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrInterfaceDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without class or interface declaration of. + * + * @param kClass The Kotlin class representing the class or interface declaration to exclude. + * @param kClasses The Kotlin class(es) representing the class or interface declaration(s) to exclude. + * @return A list containing declarations without class or interface declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceDeclarationOf()"), +) +fun List.withoutClassOrInterfaceDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutClassOrInterfaceDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without class or interface declaration of. + * + * @param kClasses The Kotlin class(es) representing the class or interface declaration(s) to exclude. + * @return A list containing declarations without class or interface declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceDeclarationOf()"), +) +fun List.withoutClassOrInterfaceDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasClassOrInterfaceDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrInterfaceDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified interface or object declaration. + * + * @param predicate The predicate function to determine if a interface or object declaration satisfies a condition. + * @return A list containing declarations with the specified interface or object declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withInterfaceOrObjectDeclaration()")) +fun List.withInterfaceOrObjectDeclaration( + predicate: ((KoInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filter { + when (predicate) { + null -> it.isInterfaceOrObject + else -> it.asInterfaceOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations without the specified interface or object declaration. + * + * @param predicate The predicate function to determine if a interface or object declaration satisfies a condition. + * @return A list containing declarations without the specified interface or object declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutInterfaceOrObjectDeclaration()"), +) +fun List.withoutInterfaceOrObjectDeclaration( + predicate: ((KoInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isInterfaceOrObject + else -> it.asInterfaceOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations with interface or object declaration of. + * + * @param kClass The Kotlin class representing the interface or object declaration to include. + * @param kClasses The Kotlin class(es) representing the interface or object declaration(s) to include. + * @return A list containing declarations with the interface or object declaration of the specified Kotlin class(es). + */ + +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withInterfaceOrObjectDeclarationOf()"), +) +fun List.withInterfaceOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withInterfaceOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with interface or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the interface or object declaration(s) to include. + * @return A list containing declarations with the interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withInterfaceOrObjectDeclarationOf()"), +) +fun List.withInterfaceOrObjectDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasInterfaceOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasInterfaceOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without interface or object declaration of. + * + * @param kClass The Kotlin class representing the interface or object declaration to exclude. + * @param kClasses The Kotlin class(es) representing the interface or object declaration(s) to exclude. + * @return A list containing declarations without interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutInterfaceOrObjectDeclarationOf()"), +) +fun List.withoutInterfaceOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutInterfaceOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without interface or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the interface or object declaration(s) to exclude. + * @return A list containing declarations without interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutInterfaceOrObjectDeclarationOf()"), +) +fun List.withoutInterfaceOrObjectDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasInterfaceOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasInterfaceOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified class, interface or object declaration. + * + * @param predicate The predicate function to determine if an class, interface or object declaration satisfies a condition. + * @return A list containing declarations with the specified class, interface or object declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withClassOrInterfaceOrObjectDeclaration()"), +) +fun List.withClassOrInterfaceOrObjectDeclaration( + predicate: ((KoClassAndInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filter { + when (predicate) { + null -> it.isClassOrInterfaceOrObject + else -> it.asClassOrInterfaceOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations without the specified class, interface or object declaration. + * + * @param predicate The predicate function to determine if a class, interface or object declaration satisfies a condition. + * @return A list containing declarations without the specified class, interface or object declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceOrObjectDeclaration()"), +) +fun List.withoutClassOrInterfaceOrObjectDeclaration( + predicate: ((KoClassAndInterfaceAndObjectDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isClassOrInterfaceOrObject + else -> it.asClassOrInterfaceOrObjectDeclaration()?.let { declaration -> predicate(declaration) } == true + } + } + +/** + * List containing declarations with class, interface or object declaration of. + * + * @param kClass The Kotlin class representing the class, interface or object declaration to include. + * @param kClasses The Kotlin class(es) representing the class, interface or object declaration(s) to include. + * @return A list containing declarations with the class, interface or object declaration of the specified Kotlin class(es). + */ + +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withClassOrInterfaceOrObjectDeclarationOf()"), +) +fun List.withClassOrInterfaceOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withClassOrInterfaceOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with class, interface or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the class, interface or object declaration(s) to include. + * @return A list containing declarations with the class, interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withClassOrInterfaceOrObjectDeclarationOf()"), +) +fun List.withClassOrInterfaceOrObjectDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasClassOrInterfaceOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrInterfaceOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without class, interface or object declaration of. + * + * @param kClass The Kotlin class representing the class, interface or object declaration to exclude. + * @param kClasses The Kotlin class(es) representing the class, interface or object declaration(s) to exclude. + * @return A list containing declarations without class, interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceOrObjectDeclarationOf()"), +) +fun List.withoutClassOrInterfaceOrObjectDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutClassOrInterfaceOrObjectDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without class, interface or object declaration of. + * + * @param kClasses The Kotlin class(es) representing the class, interface or object declaration(s) to exclude. + * @return A list containing declarations without class, interface or object declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutClassOrInterfaceOrObjectDeclarationOf()"), +) +fun List.withoutClassOrInterfaceOrObjectDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasClassOrInterfaceOrObjectDeclaration() + else -> kClasses.any { kClass -> it.hasClassOrInterfaceOrObjectDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified type alias declaration. + * + * @param predicate The predicate function to determine if a type alias declaration satisfies a condition. + * @return A list containing declarations with the specified type alias declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withTypeAliasDeclaration()")) +fun List.withTypeAliasDeclaration(predicate: ((KoTypeAliasDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isTypeAlias + else -> + it.asTypeAliasDeclaration()?.let { typeAliasDeclaration -> predicate(typeAliasDeclaration) } == true + } + } + +/** + * List containing declarations without the specified type alias declaration. + * + * @param predicate The predicate function to determine if a type alias declaration satisfies a condition. + * @return A list containing declarations without the specified type alias declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutTypeAliasDeclaration()")) +fun List.withoutTypeAliasDeclaration(predicate: ((KoTypeAliasDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isTypeAlias + else -> + it.asTypeAliasDeclaration()?.let { typeAliasDeclaration -> predicate(typeAliasDeclaration) } == true + } + } + +/** + * List containing declarations with the specified import alias declaration. + * + * @param predicate The predicate function to determine if a import alias declaration satisfies a condition. + * @return A list containing declarations with the specified import alias declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withImportAliasDeclaration()")) +fun List.withImportAliasDeclaration(predicate: ((KoImportAliasDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isImportAlias + else -> + it + .asImportAliasDeclaration() + ?.let { importAliasDeclaration -> predicate(importAliasDeclaration) } == true + } + } + +/** + * List containing declarations without the specified import alias declaration. + * + * @param predicate The predicate function to determine if a import alias declaration satisfies a condition. + * @return A list containing declarations without the specified import alias declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutImportAliasDeclaration()")) +fun List.withoutImportAliasDeclaration(predicate: ((KoImportAliasDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isImportAlias + else -> + it + .asImportAliasDeclaration() + ?.let { importAliasDeclaration -> predicate(importAliasDeclaration) } == true + } + } + +/** + * List containing declarations with the specified kotlin type declaration. + * + * @param predicate The predicate function to determine if a kotlin type declaration satisfies a condition. + * @return A list containing declarations with the specified kotlin type declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinTypeDeclaration()")) +fun List.withKotlinTypeDeclaration(predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isKotlinType + else -> + it.asKotlinTypeDeclaration()?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations without the specified kotlin type declaration. + * + * @param predicate The predicate function to determine if a kotlin type declaration satisfies a condition. + * @return A list containing declarations without the specified kotlin type declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutKotlinTypeDeclaration()")) +fun List.withoutKotlinTypeDeclaration(predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isKotlinType + else -> + it.asKotlinTypeDeclaration()?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations with kotlin type declaration of. + * + * @param kClass The Kotlin class representing the kotlin type declaration to include. + * @param kClasses The Kotlin class(es) representing the kotlin type declaration(s) to include. + * @return A list containing declarations with the kotlin type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinTypeDeclarationOf()")) +fun List.withKotlinTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withKotlinTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with kotlin type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin type declaration(s) to include. + * @return A list containing declarations with the kotlin type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinTypeDeclarationOf()")) +fun List.withKotlinTypeDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasKotlinTypeDeclaration() + else -> kClasses.any { kClass -> it.hasKotlinTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without kotlin type declaration of. + * + * @param kClass The Kotlin class representing the kotlin type declaration to exclude. + * @param kClasses The Kotlin class(es) representing the kotlin type declaration(s) to exclude. + * @return A list containing declarations without kotlin type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutKotlinTypeDeclarationOf()")) +fun List.withoutKotlinTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutKotlinTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without kotlin type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin type declaration(s) to exclude. + * @return A list containing declarations without kotlin type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutKotlinTypeDeclarationOf()")) +fun List.withoutKotlinTypeDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasKotlinTypeDeclaration() + else -> kClasses.any { kClass -> it.hasKotlinTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified kotlin basic type declaration. + * + * @param predicate The predicate function to determine if a kotlin basic type declaration satisfies a condition. + * @return A list containing declarations with the specified kotlin basic type declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinBasicTypeDeclaration()")) +fun List.withKotlinBasicTypeDeclaration(predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isKotlinBasicType + else -> + it + .asKotlinBasicTypeDeclaration() + ?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations without the specified kotlin basic type declaration. + * + * @param predicate The predicate function to determine if a kotlin basic type declaration satisfies a condition. + * @return A list containing declarations without the specified kotlin basic type declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinBasicTypeDeclaration()"), +) +fun List.withoutKotlinBasicTypeDeclaration(predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isKotlinBasicType + else -> + it + .asKotlinBasicTypeDeclaration() + ?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations with kotlin basic type declaration of. + * + * @param kClass The Kotlin class representing the kotlin basic type declaration to include. + * @param kClasses The Kotlin class(es) representing the kotlin basic type declaration(s) to include. + * @return A list containing declarations with the kotlin basic type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinBasicTypeDeclarationOf()")) +fun List.withKotlinBasicTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withKotlinBasicTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with kotlin basic type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin basic type declaration(s) to include. + * @return A list containing declarations with the kotlin basic type declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withKotlinBasicTypeDeclarationOf()")) +fun List.withKotlinBasicTypeDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.isKotlinBasicType + else -> kClasses.any { kClass -> it.hasKotlinBasicTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without kotlin basic type declaration of. + * + * @param kClass The Kotlin class representing the kotlin basic type declaration to exclude. + * @param kClasses The Kotlin class(es) representing the kotlin basic type declaration(s) to exclude. + * @return A list containing declarations without kotlin basic type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinBasicTypeDeclarationOf()"), +) +fun List.withoutKotlinBasicTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutKotlinBasicTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without kotlin basic type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin basic type declaration(s) to exclude. + * @return A list containing declarations without kotlin basic type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinBasicTypeDeclarationOf()"), +) +fun List.withoutKotlinBasicTypeDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.isKotlinBasicType + else -> kClasses.any { kClass -> it.hasKotlinBasicTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified kotlin collection type declaration. + * + * @param predicate The predicate function to determine if a kotlin collection type declaration satisfies a condition. + * @return A list containing declarations with the specified kotlin collection type declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withKotlinCollectionTypeDeclaration()"), +) +fun List.withKotlinCollectionTypeDeclaration( + predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null, +): List = + filter { + when (predicate) { + null -> it.isKotlinCollectionType + else -> + it + .asKotlinCollectionTypeDeclaration() + ?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations without the specified kotlin collection type declaration. + * + * @param predicate The predicate function to determine if a kotlin collection type declaration satisfies a condition. + * @return A list containing declarations without the specified kotlin collection type declaration. + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinCollectionTypeDeclaration()"), +) +fun List.withoutKotlinCollectionTypeDeclaration( + predicate: ((KoKotlinTypeDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isKotlinCollectionType + else -> + it + .asKotlinCollectionTypeDeclaration() + ?.let { kotlinTypeDeclaration -> predicate(kotlinTypeDeclaration) } == true + } + } + +/** + * List containing declarations with kotlin collection type declaration of. + * + * @param kClass The Kotlin class representing the kotlin collection type declaration to include. + * @param kClasses The Kotlin class(es) representing the kotlin collection type declaration(s) to include. + * @return A list containing declarations with the kotlin collection type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withKotlinCollectionTypeDeclarationOf()"), +) +fun List.withKotlinCollectionTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withKotlinCollectionTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with kotlin collection type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin collection type declaration(s) to include. + * @return A list containing declarations with the kotlin collection type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withKotlinCollectionTypeDeclarationOf()"), +) +fun List.withKotlinCollectionTypeDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.isKotlinCollectionType + else -> kClasses.any { kClass -> it.hasKotlinCollectionTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without kotlin collection type declaration of. + * + * @param kClass The Kotlin class representing the kotlin collection type declaration to exclude. + * @param kClasses The Kotlin class(es) representing the kotlin collection type declaration(s) to exclude. + * @return A list containing declarations without kotlin collection type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinCollectionTypeDeclarationOf()"), +) +fun List.withoutKotlinCollectionTypeDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutKotlinCollectionTypeDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without kotlin collection type declaration of. + * + * @param kClasses The Kotlin class(es) representing the kotlin collection type declaration(s) to exclude. + * @return A list containing declarations without kotlin collection type declaration of the specified Kotlin class(es). + */ +@Deprecated( + "Will be removed in version 0.19.0", + ReplaceWith("sourceDeclarations().withoutKotlinCollectionTypeDeclarationOf()"), +) +fun List.withoutKotlinCollectionTypeDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.isKotlinCollectionType + else -> kClasses.any { kClass -> it.hasKotlinCollectionTypeDeclarationOf(kClass) } + } + } + +/** + * List containing declarations with the specified type parameter declaration. + * + * @param predicate The predicate function to determine if a type parameter declaration satisfies a condition. + * @return A list containing declarations with the specified type parameter declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withTypeParameterDeclaration()")) +fun List.withTypeParameterDeclaration(predicate: ((KoTypeParameterDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isTypeParameter + else -> + it + .asTypeParameterDeclaration() + ?.let { typeParameter -> predicate(typeParameter) } == true + } + } + +/** + * List containing declarations without the specified type parameter declaration. + * + * @param predicate The predicate function to determine if a type parameter declaration satisfies a condition. + * @return A list containing declarations without the specified type parameter declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutTypeParameterDeclaration()")) +fun List.withoutTypeParameterDeclaration( + predicate: ((KoTypeParameterDeclaration) -> Boolean)? = null, +): List = + filterNot { + when (predicate) { + null -> it.isTypeParameter + else -> + it + .asTypeParameterDeclaration() + ?.let { typeParameter -> predicate(typeParameter) } == true + } + } + +/** + * List containing declarations with the specified external declaration. + * + * @param predicate The predicate function to determine if an external declaration satisfies a condition. + * @return A list containing declarations with the specified external declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withExternalDeclaration()")) +fun List.withExternalDeclaration(predicate: ((KoExternalDeclaration) -> Boolean)? = null): List = + filter { + when (predicate) { + null -> it.isExternal + else -> + it + .asExternalDeclaration() + ?.let { externalDeclaration -> predicate(externalDeclaration) } == true + } + } + +/** + * List containing declarations without the specified external declaration. + * + * @param predicate The predicate function to determine if an external declaration satisfies a condition. + * @return A list containing declarations without the specified external declaration. + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutExternalDeclaration()")) +fun List.withoutExternalDeclaration(predicate: ((KoExternalDeclaration) -> Boolean)? = null): List = + filterNot { + when (predicate) { + null -> it.isExternal + else -> + it + .asExternalDeclaration() + ?.let { externalDeclaration -> predicate(externalDeclaration) } == true + } + } + +/** + * List containing declarations with external declaration of. + * + * @param kClass The Kotlin class representing the external declaration to include. + * @param kClasses The Kotlin class(es) representing the external declaration(s) to include. + * @return A list containing declarations with the external declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withExternalDeclarationOf()")) +fun List.withExternalDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withExternalDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations with external declaration of. + * + * @param kClasses The Kotlin class(es) representing the external declaration(s) to include. + * @return A list containing declarations with the external declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withExternalDeclarationOf()")) +fun List.withExternalDeclarationOf(kClasses: Collection>): List = + filter { + when { + kClasses.isEmpty() -> it.hasExternalDeclaration() + else -> kClasses.any { kClass -> it.hasExternalDeclarationOf(kClass) } + } + } + +/** + * List containing declarations without external declaration of. + * + * @param kClass The Kotlin class representing the external declaration to exclude. + * @param kClasses The Kotlin class(es) representing the external declaration(s) to exclude. + * @return A list containing declarations without external declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutExternalDeclarationOf()")) +fun List.withoutExternalDeclarationOf( + kClass: KClass<*>, + vararg kClasses: KClass<*>, +): List = withoutExternalDeclarationOf(listOf(kClass, *kClasses)) + +/** + * List containing declarations without external declaration of. + * + * @param kClasses The Kotlin class(es) representing the external declaration(s) to exclude. + * @return A list containing declarations without external declaration of the specified Kotlin class(es). + */ +@Deprecated("Will be removed in version 0.19.0", ReplaceWith("sourceDeclarations().withoutExternalDeclarationOf()")) +fun List.withoutExternalDeclarationOf(kClasses: Collection>): List = + filterNot { + when { + kClasses.isEmpty() -> it.hasExternalDeclaration() + else -> kClasses.any { kClass -> it.hasExternalDeclarationOf(kClass) } + } + } 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 87d18341dc..c3fefe8f24 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 @@ -14,30 +14,22 @@ internal class LayerDependenciesCore( internal val layerDependencies = mutableSetOf() internal var layers = mutableSetOf() - internal val dependsOnDependencies: Map> + // ToDO: Create type + internal val dependsOnDependencies: Set get() = layerDependencies .filter { it.dependencyType == LayerDependencyType.DEPENDS_ON_LAYER } - .groupBy { it.layer1 } - .mapValues { (_, dependencies) -> - dependencies.mapNotNull { it.layer2 }.toSet() - } + .toSet() - internal val doesNotDependsOnDependencies: Map> + internal val doesNotDependsOnDependencies: List get() = layerDependencies .filter { it.dependencyType == LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER } - .groupBy { it.layer1 } - .mapValues { (_, dependencies) -> - dependencies.mapNotNull { it.layer2 }.toSet() - } - internal val dependsOnNothingDependencies: Set + internal val dependsOnNothingDependencies: List get() = layerDependencies .filter { it.dependencyType == LayerDependencyType.DEPEND_ON_NOTHING } - .map { it.layer1 } - .toSet() fun checkEmptyLayersDependencies() { if (layers.isEmpty()) { @@ -64,12 +56,17 @@ internal class LayerDependenciesCore( override fun Layer.dependsOn( layer: Layer, vararg layers: Layer, + strict: Boolean, ) { - dependsOn(setOf(layer) + layers.toSet()) + dependsOn(setOf(layer) + layers.toSet(), strict) } - override fun Layer.dependsOn(layers: Set) { + override fun Layer.dependsOn( + layers: Set, + strict: Boolean, + ) { require(layers.isNotEmpty()) { "Layers set is empty." } + requireLayerCannotBeDependentOnItself(this, layers) { "Layer '$name' cannot be dependent on itself." } val dependOnNothingDependency = getLayerWithDependOnNothingDependency(this) @@ -87,18 +84,24 @@ internal class LayerDependenciesCore( } layers.forEach { - addLayerDependency(this, LayerDependencyType.DEPENDS_ON_LAYER, it) + addLayerDependency(this, LayerDependencyType.DEPENDS_ON_LAYER, it, strict) } layerValidatorManager.validateLayerDependencies(layerDependencies) } - override fun Collection.dependsOn(layer: Layer) { - forEach { it.dependsOn(layer) } + override fun Collection.dependsOn( + vararg layers: Layer, + strict: Boolean, + ) { + forEach { it.dependsOn(layers.toSet(), strict) } } - override fun Collection.dependsOn(layers: Set) { - forEach { it.dependsOn(layers) } + override fun Collection.dependsOn( + layers: Set, + strict: Boolean, + ) { + forEach { it.dependsOn(layers, strict) } } private fun getLayersMessage(layers: Set) = @@ -133,7 +136,7 @@ internal class LayerDependenciesCore( } layers.forEach { - addLayerDependency(this, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, it) + addLayerDependency(this, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, it, false) } layerValidatorManager.validateLayerDependencies(layerDependencies) @@ -161,7 +164,7 @@ internal class LayerDependenciesCore( ) } - addLayerDependency(this, LayerDependencyType.DEPEND_ON_NOTHING, null) + addLayerDependency(this, LayerDependencyType.DEPEND_ON_NOTHING, null, false) layers.add(this) layerValidatorManager.validateLayerDependencies(layerDependencies) @@ -173,7 +176,7 @@ internal class LayerDependenciesCore( override fun Layer.include() { layers.add(this) - layerDependencies.add(LayerDependency(this, LayerDependencyType.NONE, null)) + layerDependencies.add(LayerDependency(this, LayerDependencyType.NONE)) } override fun Collection.include() { @@ -201,10 +204,27 @@ internal class LayerDependenciesCore( layer1: Layer, layerDependencyType: LayerDependencyType, layer2: Layer?, + strict: Boolean, ) { - val result = layerDependencies.add(LayerDependency(layer1, layerDependencyType, layer2)) + val forbiddenStrictOverride = + layerDependencies.firstOrNull { + it.layer1 == layer1 && + it.dependencyType == layerDependencyType && + it.layer2 == layer2 + it.strict != strict + } + + if (forbiddenStrictOverride != null) { + throw KoInvalidAssertArchitectureConfigurationException( + "Layer dependency configuration for layer '${layer1.name}' is already defined with " + + "a strict=${forbiddenStrictOverride.strict} value. It cannot be overridden with strict=$strict.", + ) + } + + val layerDependency = LayerDependency(layer1, layerDependencyType, layer2, strict) + val added = layerDependencies.add(layerDependency) - if (result.not()) { + if (added.not()) { val layerName = if (layer2?.name != null) { "'${layer2.name}'" diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependency.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependency.kt index be7f7ac0ff..147753e7ec 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependency.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/architecture/LayerDependency.kt @@ -6,6 +6,7 @@ internal data class LayerDependency( val layer1: Layer, val dependencyType: LayerDependencyType, val layer2: Layer? = null, + val strict: Boolean? = null, ) { init { require(!((dependencyType == LayerDependencyType.DEPENDS_ON_LAYER) && layer2 == null)) { diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoKDocDeclarationCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoKDocDeclarationCore.kt index 5176a0757c..cf039eba39 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoKDocDeclarationCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoKDocDeclarationCore.kt @@ -26,6 +26,8 @@ import com.lemonappdev.konsist.core.provider.tag.KoKDocVersionTagProviderCore import com.lemonappdev.konsist.core.util.EndOfLine import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.kdoc.psi.api.KDocElement +import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection +import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag internal class KoKDocDeclarationCore( private val kDocElement: KDocElement, @@ -54,6 +56,14 @@ internal class KoKDocDeclarationCore( KoKDocSinceTagProviderCore { override val psiElement: PsiElement by lazy { kDocElement } + override val kDocTags: List by lazy { + kDocElement + .children + .filterIsInstance() + .flatMap { it.children.toList() } + .filterIsInstance() + } + override val text: String by lazy { val splitKDoc = kDocElement diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoParentDeclarationCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoParentDeclarationCore.kt index 925ad60e96..2b271be478 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoParentDeclarationCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/declaration/KoParentDeclarationCore.kt @@ -105,14 +105,13 @@ internal class KoParentDeclarationCore( if (import.alias != null) { import.alias?.name == innerName } else { - import.name.substringAfterLast(".") == innerName + import.name.substringAfterLast(".") == outerName } } val fullyQualifiedName = - import - ?.name - ?: (containingFile.packagee?.name + "." + name) + import?.name + ?: "${containingFile.packagee?.name?.let { "$it." } ?: ""}$name" val isAlias = import?.alias != null diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/model/DataCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/model/DataCore.kt index b69a90df85..cc7adf2423 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/model/DataCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/model/DataCore.kt @@ -60,9 +60,6 @@ fun getClass( ?: containingFile .classes() .firstOrNull { decl -> decl.fullyQualifiedName == declarationQualifiedName } - ?: containingFile - .classes() - .firstOrNull { decl -> decl.name == name } } fun getInterface( @@ -84,9 +81,6 @@ fun getInterface( ?: containingFile .interfaces() .firstOrNull { decl -> decl.fullyQualifiedName == declarationQualifiedName } - ?: containingFile - .interfaces() - .firstOrNull { decl -> decl.name == name } } fun getObject( @@ -108,9 +102,6 @@ fun getObject( ?: containingFile .objects() .firstOrNull { decl -> decl.fullyQualifiedName == declarationQualifiedName } - ?: containingFile - .objects() - .firstOrNull { decl -> decl.name == name } } fun getTypeAlias( diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/provider/tag/KoKDocTagProviderCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/provider/tag/KoKDocTagProviderCore.kt index a4ab2b98f0..395b7fddc7 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/provider/tag/KoKDocTagProviderCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/provider/tag/KoKDocTagProviderCore.kt @@ -2,45 +2,48 @@ package com.lemonappdev.konsist.core.provider.tag import com.lemonappdev.konsist.api.KoKDocTag import com.lemonappdev.konsist.api.declaration.KoKDocTagDeclaration -import com.lemonappdev.konsist.api.declaration.KoValuedKDocTagDeclaration import com.lemonappdev.konsist.api.provider.tag.KoKDocTagProvider import com.lemonappdev.konsist.core.declaration.KoKDocTagDeclarationCore import com.lemonappdev.konsist.core.declaration.KoValuedKDocTagDeclarationCore import com.lemonappdev.konsist.core.provider.KoBaseProviderCore import com.lemonappdev.konsist.core.provider.KoTextProviderCore -import com.lemonappdev.konsist.core.util.EndOfLine -import java.util.Locale +import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink +import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag internal interface KoKDocTagProviderCore : KoKDocTagProvider, KoTextProviderCore, KoBaseProviderCore { - override val tags: List - get() { - val regex = "@(\\w+)".toRegex() - - val tagsAsStringList = - text - .substringAfter("@", "") - .split("${EndOfLine.UNIX.value}@") - .map { ("@${it.replaceFirstChar { char -> char.lowercase(Locale.getDefault()) }}").trimEnd() } - - val tagsWithName = - tagsAsStringList - .filterNot { it == "@" } - .flatMap { regex.findAll(it) } - .mapNotNull { KoKDocTag.values().firstOrNull { tag -> tag.type == it.value } } - .zip(tagsAsStringList) + val kDocTags: List - val tagsGroupingByValued = tagsWithName.groupBy { it.first.isValued } - - return tagsGroupingByValued.flatMap { - when (it.key) { - true -> it.value.map { value -> parseToValuedTag(value.first, value.second) } - false -> it.value.map { value -> parseToTag(value.first, value.second) } - } - } - } + override val tags: List + get() = + kDocTags + .map { tag -> + val name = + KoKDocTag + .values() + .firstOrNull { value -> value.type.removePrefix("@") == tag.name } + + if (name == null) { + return@map null + } + + val value = + tag + .children + .filterIsInstance() + .firstOrNull() + ?.text + + val description = tag.getContent() + + if (value != null) { + KoValuedKDocTagDeclarationCore(name, value, description) + } else { + KoKDocTagDeclarationCore(name, description) + } + }.filterNotNull() override val numTags: Int get() = tags.size @@ -68,30 +71,4 @@ internal interface KoKDocTagProviderCore : tags.isEmpty() -> hasTags() else -> this.tags.map { it.name }.containsAll(tags) } - - private fun parseToValuedTag( - koKDocTag: KoKDocTag, - sentence: String, - ): KoValuedKDocTagDeclaration { - val parsed = sentence.split(" ") - val description = - parsed - .subList(2, parsed.size) - .joinToString(" ") - - return KoValuedKDocTagDeclarationCore(koKDocTag, parsed[1], description) - } - - private fun parseToTag( - koKDocTag: KoKDocTag, - sentence: String, - ): KoKDocTagDeclaration { - val parsed = sentence.split(" ") - val description = - parsed - .subList(1, parsed.size) - .joinToString(" ") - - return KoKDocTagDeclarationCore(koKDocTag, description) - } } 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 7cee6094c6..7173a5f605 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 @@ -182,69 +182,65 @@ private fun getFailedDependsOnMessage(dependsOnLayerDependencyFailures: List, layerDependencies: LayerDependenciesCore, -): List { - val failedLayerDependencies = mutableListOf() - - layerDependencies - .dependsOnDependencies - .forEach { (layer, otherLayers) -> - otherLayers.forEach { otherLayer -> - if (!layer.isDependentOn(otherLayer, files)) { - failedLayerDependencies += DependsOnLayerDependencyFailure(layer, otherLayer) +): List = + layerDependencies.dependsOnDependencies + .groupBy { it.layer1 } + .flatMap { (layer1, dependencies) -> + dependencies + .mapNotNull { dep -> + dep.layer2?.let { layer2 -> + Triple(layer1, layer2, dep.strict) + } + }.filter { (layer1, layer2, strict) -> + strict == true && !layer1.isDependentOn(layer2, files) + }.map { (layer1, layer2, _) -> + DependsOnLayerDependencyFailure(layer1, layer2) } - } } - return failedLayerDependencies -} - private fun getFailedDoesNotDependsOnLayers( files: List, layerDependencies: LayerDependenciesCore, ): List { - val failedLayerDependencies = mutableListOf() - - layerDependencies - .doesNotDependsOnDependencies - .forEach { (layer, otherLayers) -> - otherLayers.forEach { otherLayer -> - val dependOnFiles = layer.getDependentOnFiles(otherLayer, files) - - if (dependOnFiles.isNotEmpty()) { - failedLayerDependencies += - DoesNotDependsOnLayerDependencyFailure( - layer, - dependOnFiles, - otherLayer, - ) - } + val forbiddenDependencies = + layerDependencies.doesNotDependsOnDependencies + .groupBy { it.layer1 } + .mapValues { (_, dependencies) -> dependencies.mapNotNull { it.layer2 }.toSet() } + + return forbiddenDependencies.flatMap { (sourceLayer, targetLayers) -> + targetLayers.mapNotNull { targetLayer -> + val dependentFiles = sourceLayer.getDependentOnFiles(targetLayer, files) + + dependentFiles.takeIf { it.isNotEmpty() }?.let { + DoesNotDependsOnLayerDependencyFailure( + sourceLayer, + dependentFiles, + targetLayer, + ) } } - - return failedLayerDependencies + } } private fun getFailedDependsOnNothing( files: List, layerDependencies: LayerDependenciesCore, ): List { - val failedLayerDependencies = mutableListOf() - - layerDependencies - .dependsOnNothingDependencies - .forEach { layer -> - val dependentFiles = layer.getDependentOnAnyLayerFiles(files, layerDependencies) - - if (dependentFiles.isNotEmpty()) { - failedLayerDependencies += - DependsOnNothingDependencyFailure( - layer, - dependentFiles, - ) - } + val isolatedLayers = + layerDependencies.dependsOnNothingDependencies + .map { it.layer1 } + .toSet() + + return isolatedLayers.mapNotNull { layer -> + val dependentFiles = layer.getDependentOnAnyLayerFiles(files, layerDependencies) + + dependentFiles.takeIf { it.isNotEmpty() }?.let { + DependsOnNothingDependencyFailure( + layer, + dependentFiles, + ) } - - return failedLayerDependencies + } } private fun Layer.isDependentOn( diff --git a/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoDeclarationAndProviderAssertCore.kt b/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoDeclarationAndProviderAssertCore.kt index a731e280b9..8cb5551585 100644 --- a/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoDeclarationAndProviderAssertCore.kt +++ b/lib/src/main/kotlin/com/lemonappdev/konsist/core/verify/KoDeclarationAndProviderAssertCore.kt @@ -289,6 +289,7 @@ private fun getFailedNameWithDeclarationType( declarationType: String?, ) = if (name != null) "$declarationType $name" else "$declarationType" +@Suppress("detekt.CyclomaticComplexMethod") private fun getEmptyResult( items: List<*>, additionalMessage: String?, @@ -303,31 +304,63 @@ private fun getEmptyResult( if (isEmpty) { val nullCount = items.count { it == null } val nullValues = - if (nullCount == 1) { - "$nullCount null value" - } else if (nullCount > 1) { - "$nullCount null values" - } else { - "" + when { + nullCount == 1 -> "$nullCount null value" + nullCount > 1 -> "$nullCount null values" + else -> "" } + val otherValues = items.filterNotNull().joinToString(",\n") var text = " It contains " if (nullValues.isNotEmpty()) text += nullValues if (nullValues.isNotEmpty() && otherValues.isNotEmpty()) text += " and " - if (otherValues.isNotEmpty()) text += "values:\n$otherValues" + if (otherValues.isNotEmpty()) text += "values:" + if (nullValues.isNotEmpty() && otherValues.isEmpty()) text += "." - "$text." + text } else { "" } + val customMessage = if (additionalMessage != null) "\n${additionalMessage}\n" else " " - val message = "Assert '$testMethodName' failed.${customMessage}Declaration list is$negation empty.$values" + val getRootMessage = + "Assert '$testMethodName' failed.${customMessage}Declaration list is$negation empty.$values" + + val failedDeclarationAsciiTreeNodes = + items + .filterNotNull() + .mapNotNull { + it + .createErrorOutput() + ?.let { string -> AsciiTreeNode(string, emptyList()) } + } + + val message = + AsciiTreeCreator().invoke( + AsciiTreeNode( + getRootMessage, + failedDeclarationAsciiTreeNodes, + ), + ) throw KoAssertionFailedException(message) } } +private fun E?.createErrorOutput(): String? { + if (this != null) { + val declarationType = getDeclarationType() + val name = (this as? KoNameProvider)?.name + val location = (this as? KoLocationProvider)?.location + val hyperlinkLocation = location?.let { path -> HyperlinkUtil.toHyperlink(path) } + + return "$declarationType $name $hyperlinkLocation" + } + + return null +} + private fun getNullResult( item: Any?, additionalMessage: String?, @@ -338,10 +371,25 @@ private fun getNullResult( if (isNull != itemIsNull) { val negation = if (isNull) " not" else "" - val value = if (isNull) ": " + item.toString() else "" + val value = if (isNull) ": $item" else "" val customMessage = if (additionalMessage != null) "\n${additionalMessage}\n" else " " - val message = "Assert `$testMethodName` failed.${customMessage}Declaration has$negation null value$value." + val getRootMessage = + "Assert `$testMethodName` failed.${customMessage}Declaration has$negation null value$value." + + val failedDeclarationAsciiTreeNode: AsciiTreeNode? = + item.createErrorOutput()?.let { string -> AsciiTreeNode(string, emptyList()) } + + val message = + failedDeclarationAsciiTreeNode?.let { + AsciiTreeCreator().invoke( + AsciiTreeNode( + getRootMessage, + listOf(failedDeclarationAsciiTreeNode), + ), + ) + } ?: getRootMessage + throw KoAssertionFailedException(message) } } diff --git a/lib/src/snippet/kotlin/com/lemonappdev/konsist/GeneralSnippets.ktdoc b/lib/src/snippet/kotlin/com/lemonappdev/konsist/GeneralSnippets.ktdoc index 815e621243..749bff3c22 100644 --- a/lib/src/snippet/kotlin/com/lemonappdev/konsist/GeneralSnippets.ktdoc +++ b/lib/src/snippet/kotlin/com/lemonappdev/konsist/GeneralSnippets.ktdoc @@ -24,7 +24,6 @@ import com.lemonappdev.konsist.api.ext.list.withPackage import com.lemonappdev.konsist.api.ext.provider.hasAnnotationOf import com.lemonappdev.konsist.api.verify.assertFalse import com.lemonappdev.konsist.api.verify.assertTrue -import org.junit.jupiter.api.Test import java.util.Locale import javax.inject.Inject diff --git a/lib/src/test/kotlin/com/lemonappdev/konsist/api/architecture/LayerTest.kt b/lib/src/test/kotlin/com/lemonappdev/konsist/api/architecture/LayerTest.kt index 447c59d538..a3b45c819b 100644 --- a/lib/src/test/kotlin/com/lemonappdev/konsist/api/architecture/LayerTest.kt +++ b/lib/src/test/kotlin/com/lemonappdev/konsist/api/architecture/LayerTest.kt @@ -1,5 +1,6 @@ package com.lemonappdev.konsist.api.architecture +import org.amshove.kluent.shouldNotThrow import org.amshove.kluent.shouldThrow import org.amshove.kluent.withMessage import org.junit.jupiter.api.Test @@ -99,6 +100,17 @@ class LayerTest { "Invalid package definition for layer 'name'. Package can only end with '..'. Current definition: com..example.." } + @Test + fun `create Layer with package starting with two dots should not throw exception`() { + // when + val func = { + Layer("Domain", "..domain..") + } + + // then + func shouldNotThrow IllegalArgumentException::class + } + @Test fun `create Layer with valid package name should not throw exception`() { // given 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 da4406a2f0..9f991294e1 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 @@ -57,14 +57,33 @@ class LayerDependenciesCoreTest { // then dependsOn shouldBeEqualTo - mapOf( - layer1 to setOf(layer2), + setOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer2, + strict = false, + ), ) + doesNotDependOn shouldBeEqualTo - mapOf( - layer2 to setOf(layer3), + listOf( + LayerDependency( + layer1 = layer2, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer3, + strict = false, + ), + ) + + dependsOnNothing shouldBeEqualTo + listOf( + LayerDependency( + layer1 = layer3, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + strict = false, + ), ) - dependsOnNothing shouldBeEqualTo setOf(layer3) } // endregion @@ -95,8 +114,13 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2), + setOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer2, + strict = false, + ), ) } @@ -119,9 +143,19 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2), - layer2 to setOf(layer3), + setOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer2, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } @@ -143,8 +177,19 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2, layer3), + setOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } // endregion @@ -176,8 +221,13 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2), + listOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer2, + strict = false, + ), ) } @@ -200,9 +250,19 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2), - layer2 to setOf(layer3), + listOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer2, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } @@ -224,8 +284,19 @@ class LayerDependenciesCoreTest { // then result shouldBeEqualTo - mapOf( - layer1 to setOf(layer2, layer3), + listOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } // endregion @@ -255,7 +326,14 @@ class LayerDependenciesCoreTest { val result = sut.dependsOnNothingDependencies // then - result shouldBeEqualTo setOf(layer1) + result shouldBeEqualTo + listOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + strict = false, + ), + ) } @Test @@ -275,9 +353,20 @@ class LayerDependenciesCoreTest { val result = sut.dependsOnNothingDependencies // then - result shouldBeEqualTo setOf(layer1, layer2) + result shouldBeEqualTo + listOf( + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + strict = false, + ), + LayerDependency( + layer1 = layer2, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + strict = false, + ), + ) } - // endregion // region dependsOn @@ -387,8 +476,18 @@ class LayerDependenciesCoreTest { // then sut.layerDependencies shouldContainAll setOf( - LayerDependency(layer1, LayerDependencyType.DEPENDS_ON_LAYER, layer2), - LayerDependency(layer1, LayerDependencyType.DEPENDS_ON_LAYER, layer3), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } @@ -459,6 +558,28 @@ class LayerDependenciesCoreTest { "Layer 'name1' is already configured with no dependencies. It cannot subsequently depend on layer 'name2'." } + @Test + fun `dependsOn throws exception for forbidden strict override`() { + // given + val layer1 = Layer("name1", "package1..") + val layer2 = Layer("name2", "package2..") + + justRun { layerValidatorManager.validateLayerDependencies(any()) } + + // when + val func = { + with(sut) { + layer1.dependsOn(layer2, strict = false) + layer1.dependsOn(layer2, strict = true) + } + } + + // then + func shouldThrow KoInvalidAssertArchitectureConfigurationException::class withMessage + "Layer dependency configuration for layer 'name1' is already defined with a strict=false value. " + + "It cannot be overridden with strict=true." + } + // endregion //region doesNotDependOn @@ -516,8 +637,18 @@ class LayerDependenciesCoreTest { // then sut.layerDependencies shouldContainAll setOf( - LayerDependency(layer1, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, layer2), - LayerDependency(layer1, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, layer3), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer2, + strict = false, + ), + LayerDependency( + layer1 = layer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = layer3, + strict = false, + ), ) } @@ -695,7 +826,12 @@ class LayerDependenciesCoreTest { // then sut.layerDependencies shouldContainAll setOf( - LayerDependency(layer, LayerDependencyType.DEPEND_ON_NOTHING, null), + LayerDependency( + layer1 = layer, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + layer2 = null, + strict = false, + ), ) } @@ -819,7 +955,7 @@ class LayerDependenciesCoreTest { } // endregion - // region Collection dependencies + // region Collection extension dependencies @Test fun `collection dependsOn single layer creates dependencies for all layers in collection`() { // given @@ -835,8 +971,20 @@ class LayerDependenciesCoreTest { } // then - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer, + strict = false, + ) } @Test @@ -856,10 +1004,34 @@ class LayerDependenciesCoreTest { } // then - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer1) - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer2) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer1) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DEPENDS_ON_LAYER, targetLayer2) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer1, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer2, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer1, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DEPENDS_ON_LAYER, + layer2 = targetLayer2, + strict = false, + ) } @Test @@ -876,8 +1048,20 @@ class LayerDependenciesCoreTest { } // then - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DEPEND_ON_NOTHING, null) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DEPEND_ON_NOTHING, null) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + layer2 = null, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DEPEND_ON_NOTHING, + layer2 = null, + strict = false, + ) } @Test @@ -915,8 +1099,20 @@ class LayerDependenciesCoreTest { } // then - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer, + strict = false, + ) } @Test @@ -936,10 +1132,34 @@ class LayerDependenciesCoreTest { } // then - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer1) - sut.layerDependencies shouldContain LayerDependency(sourceLayer1, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer2) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer1) - sut.layerDependencies shouldContain LayerDependency(sourceLayer2, LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, targetLayer2) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer1, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer1, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer2, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer1, + strict = false, + ) + sut.layerDependencies shouldContain + LayerDependency( + layer1 = sourceLayer2, + dependencyType = LayerDependencyType.DOES_NOT_DEPEND_ON_LAYER, + layer2 = targetLayer2, + strict = false, + ) } // endregion } diff --git a/samples/starter-projects/android-gradle-groovy-junit-4/konsistTest/build.gradle b/samples/starter-projects/android-gradle-groovy-junit-4/konsistTest/build.gradle index b4466307c8..325b41561b 100644 --- a/samples/starter-projects/android-gradle-groovy-junit-4/konsistTest/build.gradle +++ b/samples/starter-projects/android-gradle-groovy-junit-4/konsistTest/build.gradle @@ -36,7 +36,7 @@ dependencies { // Add JUnit dependency testImplementation 'junit:junit:4.13.2' - testImplementation 'com.lemonappdev:konsist:0.16.1' + testImplementation 'com.lemonappdev:konsist:0.17.0' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' diff --git a/samples/starter-projects/android-gradle-groovy-junit-5/app/build.gradle b/samples/starter-projects/android-gradle-groovy-junit-5/app/build.gradle index dc20b83171..f18a40d162 100644 --- a/samples/starter-projects/android-gradle-groovy-junit-5/app/build.gradle +++ b/samples/starter-projects/android-gradle-groovy-junit-5/app/build.gradle @@ -50,5 +50,5 @@ dependencies { implementation("org.junit.jupiter:junit-jupiter-params:5.11.3") // Add Konsist dependency - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") } diff --git a/samples/starter-projects/android-gradle-groovy-junit-5/konsistTest/build.gradle b/samples/starter-projects/android-gradle-groovy-junit-5/konsistTest/build.gradle index 5edfebae6a..b6be348106 100644 --- a/samples/starter-projects/android-gradle-groovy-junit-5/konsistTest/build.gradle +++ b/samples/starter-projects/android-gradle-groovy-junit-5/konsistTest/build.gradle @@ -39,7 +39,7 @@ dependencies { testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.11.3" // Add Konsist dependency - testImplementation 'com.lemonappdev:konsist:0.16.1' + testImplementation 'com.lemonappdev:konsist:0.17.0' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' diff --git a/samples/starter-projects/android-gradle-groovy-kotest/konsistTest/build.gradle b/samples/starter-projects/android-gradle-groovy-kotest/konsistTest/build.gradle index e5905a365a..03de0f3455 100644 --- a/samples/starter-projects/android-gradle-groovy-kotest/konsistTest/build.gradle +++ b/samples/starter-projects/android-gradle-groovy-kotest/konsistTest/build.gradle @@ -38,6 +38,6 @@ dependencies { testImplementation "io.kotest:kotest-runner-junit5:5.9.1" // Add Konsist dependency - testImplementation 'com.lemonappdev:konsist:0.16.1' + testImplementation 'com.lemonappdev:konsist:0.17.0' } diff --git a/samples/starter-projects/android-gradle-kotlin-junit-4/konsistTest/build.gradle.kts b/samples/starter-projects/android-gradle-kotlin-junit-4/konsistTest/build.gradle.kts index b21a96b020..00b48822d5 100644 --- a/samples/starter-projects/android-gradle-kotlin-junit-4/konsistTest/build.gradle.kts +++ b/samples/starter-projects/android-gradle-kotlin-junit-4/konsistTest/build.gradle.kts @@ -33,5 +33,5 @@ dependencies { testImplementation("junit:junit:4.13.2") // Add Konsist dependency - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") } diff --git a/samples/starter-projects/android-gradle-kotlin-junit-5/konsistTest/build.gradle.kts b/samples/starter-projects/android-gradle-kotlin-junit-5/konsistTest/build.gradle.kts index c336d68af9..d8294bad55 100644 --- a/samples/starter-projects/android-gradle-kotlin-junit-5/konsistTest/build.gradle.kts +++ b/samples/starter-projects/android-gradle-kotlin-junit-5/konsistTest/build.gradle.kts @@ -35,5 +35,5 @@ dependencies { testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.11.3") // Add Konsist dependency - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") } diff --git a/samples/starter-projects/android-gradle-kotlin-kotest/konsistTest/build.gradle.kts b/samples/starter-projects/android-gradle-kotlin-kotest/konsistTest/build.gradle.kts index 9f18993522..86edf70f78 100644 --- a/samples/starter-projects/android-gradle-kotlin-kotest/konsistTest/build.gradle.kts +++ b/samples/starter-projects/android-gradle-kotlin-kotest/konsistTest/build.gradle.kts @@ -34,5 +34,5 @@ dependencies { testImplementation("io.kotest:kotest-runner-junit5:5.9.1") // Add Konsist dependency - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") } diff --git a/samples/starter-projects/kmp-gradle-kotlin-junit5/build.gradle.kts b/samples/starter-projects/kmp-gradle-kotlin-junit5/build.gradle.kts index b6103f52fe..4c6c2bcaac 100644 --- a/samples/starter-projects/kmp-gradle-kotlin-junit5/build.gradle.kts +++ b/samples/starter-projects/kmp-gradle-kotlin-junit5/build.gradle.kts @@ -49,15 +49,15 @@ kotlin { } val jvmTest by getting { dependencies { - implementation("com.lemonappdev:konsist:0.16.1") + implementation("com.lemonappdev:konsist:0.17.0") } } val jsMain by getting { dependencies { - implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.3.1-pre.838") - implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.3.1-pre.838") - implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion:11.13.5-pre.838") + implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.3.1-pre.839") + implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.3.1-pre.839") + implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion:11.13.5-pre.839") } } val jsTest by getting diff --git a/samples/starter-projects/kmp-gradle-kotlin-junit5/konsistTest/build.gradle.kts b/samples/starter-projects/kmp-gradle-kotlin-junit5/konsistTest/build.gradle.kts index 9e4ad4f32b..d0e9a1a0fe 100644 --- a/samples/starter-projects/kmp-gradle-kotlin-junit5/konsistTest/build.gradle.kts +++ b/samples/starter-projects/kmp-gradle-kotlin-junit5/konsistTest/build.gradle.kts @@ -12,6 +12,6 @@ tasks.withType { } dependencies { - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.11.3") } diff --git a/samples/starter-projects/kmp-gradle-kotlin-kotest/build.gradle.kts b/samples/starter-projects/kmp-gradle-kotlin-kotest/build.gradle.kts index 37047852a0..c682982323 100644 --- a/samples/starter-projects/kmp-gradle-kotlin-kotest/build.gradle.kts +++ b/samples/starter-projects/kmp-gradle-kotlin-kotest/build.gradle.kts @@ -51,16 +51,16 @@ kotlin { } val jvmTest by getting { dependencies { - implementation("com.lemonappdev:konsist:0.16.1") + implementation("com.lemonappdev:konsist:0.17.0") implementation("io.kotest:kotest-runner-junit5:5.9.1") } } val jsMain by getting { dependencies { - implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.3.1-pre.838") - implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.3.1-pre.838") - implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion:11.13.5-pre.838") + implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.3.1-pre.839") + implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.3.1-pre.839") + implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion:11.13.5-pre.839") } } val jsTest by getting diff --git a/samples/starter-projects/kmp-gradle-kotlin-kotest/konsistTest/build.gradle.kts b/samples/starter-projects/kmp-gradle-kotlin-kotest/konsistTest/build.gradle.kts index 896a892732..4b0a72db18 100644 --- a/samples/starter-projects/kmp-gradle-kotlin-kotest/konsistTest/build.gradle.kts +++ b/samples/starter-projects/kmp-gradle-kotlin-kotest/konsistTest/build.gradle.kts @@ -11,6 +11,6 @@ tasks.withType { } dependencies { - testImplementation("com.lemonappdev:konsist:0.16.1") + testImplementation("com.lemonappdev:konsist:0.17.0") testImplementation("io.kotest:kotest-runner-junit5:5.9.1") } diff --git a/samples/starter-projects/spring-gradle-groovy-junit-5/build.gradle b/samples/starter-projects/spring-gradle-groovy-junit-5/build.gradle index d6feebf063..479674bea2 100644 --- a/samples/starter-projects/spring-gradle-groovy-junit-5/build.gradle +++ b/samples/starter-projects/spring-gradle-groovy-junit-5/build.gradle @@ -49,7 +49,7 @@ testing { implementation project() // Add Konsist dependency - implementation "com.lemonappdev:konsist:0.16.1" + implementation "com.lemonappdev:konsist:0.17.0" // Add junit-jupiter-params dependency (required for dynamic Tests) implementation "org.junit.jupiter:junit-jupiter-params:5.11.3" diff --git a/samples/starter-projects/spring-gradle-groovy-kotest/build.gradle b/samples/starter-projects/spring-gradle-groovy-kotest/build.gradle index 1cf04130d5..a6399fbc39 100644 --- a/samples/starter-projects/spring-gradle-groovy-kotest/build.gradle +++ b/samples/starter-projects/spring-gradle-groovy-kotest/build.gradle @@ -49,7 +49,7 @@ testing { implementation project() // Add Konsist dependency - implementation "com.lemonappdev:konsist:0.16.1" + implementation "com.lemonappdev:konsist:0.17.0" // Add Kotest dependency implementation "io.kotest:kotest-runner-junit5:5.9.1" diff --git a/samples/starter-projects/spring-gradle-kotlin-junit-5/build.gradle.kts b/samples/starter-projects/spring-gradle-kotlin-junit-5/build.gradle.kts index b13d6bef37..15edc65182 100644 --- a/samples/starter-projects/spring-gradle-kotlin-junit-5/build.gradle.kts +++ b/samples/starter-projects/spring-gradle-kotlin-junit-5/build.gradle.kts @@ -45,7 +45,7 @@ testing { implementation(project()) // Add Konsist dependency - implementation("com.lemonappdev:konsist:0.16.1") + implementation("com.lemonappdev:konsist:0.17.0") // Add junit-jupiter-params dependency (required for dynamic Tests) implementation("org.junit.jupiter:junit-jupiter-params:5.11.3") diff --git a/samples/starter-projects/spring-gradle-kotlin-kotest/build.gradle.kts b/samples/starter-projects/spring-gradle-kotlin-kotest/build.gradle.kts index 5f3c35ab14..9d491fc461 100644 --- a/samples/starter-projects/spring-gradle-kotlin-kotest/build.gradle.kts +++ b/samples/starter-projects/spring-gradle-kotlin-kotest/build.gradle.kts @@ -45,7 +45,7 @@ testing { implementation(project()) // Add Konsist dependency - implementation("com.lemonappdev:konsist:0.16.1") + implementation("com.lemonappdev:konsist:0.17.0") // Add Kotest dependency implementation("io.kotest:kotest-runner-junit5-jvm:5.9.1") diff --git a/samples/starter-projects/spring-maven-junit5/pom.xml b/samples/starter-projects/spring-maven-junit5/pom.xml index fae8e00e3b..eee7da3fa0 100644 --- a/samples/starter-projects/spring-maven-junit5/pom.xml +++ b/samples/starter-projects/spring-maven-junit5/pom.xml @@ -50,7 +50,7 @@ com.lemonappdev konsist - 0.16.1 + 0.17.0 test diff --git a/samples/starter-projects/spring-maven-kotest/pom.xml b/samples/starter-projects/spring-maven-kotest/pom.xml index 18af97d2bf..acceadcc55 100644 --- a/samples/starter-projects/spring-maven-kotest/pom.xml +++ b/samples/starter-projects/spring-maven-kotest/pom.xml @@ -50,7 +50,7 @@ com.lemonappdev konsist - 0.16.1 + 0.17.0 test