diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 792620d7ac..7fa02e9203 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -4,8 +4,6 @@ on: push: branches: [ main ] pull_request: - paths-ignore: - - 'docs/**' types: [ opened, synchronize ] jobs: diff --git a/docs/.gitbook/assets/KonsistTestSourceSet.png b/docs/.gitbook/assets/KonsistTestSourceSet.png deleted file mode 100644 index 35c983df18..0000000000 Binary files a/docs/.gitbook/assets/KonsistTestSourceSet.png and /dev/null differ diff --git a/docs/.gitbook/assets/TestSourceSet.png b/docs/.gitbook/assets/TestSourceSet.png deleted file mode 100644 index 2a15b1681f..0000000000 Binary files a/docs/.gitbook/assets/TestSourceSet.png and /dev/null differ diff --git a/docs/ConfigureKonsist.md b/docs/ConfigureKonsist.md deleted file mode 100644 index 9e1dc073f0..0000000000 --- a/docs/ConfigureKonsist.md +++ /dev/null @@ -1,36 +0,0 @@ -# Configure Konsist - -# Add Dependency To Test Source Set - -`Konsist` can be added to the project using the `test` source set. - -![KonsistSourceSet.png](misc/TestSourceSet.png) - -Add the following dependency to the `module\build.gradle.kts` file: - -```kotlin -dependencies { - testImplementation(KONSIST_DEPENDENCY) -} -``` - -# Create KonsistTest Source Set - -For better test separation a new `konsistTest` source set can be defined using the -[JVM Test Suite Plugin](https://docs.gradle.org/current/userguide/jvm_test_suite_plugin.html). - -![KonsistSourceSet.png](misc/KonsistTestSourceSet.png) - -Add the following `testing` block configuration to the `module\build.gradle.kts` file: - -```kotlin -testing { - suites { - register("konsistTest", JvmTestSuite::class) { - dependencies { - // KONSIST_DEPENDENCY - } - } - } -} -``` diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md deleted file mode 100644 index a997ef95e3..0000000000 --- a/docs/GettingStarted.md +++ /dev/null @@ -1,100 +0,0 @@ -## Getting Started - -Add the following dependency to the `module\build.gradle.kts` file: - -```kotlin -dependencies { - testImplementation(KONSIST_DEPENDENCY) -} -``` - -> Note: Konsist can be configured using custom `konsistTest` source set. See [ConfigureKonsist.md](ConfigureKonsist.md). - -### Usage - -Konsist provides API to query the project Kotlin codebase. It provides -[KoScope](src/main/kotlin/com/lemon/konsist/core/declaration/KoScope.kt) class as entry point for parsing project files. - -At high level Konsist API works as follows: - -```mermaid -flowchart LR - Step1["Define the scope"]-->Step2["Filter scope declarations"] - Step2-->Step3["Perform check"] -``` - -Konsist test are written in form of JUnit tests. Here is an example of a test verifying that all classes annotated with -`RestController` annotation reside in correct package: - - -```kotlin -class ControllerClassKonsistTest { - private val sut = KoScope.fromProject() // 1. Create scope representing the whole project (all Kotlin files in project) - - @Test - fun `classes annotated with 'RestController' annotation should reside in __application__controller__ package`() { - projectScope // 1. Use the scope - .classes() // 2. Get all classes in the project - .filter { it.isAnnotatedWith("RestController") } // 2. Filter classes annotated with 'RestController' - .check { it.resideInPackages("..application..controller..") } // 3. Define the check - } -} -``` - -Scope can be also filtered to retrieve other types of declarations such as interfaces, objects, properties, constructors etc. -See [KoScope](src/main/kotlin/com/lemon/konsist/core/declaration/KoScope.kt). - -## Under The Hood - -Konsist is built on top of [Kotlin Compiler Psi](https://github.com/JetBrains/kotlin/tree/master/compiler/psi/src/org/jetbrains/kotlin/psi). -It wraps Kotlin compiler parser and provides a simple API to access Kotlin code declarations. - -Declarations tree mimics the Kotlin code structure: - -```mermaid ---- -title: Project code base representation ---- - -flowchart TD - KoScope - KoScope---KoFile - KoFile---KoClass - KoFile---KoInterface - KoFile---KoObject - KoFile---Other["..."] - KoClass---KoProperty - KoClass---KoFunction -``` - -To build declaration tree create instance of the [KoScope.md](KoScope.md) class. - -## Project Status - -Project is in early stage. it has been used in production, however there are still some minor features missing and API -is not stable yet. - -Konsist roadmap: - -```mermaid -%%{init: { 'theme': 'forest', 'timeline': {'disableMulticolor': true} , 'themeVariables': { -'cScale0': '#139113', -'cScale1': '#00ff00', -'cScale2': '#0000ff' -} } }%% -timeline - title Konsist Roadmap - Q1 2023 (Canary): Design base APIs - : Core Library developement - Q2 2023 Alpha: Implement features - : Stabilise APIs - : Create documentation - : Implement features - Q3 2023 Beta: Bug fixes - : Polish documentation - : API tinkering (minimal changes) - Q4 2023 (1.0 Release): Release 1.0 - : Wide community driven testing - 2024 (1.x): Implement new Features - : API improvements -``` diff --git a/docs/KoScope.md b/docs/KoScope.md deleted file mode 100644 index 625cba3244..0000000000 --- a/docs/KoScope.md +++ /dev/null @@ -1,157 +0,0 @@ -# KoScope - -The -[KoScope](../src/main/kotlin/com/lemon/konsist/core/declaration/KoScope.kt) class is the entry point. It represents set -of Kotlin files to be verified by Konsist library. Scope can be created for a single Kotlin file, folder, package, module -or entire project. - -Consider this scope: - -```mermaid ---- -title: Project code base representation ---- - -flowchart TD - KoScope - KoScope---KoFile - KoFile---KoClass - KoFile---KoInterface - KoFile---KoObject - KoFile---Other["..."] - KoClass---KoProperty - KoClass---KoFunction -``` - -Scope allows to query available kotlin files to tailor the code base verification. -([KoFile.kt](../src/main/kotlin/com/lemon/konsist/core/declaration/KoFile.kt)), -classes (), - -Scopes should be reused across tests to improve test performance: - -``` -tests/ -├─ data/ -│ ├─ DataTest.kt -├─ app/ -│ ├─ AppTest.kt -├─ MyScope.kt <--- Instance of the KoScope used in both DataTest and AppTest classes. - -``` - -## Scope creation - -The `KoScope` class allows to create scope containing all Kotlin files present in the project: - -```kotlin -KoScope.fromProjectFiles() // All Kotlin files present in the project -KoScope.fromProjectFiles(module = "app") // All Kotlin files present in the "app" module -KoScope.fromProjectFiles(sourceSet = "test") // All Kotlin files present in the "test" source sets -``` - -The `module` and `sourceSet` arguments allows to create more granular scopes. - -### More Granular Scopes - -It is also possible to create more granular scopes to store different subsets of project files e.g. -- scope representing for production code -- scope representing for test code -- scope representing specific application layer -- ... - -Here is an example of creating scopes for production code and test code: - -```kotlin -KoScope.fromProjectTestFiles() // All Kotlin files present test sources sets -KoScope.fromProjectProductionFiles() // All Kotlin files present production sources sets -``` - -Here is an example of creating scope for all files stored in `usecase` package: - -```kotlin -val myScope = KoScope.fromPackage("..usecase..") -``` - -> You can read more about package selector in [PackageSelector.md](PackageSelector.md). - -Here is an example of creating scope for all files stored in `domain` folder`: - -```kotlin -val myScope = KoScope.fromPath("/domain") -``` - -It is also possible to create scope from a single file: - -```kotlin -val myScope = KoScope.fromFile("/domain/UseCase.kt") -``` - -For even more granular control you can use `KoScope.slice` method to retrieve a scope containing subset of files -from the scope: - -```kotlin -// scope containing all files in "test" folder -koScope.slice { it.relativePath.contains("/test/") } - -// scope containing all files in "com.domain.usecase" package -koScope.slice { it.hasImport("com.domain.usecase") } - -// scope containing all files in "usecase" package and its subpackages -koScope.slice { it.hasImport("usecase..") } -``` - -The `KoScope` can be printed to display list of all files present in the scope. Here is an example: - -```kotlin -println(koScope) -``` - -## Filtering Declarations - -The `KoScope` class provides a set of methods to access Kotlin declarations. Each method returns a list representing a -subset declarations of the original scope: -- `files()` - returns all files present in the scope -- `classes()` - returns all classes present in the scope -- `interfaces()` - returns all interfaces present in the scope -- `objects()` - returns all objects present in the scope -- `functions()` - returns all functions present in the scope -- `properties()` - returns all properties present in the scope -- `companionObjects()` - returns all companion objects present in the scope -- `declarations()` - returns all declarations present in the scope - -Here is an example of retrieving all classes present in the scope: - -```kotlin -@Test - fun `every BaseUseCase child class has UseCase suffix`() { - scope - .classes() - .filter { it.parentClass == "BaseUseCase" } - .check { it.name.endsWith("UseCase") } - } -``` - -Here is an example of retrieving all properties defined in classes and verifying that they are not annotated with -`Inject` annotation: - -```kotlin -@Test - fun `no classes should use field injection`() { - mangoScope - .classes() - .flatMap { it.properties() } - .checkNot { it.hasAnnotation(Inject::class) } - } -``` - -## Scope composition - -It is possible to compose scopes using Kotlin operators: - -```kotlin -// add scopes -val allKoScope = productionScope + testScope - -// subtract scopes -val outerLayersScope = allLayersScope - domainLayerScope -``` diff --git a/docs/PackageSelector.md b/docs/PackageSelector.md deleted file mode 100644 index 90cf708b0e..0000000000 --- a/docs/PackageSelector.md +++ /dev/null @@ -1,5 +0,0 @@ -# PackageSelector - -Package selector is used to filer and verify Kotlin files by given package. - -The two dots (`..`) means any number of packages including zero. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index c9dc7faefd..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# What is Konsist? - -Konsist is a library that helps to guard [Kotlin](https://kotlinlang.org/) codebase consistency. It facilitates standardization of the Kotlin codebase by enforcing coding conventions and guarding project architecture. - -At high-level Konsist can: - -* verify if classes reside in correct packages -* verify if classes reside in correct packages - - - -Example checks: - -* Check if all repository classes are reside in repository package -* Check if every use case has one public function -* Check if class is not using forbidden dependencies -* Check if `Controller` class is annotated with `@Controller` Annotation -* Check if use case has one public function -* Check if no classes are using Java util logging -* and much more… see sample checks - - - -Konsist tests are written in Kotlin. Here is a simple test that verifies if every use case class resides in `usecase` package: - -```kotlin -@Test -fun `every use case must reside in use case package`() { - KoScope - .fromProject() // Define scope using all Kotlin files present in the project - .classes() // Map to list of classes - .withNameSuffix("UseCase") // Filter classes heaving name ending with 'UseCase' - .assert { it.resideInPackages("..usecase..") } // Assert use case -} -``` - -Konsist works with any test framework that executes Kotlin code such as [JUni4](https://junit.org/junit4/) and [JUnit5](https://junit.org/junit5/). - - - -Take a look at the [gettingstarted.md](getting-started/gettingstarted.md "mention") page to learn how to set up Konsist or go straight to the [Broken link](broken-reference "mention") section to review more examples. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md deleted file mode 100644 index d7cb83954a..0000000000 --- a/docs/SUMMARY.md +++ /dev/null @@ -1,38 +0,0 @@ -# Table of contents - -## 🚀 GETTING STARTED - -* [What is Konsist?](README.md) -* [Getting Started](getting-started/gettingstarted.md) -* [Add Custom Test Directory](getting-started/configurekonsist.md) -* [PR Check](getting-started/pr-check.md) -* [Project Status](getting-started/gettingstarted-1.md) -* [Under The Hood](getting-started/under-the-hood.md) -* [Changelog](getting-started/changelog.md) -* [Why there are no pre-defined rules?](getting-started/why-there-are-no-pre-defined-rules.md) - -## WRITING TESTS - -* [Introduction](writing-tests/introduction.md) - -## 📗 FEATURES - -* [Declaration](features/declaration.md) -* [Scope](features/koscope.md) -* [Declaration Quering And Filtering](features/declaration-quering-and-filtering.md) -* [Assert](features/assert.md) -* [Package Selector](features/packageselector.md) - -## 🔍 INSPIRATION - -* [Samples](inspiration/samples/README.md) - * [General](inspiration/samples/general.md) - * [Android](inspiration/samples/android.md) - * [Spring](inspiration/samples/spring.md) - -## ❓ HELP - -* [Sending us Feedback](help/sending-us-feedback.md) -* [Contributing](help/contributing.md) -* [Contributors](help/contributors.md) -* [Open Source Licenses](help/open-source-licenses.md) diff --git a/docs/WhatIsKonsist.md b/docs/WhatIsKonsist.md deleted file mode 100644 index a2cb71a5d8..0000000000 --- a/docs/WhatIsKonsist.md +++ /dev/null @@ -1,4 +0,0 @@ -# What is Konsist? - -Konsist helps to guard [Kotlin](https://kotlinlang.org/) project consistency. It allows to standardise Kotlin codebase -and enforce coding conventions tailored for given project. diff --git a/docs/features/assert.md b/docs/features/assert.md deleted file mode 100644 index bd08ae0c2d..0000000000 --- a/docs/features/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -description: Verify codebase ---- - -# Assert - -Assertions are used to perform code base verification. It is the final step of Konsist verification preceded by scope retrieval ([koscope.md](koscope.md "mention")) and [declaration-quering-and-filtering.md](declaration-quering-and-filtering.md "mention") steps: - -```mermaid -flowchart TB - Step1["1. Retrieve The Scope"]-->Step2 - Step2["2. Query and Filter The Declarations"]-->Step3 - Step3["3. Assert"] - style Step3 fill:#bbf,stroke:#666,stroke-width:2px,color:#fff -``` - -## Assert - -In the below snippet, the assertion (performed on the list of interfaces) verifies if every interface has a `public` visibility modifier. - -```kotlin -scope - .interfaces() - .assert { it.hasPublicModifier() } -``` - -The `it` parameter inside the `assert` the method represents a single declaration (single interface in this case), however, the assertion itself will be performed on every available interface. - -## Assert Not - -The `assertNot` is a negation of the `assert` method. In the below snippet, the assertion (performed on the list of properties) verifies if none of the properties has the `Inject` annotation: - -```kotlin -scope - .classes() - .flatMap { it.properties() } - .assertNot { it.hasAnnotation() } -``` - -## Exceptions Thrown - -The `assert` and `assertNot`methods throw: - -* `KoCheckFailedException` if the assertion criteria are not met. The error message contains a descriptive location, pointing to the exact spot in the codebase -* `KoPreconditionFailedException` if the assertion is performed on an empty list diff --git a/docs/features/declaration-quering-and-filtering.md b/docs/features/declaration-quering-and-filtering.md deleted file mode 100644 index 68d952bf4c..0000000000 --- a/docs/features/declaration-quering-and-filtering.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -description: Query and filter declarations using custom criteria ---- - -# Declaration Quering And Filtering - -## Declaration Querying - -Declaration querying is performed to retrieve declarations of a given type. It is the middle step of Konsist config preceded by scope retrieval ([koscope.md](koscope.md "mention")) and followed by verification ([assert.md](assert.md "mention")) step. - -```mermaid -flowchart TB - Step1["1. Retrieve The Scope"]-->Step2 - Step2["2. Query and Filter The Declarations"]-->Step3 - Step3["3. Assert"] - style Step2 fill:#bbf,stroke:#666,stroke-width:2px,color:#fff -``` - -Every [koscope.md](koscope.md "mention") contains a set of declarations ([declaration.md](declaration.md "mention")) such as classes (`KoClass`), properties (`KoProperty`), functions (`KoFunction`), etc. The `KoScope` class provides a set of methods to access Kotlin declarations. Each method returns a list representing a declaration subset: - -| | | -| -------------------- | -------------------------------------------------- | -| Method | Description | -| `files()` | returns all files present in the scope | -| `packages()` | returns all packages present in the scope | -| `imports()` | returns all imports present in the scope | -| `classes()` | returns all classes present in the scope | -| `interfaces()` | returns all interfaces present in the scope | -| `objects()` | returns all objects present in the scope | -| `functions()` | returns all functions present in the scope | -| `properties()` | returns all properties present in the scope | -| `companionObjects()` | returns all companion objects present in the scope | -| `typeAliases()` | returns all type aliases present in the scope | -| `declarations()` | returns all declarations present in the scope | - -To get all classes from the given scope use `KoScope.classes()` method: - -```kotlin -koScope - .classes() - -``` - -Here is an example of querying all properties defined inside classes: - -```kotlin - koScope - .classes() - .properties() - .assert { // .. } -``` - -## Declaration Filtering - -More granular filtering can be applied to additionally filter classes annotated with certain attributes like classes annotated with `RestController` annotation: - -```kotlin -koScope - .classes() - .withAnnotation -``` - -Konsist is compatible with [Kotlin Collection processing](https://kotlinlang.org/docs/collections-overview.html#list) API, so the `filter` the method can be used to additionally filter the content of the `Sequence`: Here filter return classes annotated with `UseCase` annotation: - -```kotlin -koScope - .classes() - .filter { it.hasAnnotation() } - .assert { // .. } -``` - -Konsist provides a set of `with...` extensions to simplify the syntax. The below snippet is an improved version of the above snippet: - -```kotlin -koScope - .classes() - .withParentClass() - .assert { // .. } -``` - -Multiple conditions can be applied to perform more specific filtering. The below snippet filters classes with the `BaseUseCase` parent class that reside in the `usecase` package: - -```kotlin -koScope - .classes() - .withParentClass() - .resideInPackage("..usecase") - .assert { // .. } -``` - -## Declaration Queuing And Filtering - -Queuing and filtering stages can be mixed together to perform more specific checks. The below snippet filters classes reside in the `controller` package, retrieves all properties and filter properties with `Inject` annotation: - -```kotlin -koScope - .classes() // query all classes - .resideInPackage("..controller") // filter classes in 'controller' package - .properties() // query all properties - .withAnnotation() // filter classes in 'controller' package - .assert { // .. } -``` - -## Print Declarations - -To help with debugging Konsist provides `printDeclarations` method that prints all declarations. This method helps to make sure that verification is performed on the correct list of declarations. - -```kotlin -scope - .classes() - .flatMap { it.properties() } - .printDeclarations( -``` diff --git a/docs/features/declaration.md b/docs/features/declaration.md deleted file mode 100644 index 4c7b92eb35..0000000000 --- a/docs/features/declaration.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -description: What is declaration? ---- - -# Declaration - -The declaration represents a code entity, a piece of Kotlin code. Every parsed Kotlin File (`KoFile`) (usually) contains multiple declarations. The declaration can be a package (`KoPackage`), property (`KoProperty`), annotation (`KoAnnotation`), class (`KoClass`), etc. - -{% hint style="info" %} - -{% endhint %} - -Consider this Kotlin code snippet from \~/`project/User.kt` file: - -```kotlin -private const val logLevel = "debug" - -@Entity -open class Logger(val level: String) { - fun log(message: String) { - - } -} -``` - -Declarations contained by the scope ([koscope.md](koscope.md "mention")) are mimicking the Kotlin file structure. The above snippet contains two top-level declarations - property declaration (`KoProperty`) and class declaration (`KoClass`). The `Logger` the class declaration contains a single function (`KoFunction` ) declaration. - -Each declaration contains a set of properties to facilitate filtering and verification eg. `KoClass` declaration has `name`, `modifiers` , `annotations` , `declarations` (containing `KoFunction`) etc. - -## Additional properties - -Every declaration has a few additional properties: - -* `text` - provides declaration text eg. `val property role = "Developer"` -* `location` - provides file path with file name, line, and column e.g. `~\Dev\IdeaProject\Konsist\lib\src\kotlin\com\konsist\core\KoScope:10:5` -* `textWithLocation` - provides `location` together with declaration `text` - diff --git a/docs/features/koscope.md b/docs/features/koscope.md deleted file mode 100644 index 0fb008162a..0000000000 --- a/docs/features/koscope.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -description: Access the Kotlin files ---- - -# Scope - -The [KoScope](https://github.com/LemonAppDev/konsist/blob/main/src/main/kotlin/com/lemon/konsist/core/declaration/KoScope.kt) class is the entry point to the Konsist library. It is the first step in defining the Konsist test. Scope represents a set of Kotlin files to be further queried, filtered ([declaration-quering-and-filtering.md](declaration-quering-and-filtering.md "mention")) and verified ([assert.md](assert.md "mention")). - -```mermaid -flowchart TB - Step1["1. Retrieve The Scope"]-->Step2 - Step2["2. Query and Filter The Declarations"]-->Step3 - Step3["3. Assert"] - style Step1 fill:#bbf,stroke:#666,stroke-width:2px,color:#fff -``` - -Every scope consists set of declarations ([declaration.md](declaration.md "mention")). The scope can be created for a single Kotlin file, folder, package, module, or entire project. - -Consider this scope: - -```mermaid ---- -title: Kotlin code base representation ---- - -flowchart TD - KoScope - KoScope---KoFile - KoFile---KoClass - KoFile---KoInterface - KoFile---KoObject - KoFile---Other["..."] - KoClass---KoProperty - KoClass---KoFunction -``` - -## Scope Creation - -The `KoScope` class allows creating scope containing all Kotlin files present in the project: - -```kotlin -KoScope.fromProjectFiles() // All Kotlin files present in the project -KoScope.fromProjectFiles(module = "app") // All Kotlin files present in the "app" module -KoScope.fromProjectFiles(sourceSet = "test") // All Kotlin files present in the "test" source sets -``` - -The `module` and `sourceSet` arguments allow to create of more granular scopes. - -### More Granular Scopes - -More granular scopes such as module scope or package scope can be defined to store different subsets of project files e.g. - -* scope representing production code -* scope representing for test code -* scope representing specific application layer -* ... - -Here is an example of creating scopes for production code and test code: - -```kotlin -KoScope.fromProjectTestFiles() // All Kotlin files present test source sets -KoScope.fromProjectProductionFiles() // All Kotlin files present production source sets -``` - -Here is an example of creating scope for all files stored in `usecase` package: - -```kotlin -val myScope = KoScope.fromPackage("..usecase..") -``` - -> You can read more about package selector in [PackageSelector.md](packageselector.md). - -Here is an example of creating scope for all files stored in `domain` folder\`: - -```kotlin -val myScope = KoScope.fromPath("/domain") -``` - -It is also possible to create scope from a single file: - -```kotlin -val myScope = KoScope.fromFile("/domain/UseCase.kt") -``` - -For even more granular control you can use the `KoScope.slice` method to retrieve a scope containing a subset of files from the scope: - -```kotlin -// scope containing all files in the 'test' folder -koScope.slice { it.relativePath.contains("/test/") } - -// scope containing all files in 'com.domain.usecase' package -koScope.slice { it.hasImport("com.domain.usecase") } - -// scope containing all files in 'usecase' package and its sub-packages -koScope.slice { it.hasImport("usecase..") } -``` - -The `KoScope` can be printed to display a list of all files present in the scope. Here is an example: - -```kotlin -println(koScope) -``` - -## Scope Reuse - -Scopes should be reused across tests to improve test performance. Avoid creating scope for every individual test: - -
// Test.kt
-class DataTest {
-    @Test
-    fun `test 1`() {
-        KoScope
-            .fromProject() // Create a new KoScope
-            .classes()
-            .assert { // .. } 
-    }
-
-    fun `test 2`() {
-        KoScope
-            .fromProject() // Create a new KoScope
-            .classes()
-            .assert { // .. } 
-    }
-}
-
- -It is advised to share scope instances as much as possible. One way would be to create the instance in object and access it from multiple tests: - -```kotlin -// DataTest.kt -class DataTest { - @Test - fun `test 1`() { - projectScope - .classes() - .assert { // .. } - } - - fun `test 2`() { - projectScope - .interfaces() - .assert { // .. } - } -} - -// AppTest.kt -class AppTest { - @Test - fun `test 1`() { - projectScope - .objects() - .assert { // .. } - } -} - -// ScopeProvider.kt -object { - val projectScope = KoScope.fromProject() // Create a new KoScope -} -``` - -Here is the file structure representing the above snippet: - -``` -tests/ -├─ data/ -│ ├─ DataTest.kt -├─ app/ -│ ├─ AppTest.kt -├─ ScopeProvider.kt <--- Instance of the KoScope used in both DataTest and AppTest classes. -``` - -## Scope Composition - -It is possible to compose scopes using Kotlin operators: - -```kotlin -// add scopes -val allKoScope = productionScope + testScope - -// subtract scopes -val outerLayersScope = allLayersScope - domainLayerScope -``` - -## Access Specific Declarations - -To access specific declaration types such as interfaces, classes, constructors, functions etc. utilize the [declaration-quering-and-filtering.md](declaration-quering-and-filtering.md "mention"). diff --git a/docs/features/packageselector.md b/docs/features/packageselector.md deleted file mode 100644 index 182742892c..0000000000 --- a/docs/features/packageselector.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: Select packages ---- - -# Package Selector - -Package selector is used to filer and verify Kotlin files by given package. - -The two dots (`..`) means any number of packages including zero. diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md deleted file mode 100644 index 4dc68c6ff8..0000000000 --- a/docs/getting-started/changelog.md +++ /dev/null @@ -1,2 +0,0 @@ -# Changelog - diff --git a/docs/getting-started/configurekonsist.md b/docs/getting-started/configurekonsist.md deleted file mode 100644 index 1223372f5d..0000000000 --- a/docs/getting-started/configurekonsist.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -description: Aim for better test separation. ---- - -# Add Custom Test Directory - -The `konsist` library can be added to the project by adding the dependency on the existing `test` source set (see [gettingstarted.md](gettingstarted.md "mention")). - -![test sorce directory](../.gitbook/assets/TestSourceSet.png) - -As the project grows it is desirable to isolate each type of test e.g. isolate unit tests from Konsist tests. To organize tests a new supplemental test source directory `konsistTest` can be defined. - -![konsistTest sorce directory](../.gitbook/assets/KonsistTestSourceSet.png) - -## Add Test Source Directory - -This section demonstrates how to add the `konsistTest` test source directory inside the `app` module. This test directory will have `kotlin` folder containing Kotlin code. - -{% tabs %} -{% tab title="Gradle (Kotlin)" %} -Use the Gradle built-in [JVM Test Suite plugin](https://docs.gradle.org/current/userguide/jvm\_test\_suite\_plugin.html) to define the `konsistTest` source set. Add a `testing` block to the project configuration: - -```kotlin -// app/build.gradle.kts - -plugins { - java - `jvm-test-suite` -} - -testing { - suites { - register("konsistTest", JvmTestSuite::class) { - dependencies { - // Add 'main' source set dependency - implementation(project()) - - // Add Konsist dependency - implementation("com.lemonappdev:konsist:0.7.4") - } - } - } -} - -// Add optionally to run Konsist tests with the Gradle 'check' task -tasks.named("check") { - dependsOn(testing.suites.named("integrationTest")) -} -``` -{% endtab %} - -{% tab title="Gradle" %} -Use the Gradle built-in [JVM Test Suite plugin](https://docs.gradle.org/current/userguide/jvm\_test\_suite\_plugin.html) to define the `konsistTest` source set. Add a `testing` block to the project configuration: - -```kotlin -// app/build.gradle - -plugins { - id 'java' - id 'jvm-test-suite' -} - -testing { - suites { - test { - useJUnitJupiter() - } - - integrationTest(JvmTestSuite) { - dependencies { - // Add 'main' source set dependency - implementation project() - - // Add Konsist dependency - implementation "com.lemonappdev:konsist:0.7.4" - } - - targets { - all { - testTask.configure { - shouldRunAfter(test) - } - } - } - } - } -} - -// Add optionally to run Konsist tests with the Gradle 'check' task -tasks.named('check') { - dependsOn(testing.suites.integrationTest) -} -``` -{% endtab %} - -{% tab title="Maven" %} -Use the [Maven build helper plugin](https://github.com/mojohaus/build-helper-maven-plugin) to define the `konsistTest` test source directory. Add plugin config to the project configuration: - -````xml -// app/pom.xml - - - org.codehaus.mojo - build-helper-maven-plugin - 3.3.0 - - - add-konsist-test-source - generate-test-sources - - add-test-source - - - - src/konsistTest/kotlin - - - - - -``` -```` -{% endtab %} -{% endtabs %} - - Create `app/src/konsistTest/kotlin` folder and reload the project. The IDE will present a new `konsistTest` source set in the `app` module. - -

konsistTest sorce directory

- -The `konsistTest` test source folder works exactly like build-in `test` source folder, so Kosist tests can be defined and executed in a similar way: - -{% tabs %} -{% tab title="Gradle" %} -``` - ./gradlew app:konsistTest -``` -{% endtab %} - -{% tab title="Maven" %} - -{% endtab %} -{% endtabs %} diff --git a/docs/getting-started/gettingstarted-1.md b/docs/getting-started/gettingstarted-1.md deleted file mode 100644 index 17ec305e56..0000000000 --- a/docs/getting-started/gettingstarted-1.md +++ /dev/null @@ -1,28 +0,0 @@ -# Project Status - -The project is in the early stage. It has been used in production, however, there are still some minor features missing and API is not stable yet. - -Konsist roadmap: - -```mermaid -%%{init: { 'theme': 'forest', 'timeline': {'disableMulticolor': true} , 'themeVariables': { -'cScale0': '#139113', -'cScale1': '#00ff00', -'cScale2': '#0000ff' -} } }%% -timeline - title Konsist Roadmap - Q1 2023 (Canary): Design base APIs - : Core Library developement - Q2 2023 Alpha: Implement features - : Stabilise APIs - : Create documentation - : Implement features - Q3 2023 Beta: Bug fixes - : Polish documentation - : API tinkering (minimal changes) - Q4 2023 (1.0 Release): Release 1.0 - : Wide community driven testing - 2024 (1.x): Implement new Features - : API improvements -``` diff --git a/docs/getting-started/gettingstarted.md b/docs/getting-started/gettingstarted.md deleted file mode 100644 index 85ac68f661..0000000000 --- a/docs/getting-started/gettingstarted.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -description: Quickly configure Konsist and run the first test. ---- - -# Getting Started - -Add Dependency - -### Add Repository - -Add `mavenCentral` repository: - -``` -repositories { - mavenCentral() -} -``` - -### Add Konsist Dependency - -To use Konsist, include the Konsist dependency from Maven Central: - -{% tabs %} -{% tab title="Gradle (Kotlin)" %} -Add the following dependency to the `module\build.gradle.kts` file: - -```kotlin -dependencies { - testImplementation(KONSIST_DEPENDENCY) -} -``` -{% endtab %} - -{% tab title="Gradle (Groovy)" %} -Add the following dependency to the `module\build.gradle` file: - -```groovy -dependencies { - implementation "com.lemonappdev:konsist:0.7.4" -} -``` -{% endtab %} - -{% tab title="Maven" %} -Add the following dependency to the `module\pom.xml` file: - -```xml - - com.lemonappdev - konsist - 0.7.4 - -``` -{% endtab %} - -{% tab title="More" %} -Dependency can be added to other build systems as well. Check the [snippets](https://central.sonatype.com/artifact/com.lemonappdev/konsist) section in the sonatype repository. -{% endtab %} -{% endtabs %} - -> Note: To achieve better test separation Konsist can be configured using dedicated `konsistTest` source set. See [configurekonsist.md](configurekonsist.md "mention"). - -## Usage - -At a high-level Konsist check is a Unit test that works as follows few steps: - -```mermaid -flowchart TB - Step1["1. Retrieve The Scope"]-->Step2 - Step2["2. Query and Filter The Declarations"]-->Step3 - Step3["3. Assert"] -``` - -Let's write a simple test to verify that classes annotated with the `RestController` annotation resides in `controller` package. - -### Step 1 - Get The Scope - -The first step is to get a list of Kotlin files to be verified. The `fromProject` the method can be used to obtain the instance of the scope containing all Kotlin project files: - -```kotlin -KoScope.fromProject() -``` - -{% hint style="info" %} -To define more granular scopes see the [koscope.md](../features/koscope.md "mention") page. -{% endhint %} - -### Step 2 - Query and Filter Declarations - -The next step is to access all of the classes present in the scope: - -```kotlin -KoScope.fromProject() - .classes() - -``` - -Perform additional filtering to get classes annotated with `RestController` annotation: - -```kotlin -KoScope.fromProject() - .classes() - .withAnnotation -``` - -{% hint style="info" %} -To perform more advanced quering and filtering see the [declaration-quering-and-filtering.md](../features/declaration-quering-and-filtering.md "mention")page. -{% endhint %} - -### Step 3 - Assert - -The final step is to perform code base verification - use `assert` combined with `koClass.resideInPackage` method to make sure that all classes (filtered in the previous step) reside in `controlelr` package: - -```kotlin -KoScope.fromProject() - .classes() - .withAnnotation - .assert { it.resideInPackage("..controller") } -``` - -{% hint style="info" %} -To learn more about assertions see [assert.md](../features/assert.md "mention") page. -{% endhint %} - -{% hint style="info" %} -The `..` means "controller package preceded by any number of packages" (see[packageselector.md](../features/packageselector.md "mention") syntax). -{% endhint %} - -### Wrap Konsist Code In Test - -The above code captures logic that should be guarded in the project. To verify this logic (and ideally run it with every [Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)) it must be executed as a unit test: - -```kotlin -class ControllerClassKonsistTest { - @Test - fun `classes annotated with 'RestController' annotation reside in 'controller' package`() { - KoScope.fromProject() // 1. Create a scope representing the whole project (all Kotlin files in project) - .classes() // 2. Get all classes in the project - .withAnnotation // 2. Filter classes annotated with 'RestController' - .assert { it.resideInPackage("..controller..") } // 3. Define the assertion - } -} -``` - -The above snippet presents a complete example of a test verifying that all classes annotated with `RestController` annotation resides in the `controler` package. - -{% hint style="info" %} -This test is written using [JUnit](https://junit.org/) testing framework, however, Konsist is a test framework agonistic, so any test framework can be used. -{% endhint %} - -{% hint style="info" %} -ssa #reus -{% endhint %} - -For more tests check the samples in the [Broken link](broken-reference "mention") section. - diff --git a/docs/getting-started/pr-check.md b/docs/getting-started/pr-check.md deleted file mode 100644 index 1c29c5d6f9..0000000000 --- a/docs/getting-started/pr-check.md +++ /dev/null @@ -1,36 +0,0 @@ -# PR Check - -Konsist is intended to run as a PR-level check. - -## GitHub Actions - -Here is a sample [GitHub Actions](https://docs.github.com/en/actions) workflow that will run - -``` -# .github/workflows/check.yml - -name: Check - -on: - push: - branches: [ main ] - pull_request: - types: [ opened, synchronize ] - - konsist-test: - name: Konsist Test - strategy: - fail-fast: false - steps: - - name: checkout - uses: actions/checkout@v3 - - - name: Set up JDK - uses: actions/setup-java@v3 - with: - java-version: 19 - distribution: 'zulu' - - - name: Konsist Test - run: ./gradlew app:konsistTest -``` diff --git a/docs/getting-started/under-the-hood.md b/docs/getting-started/under-the-hood.md deleted file mode 100644 index 9307b515a1..0000000000 --- a/docs/getting-started/under-the-hood.md +++ /dev/null @@ -1,23 +0,0 @@ -# Under The Hood - -Konsist is built on top of [Kotlin Compiler Psi](https://github.com/JetBrains/kotlin/tree/master/compiler/psi/src/org/jetbrains/kotlin/psi). It wraps the Kotlin compiler parser and provides a simple API to access Kotlin code declarations. - -[declaration.md](../features/declaration.md "mention") tree mimics the Kotlin code structure: - -```mermaid ---- -title: Project code base representation ---- - -flowchart TD - KoScope - KoScope---KoFile - KoFile---KoClass - KoFile---KoInterface - KoFile---KoObject - KoFile---Other["..."] - KoClass---KoProperty - KoClass---KoFunction -``` - -To build a declaration tree create an instance of the [KoScope.md](https://github.com/LemonAppDev/konsist/blob/main/docs/KoScope.md) class. diff --git a/docs/getting-started/why-there-are-no-pre-defined-rules.md b/docs/getting-started/why-there-are-no-pre-defined-rules.md deleted file mode 100644 index 9754022afa..0000000000 --- a/docs/getting-started/why-there-are-no-pre-defined-rules.md +++ /dev/null @@ -1,24 +0,0 @@ -# Why there are no pre-defined rules? - -Many linters including [Detekt](https://github.com/detekt/detekt) and [ktlint](https://github.com/pinterest/ktlint) have a predefined set of rules. These rules are derived and aligned with guidelines or common practices for writing high-quality code and industry coding conventions ([Kotlin coding conventions](https://kotlinlang.org/docs/coding-conventions.html), [Android Kotlin style guide](https://developer.android.com/kotlin/style-guide), etc.). - -However, there are no industry standards when comes to application architecture. Every code base is different - different class naming, different package structures, different application layers, etc. As the project grows code base evolves as well - it tends to have more layers, more modules, and a more complex code structure. These "rules" are hard to capture by generic linter, because they are specific to the given project. - -Let's consider a use case - a concept defined by the [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html). At a high-level the use case definition is quite simple - "use case holds a business logic". How the use case is actually represented in the code base? Well... In one project this may be a class that has a name ending with `UseCase`, in another, it may be a class extending `BaseUseCase` and in another class annotated with `@UseCase` annotation. The logic for filtering "all project use cases" will vary from project to project. - -Now let's consider the actual structure of the use case class: - -* should every use case have `UseCase` a suffix in the class name? -* can the use case be extended or include another use case? -* should every use case reside in `usecase` the package? -* should the use case have a single method? -* how this method should be named? -* can this method have overloads or should it be defined as `invoke` an operator? -* should this method have a `suspended` modifier? -* … - -Every single one of the above questions can be answered differently in different projects. That is why Konsist favors a more flexible approach - it allows filtering members and defining custom code base assertions (tests). On top of that Konsist is utilizing Kotlin collection processing API to provide more control over filtering and asserting declarations ([declaration.md](../features/declaration.md "mention")). - -{% hint style="info" %} -Some things can be standardized across different projects e.g. constructor parameter names being derived from the property name, or alphabetic the order of the parameter. At some point, Konsist may be extended to provide a small set of predefined rules out of the box. -{% endhint %} diff --git a/docs/help/contribute.md b/docs/help/contribute.md deleted file mode 100644 index 7b29cfef30..0000000000 --- a/docs/help/contribute.md +++ /dev/null @@ -1,2 +0,0 @@ -# Contribute - diff --git a/docs/help/contributing.md b/docs/help/contributing.md deleted file mode 100644 index 7b29cfef30..0000000000 --- a/docs/help/contributing.md +++ /dev/null @@ -1,2 +0,0 @@ -# Contribute - diff --git a/docs/help/contributors.md b/docs/help/contributors.md deleted file mode 100644 index 9f3085ec40..0000000000 --- a/docs/help/contributors.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributors - -Browse the [current list of contributors](https://github.com/LemonAppDev/konsist/graphs/contributors) directly on GitHub. diff --git a/docs/help/open-source-licenses.md b/docs/help/open-source-licenses.md deleted file mode 100644 index 0341aee642..0000000000 --- a/docs/help/open-source-licenses.md +++ /dev/null @@ -1,13 +0,0 @@ -# Open Source Licenses - -| Name | Licence | Page | -| ------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| Kotlin | Apache-2.0 | [https://github.com/JetBrains/kotlin](https://github.com/JetBrains/kotlin) | -| Mockk | Apache-2.0 | [https://markusamshove.github.io/Kluent/](https://markusamshove.github.io/Kluent/) | -| Kluent | MIT license | [https://markusamshove.github.io/Kluent/](https://markusamshove.github.io/Kluent/) | -| Spotless | Apache-2.0 | [https://github.com/diffplug/spotless](https://github.com/diffplug/spotless) | -| Detekt | Apache-2.0 | [https://github.com/detekt/detekt](https://github.com/detekt/detekt) | -| Gradle Test Logger Plugin | Apache-2.0 | [https://github.com/radarsh/gradle-test-logger-plugin](https://github.com/radarsh/gradle-test-logger-plugin) | -| JUnit | Eclipse Public License - v 2.0 | [https://junit.org/junit5/](https://junit.org/junit5/) | -| Gradle | Apache-2.0 | [https://gradle.org/](https://gradle.org/) | - diff --git a/docs/help/sending-us-feedback.md b/docs/help/sending-us-feedback.md deleted file mode 100644 index f306ca8ac6..0000000000 --- a/docs/help/sending-us-feedback.md +++ /dev/null @@ -1,2 +0,0 @@ -# Sending us Feedback - diff --git a/docs/inspiration/samples/README.md b/docs/inspiration/samples/README.md deleted file mode 100644 index c242e5cbf3..0000000000 --- a/docs/inspiration/samples/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Samples - -In konsist all rules are tailored for a given project. - -As the project grows additional rules can be defined to enforce various checks eg. layer boundaries, package structure, class naming, and more. diff --git a/docs/inspiration/samples/android.md b/docs/inspiration/samples/android.md deleted file mode 100644 index 922b190e5c..0000000000 --- a/docs/inspiration/samples/android.md +++ /dev/null @@ -1,3 +0,0 @@ -# Android - -Konsist can be used to guard the consistency of the [Android](https://www.android.com/) project. Take a look at these samples. diff --git a/docs/inspiration/samples/general.md b/docs/inspiration/samples/general.md deleted file mode 100644 index 76e6edc39b..0000000000 --- a/docs/inspiration/samples/general.md +++ /dev/null @@ -1,2 +0,0 @@ -# General - diff --git a/docs/inspiration/samples/spring.md b/docs/inspiration/samples/spring.md deleted file mode 100644 index fae61867a1..0000000000 --- a/docs/inspiration/samples/spring.md +++ /dev/null @@ -1,3 +0,0 @@ -# Spring - -Konsist can be used to guard the consistency of the [Spring](https://spring.io/) project. Take a look at these samples. diff --git a/docs/samples/android.md b/docs/samples/android.md deleted file mode 100644 index 922b190e5c..0000000000 --- a/docs/samples/android.md +++ /dev/null @@ -1,3 +0,0 @@ -# Android - -Konsist can be used to guard the consistency of the [Android](https://www.android.com/) project. Take a look at these samples. diff --git a/docs/samples/general.md b/docs/samples/general.md deleted file mode 100644 index 76e6edc39b..0000000000 --- a/docs/samples/general.md +++ /dev/null @@ -1,2 +0,0 @@ -# General - diff --git a/docs/samples/spring.md b/docs/samples/spring.md deleted file mode 100644 index fae61867a1..0000000000 --- a/docs/samples/spring.md +++ /dev/null @@ -1,3 +0,0 @@ -# Spring - -Konsist can be used to guard the consistency of the [Spring](https://spring.io/) project. Take a look at these samples. diff --git a/docs/writing-tests/introduction.md b/docs/writing-tests/introduction.md deleted file mode 100644 index 953179182c..0000000000 --- a/docs/writing-tests/introduction.md +++ /dev/null @@ -1,3 +0,0 @@ -# Introduction - -The following example provides a glimpse at the minimum requirements for writing a test in Konsist. The subsequent pages of this section will provide further details on all available features.