Compare commits

...

6 Commits

Author SHA1 Message Date
Artem Tsebrov 5e0fce2a60 Update testcontainers versions for better docker compatibility (#2)
https://github.com/testcontainers/testcontainers-java/releases/tag/1.18.3
Co-authored-by: Artyom Tsebrov <artem.tsebrov@touchin.ru>
Reviewed-on: #2
2023-08-04 17:38:17 +03:00
Artem Tsebrov a070a94381 Codestyle archunit (#1)
Co-authored-by: Artyom Tsebrov <artem.tsebrov@touchin.ru>
Reviewed-on: #1
2023-04-18 17:17:14 +03:00
Alexander Buntakov 0976db1e47 Merge branch 'feature/kotlin-styleguide-lint' into 'master'
Kotlin Styleguide plugins

See merge request touchinstinct/Backend-common!1
2023-04-06 16:54:03 +00:00
Artem Tsebrov e17454b996 Kotlin Styleguide plugins 2023-04-06 16:54:03 +00:00
TonCherAmi c8ed908656
Mark createdAt as not updatable (#108) 2023-01-13 17:30:42 +03:00
Artyom 20f07a4a9d
Implement "debug" level for logging (#107) 2023-01-10 14:02:39 +03:00
13 changed files with 828 additions and 11 deletions

113
README.md
View File

@ -20,6 +20,19 @@
}
```
## Project Gradle tasks
### Detekt:
- `gradle $project:detekt` - detect not formatted, complex code.
Reports are stored in "$pwd/build/reports/kotlin-detekt-${project.name}.html".
### DiKTat:
- `gradle :diktatCheck` - detect not formatted code of "kt", "kts" files;
- `gradle :diktatFix` - if possible, fix not formatted code. Known issues: full fix may require 1+ launch in order to apply all rules; some rules potentially may break code syntax.
By setting environment variable `TASKS_FILE_REPORT_ENABLED`(true, false) you may configure raw console output or html file as report.
Reports are stored in "$pwd/build/reports/diktat-report.html".
## common
Набор утилит, структур данных, исключений без привязки к `spring`
@ -68,6 +81,106 @@
Утилиты для тестирования репозиториев
## codestyle-archunit
Набор правил для поддержки оформления архитектуры.
#### Список доступных правил
- `ru.touchin.codestyle.archunit.rules.ClassNamingArchRules`
- `ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules`
#### Gradle plugin
Настройка и применение совместно с [ArchUnit Gradle Plugin](https://github.com/societe-generale/arch-unit-gradle-plugin).
Действие `checkRules` для проверки соответствие правилам запускается при операциях сборки, по умолчанию.
Вручную можно вызвать командой ``gradle :checkRules`` для нужного модуля.
Добавить его можно следующим образом на примере установки в рутовый gradle.build проекта:
Groovy DSL:
```groovy
buildscript {
dependencies {
classpath "com.societegenerale.commons:arch-unit-gradle-plugin:3.0.0"
}
}
subprojects {
dependencyManagement {
dependencies {
dependency "com.tngtech.archunit:archunit:1.0.1"
}
}
apply plugin: "java"
apply plugin: "com.societegenerale.commons.arch-unit-gradle-plugin"
archUnit {
mainScopePath = "/classes/kotlin/main" // or "/classes/java/main"
testScopePath = "/classes/kotlin/test" // or "/classes/java/test"
var applyType = applyOn("ru.touchin", "main")
configurableRules = [
configurableRule(
"ru.touchin.codestyle.archunit.rules.ClassNamingArchRules",
applyType,
),
configurableRule(
"ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules",
applyType,
),
]
}
dependencies {
archUnitExtraLib "ru.touchin:codestyle-archunit" // or archUnitExtraLib project(":codestyle-archunit")
}
}
```
Kotlin DSL:
```kotlin
plugins {
id("com.societegenerale.commons.arch-unit-gradle-plugin") version "3.0.0"
}
subprojects {
configure<DependencyManagementExtension> {
dependencies {
dependency("com.tngtech.archunit:archunit:1.0.1")
}
}
apply(plugin = "java")
apply(plugin = "com.societegenerale.commons.arch-unit-gradle-plugin")
archUnit {
mainScopePath = "/classes/kotlin/main" // or "/classes/java/main"
testScopePath = "/classes/kotlin/test" // or "/classes/java/test"
configurableRules = listOf(
"ru.touchin.codestyle.archunit.rules.ClassNamingArchRules",
"ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules"
).map { package ->
configurableRule(
package,
applyOn("ru.touchin", "main")
)
}
}
dependencies {
archUnitExtraLib("ru.touchin:codestyle-archunit") // or archUnitExtraLib(project(":codestyle-archunit"))
}
}
```
Отключить проверки на таске помимо конфигурирования `configurableRule` можно также таким образом:
```kotlin
// clear action launch for root project to avoid exception
tasks.checkRules.configure {
actions.clear()
}
```
## logger
Основные компоненты логирования:

View File

@ -1,10 +1,11 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
import org.jetbrains.kotlin.cli.common.toBooleanLenient
plugins {
kotlin("jvm")
id ("org.springframework.boot") apply false
id("org.springframework.boot") apply false
// IntelliJ
idea
@ -17,7 +18,8 @@ plugins {
// https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/
id("io.spring.dependency-management")
id("io.gitlab.arturbosch.detekt").version("1.18.0")
id("io.gitlab.arturbosch.detekt")
id("org.cqfn.diktat.diktat-gradle-plugin")
}
allprojects {
@ -33,6 +35,30 @@ allprojects {
apply(plugin = "idea")
}
diktat {
inputs {
include(
"**/src/**/*.kt",
"*.kts",
"**/*.kts",
"**/src/**/*.kts",
)
exclude(
"**/build/**",
"build/**",
)
}
val tasksFileReportEnabled = project.properties["TASKS_FILE_REPORT_ENABLED"]
?.let { it.toString().toBooleanLenient() }
?: true
reporter = if (tasksFileReportEnabled) "html" else "plain"
output = if (tasksFileReportEnabled) "${project.buildDir}/reports/diktat-report.html" else String()
diktatConfigFile = file("$rootDir/diktat-analysis.yml")
ignoreFailures = true
debug = false
}
subprojects {
println("Enabling Kotlin JVM plugin in project ${project.name}...")
apply(plugin = "org.jetbrains.kotlin.jvm")
@ -55,7 +81,7 @@ subprojects {
reports {
txt.enabled = false
xml.enabled = false
html{
html {
enabled = true
destination = file("${project.buildDir}/reports/kotlin-detekt-${project.name}.html")
}
@ -73,13 +99,15 @@ subprojects {
dependency("ch.qos.logback.contrib:logback-json-classic:0.1.5")
dependency("ch.qos.logback.contrib:logback-jackson:0.1.5")
dependency("org.testcontainers:testcontainers:1.15.1")
dependency("org.testcontainers:postgresql:1.15.1")
dependency("org.testcontainers:junit-jupiter:1.15.1")
dependency("org.testcontainers:testcontainers:1.18.3")
dependency("org.testcontainers:postgresql:1.18.3")
dependency("org.testcontainers:junit-jupiter:1.18.3")
dependency("org.junit.jupiter:junit-jupiter-api:5.4.2")
dependency("org.junit.jupiter:junit-jupiter-params:5.4.2")
dependency("org.junit.jupiter:junit-jupiter-engine:5.4.2")
dependency("com.tngtech.archunit:archunit:1.0.1")
dependency("org.liquibase:liquibase-core:4.4.0")
dependency("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
@ -105,7 +133,7 @@ subprojects {
dependencies {
// use for @ConstructorBinding
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
}

View File

@ -0,0 +1,8 @@
plugins {
id("kotlin")
}
dependencies {
implementation(project(":common"))
implementation("com.tngtech.archunit:archunit")
}

View File

@ -0,0 +1,53 @@
package ru.touchin.codestyle.archunit.rules
import com.tngtech.archunit.lang.ArchRule
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods
import ru.touchin.common.exceptions.CommonException
/**
* Set of rules that defines constraint for classes naming.
*/
@Suppress("unused")
object ClassNamingArchRules {
val CLASSES_WHICH_HAVE_SCHEDULED_METHODS_MUST_HAVE_SUFFIX: ArchRule = methods()
.that()
.areAnnotatedWith("org.springframework.scheduling.annotation.Scheduled")
.should().beDeclaredInClassesThat().haveSimpleNameEndingWith("Job")
.allowEmptyShould(true)
.because("Classes that use 'Scheduled' annotation must have name with 'Job' suffix")
val ANNOTATED_SERVICE_CLASSES_MUST_HAVE_SUFFIX: ArchRule = methods()
.that().areAnnotatedWith("org.springframework.stereotype.Service")
.should().beDeclaredInClassesThat().haveSimpleNameContaining("Service")
.allowEmptyShould(true)
.because("Classes that use 'Service' annotation are assignable to class with `Service` suffix")
val ANNOTATED_ENTITY_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
.that().areAnnotatedWith("javax.persistence.Entity")
.should().haveSimpleNameEndingWith("Entity")
.allowEmptyShould(true)
.because("Hibernate 'Entity' classes must have name with 'Entity' suffix")
val EXCEPTION_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
.that().areAssignableTo(Exception::class.java)
.or().areAssignableTo(CommonException::class.java)
.should().haveSimpleNameEndingWith("Exception")
.allowEmptyShould(true)
.because("'Exception' classes must have name with 'Exception' suffix")
val JPAREPOSITORY_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
.that().areAssignableTo("org.springframework.data.jpa.repository.JpaRepository")
.should().haveSimpleNameEndingWith("Repository")
.allowEmptyShould(true)
.because("Classes that use 'JpaRepository' must have name with 'Repository' suffix")
val WEBCLIENT_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
.that().haveFullyQualifiedName("org.springframework.web.reactive.valction.client.WebClient")
.should().onlyBeAccessed().byClassesThat().haveSimpleNameEndingWith("WebClient")
.allowEmptyShould(true)
.because("Classes that use Spring 'WebClient' must have name with 'WebClient' suffix")
}

View File

@ -0,0 +1,56 @@
package ru.touchin.codestyle.archunit.rules
import com.tngtech.archunit.lang.ArchRule
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes
/**
* Set of rules that defines constraint for classes placement.
*/
@Suppress("unused")
object ClassPackagingArchRules {
val IMPL_CLASSES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("Impl")
.should().resideInAPackage("..impl..")
.allowEmptyShould(true)
.because("Implementations of interfaces must reside in package 'impl'")
val ENTITIES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("Entity")
.should().resideInAPackage("..models..")
.allowEmptyShould(true)
.because("'Entity' must reside in package 'models'")
val REPOSITORIES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("Repository")
.should().resideInAPackage("..repositories..")
.allowEmptyShould(true)
.because("'Repository' must reside in package 'repositories'")
val CORE_SERVICES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("CoreService")
.should().resideInAPackage("..services..")
.allowEmptyShould(true)
.because("'CoreService' must reside in package 'services'")
val CONVERTERS_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("Converter")
.should().resideInAPackage("..converters..")
.allowEmptyShould(true)
.because("'Converter' must reside in package 'converters'")
val EXCEPTIONS_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().haveSimpleNameEndingWith("Exception")
.should().resideInAPackage("..exceptions..")
.allowEmptyShould(true)
.because("'Exception' must reside in package 'exceptions'")
val ENUM_CLASSES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
.that().areEnums()
.should().resideInAPackage("..enums..")
.allowEmptyShould(true)
.because("'Enum' must reside in package 'enums'")
}

View File

@ -13,7 +13,7 @@ import javax.persistence.MappedSuperclass
@MappedSuperclass
abstract class BaseEntity : Serializable {
@CreatedDate
@CreatedDate(updatable = false)
lateinit var createdAt: ZonedDateTime
@LastModifiedDate

View File

@ -73,11 +73,14 @@ complexity:
threshold: 40
LongParameterList:
active: true
threshold: 10
functionThreshold: 10
ignoreDefaultParameters: false
MethodOverloading:
active: false
threshold: 5
NamedArguments:
active: false
threshold: 2
NestedBlockDepth:
active: true
threshold: 4
@ -290,6 +293,9 @@ style:
DataClassContainsFunctions:
active: false
conversionFunctionPrefix: 'to'
DestructuringDeclarationWithTooManyEntries:
active: true
maxDestructuringEntries: 5
EqualsNullCall:
active: true
ExplicitItLambdaParameter:

536
diktat-analysis.yml Normal file
View File

@ -0,0 +1,536 @@
#### ENABLED RULES ####
# Checks that there is no more than one statement per line
- name: MORE_THAN_ONE_STATEMENT_PER_LINE
enabled: true
# Checks that line breaks follow code style guide: rule 3.6
- name: WRONG_NEWLINES
enabled: true
configuration:
# If the number of parameters on one line is more than this threshold, all parameters will be placed on separate lines.
maxParametersInOneLine: 2
# 3 by default.
maxCallsInOneLine: 2
# Checks that indentation is correct
- name: WRONG_INDENTATION
enabled: true
configuration:
# Is newline at the end of a file needed
newlineAtEnd: true
# If true: in parameter list when parameters are split by newline they are indented with two indentations instead of one
extendedIndentOfParameters: false
# If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it
alignedParameters: true
# If true, expression bodies which begin on a separate line are indented
# using a continuation indent. The default is false.
#
# This flag is called CONTINUATION_INDENT_FOR_EXPRESSION_BODIES in IDEA and
# ij_kotlin_continuation_indent_for_expression_bodies in .editorconfig.
extendedIndentForExpressionBodies: false
# If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
extendedIndentAfterOperators: true
# If true: when dot qualified expression starts on a new line, this line will be indented with two indentations instead of one
extendedIndentBeforeDot: false
# The indentation size for each file
indentationSize: 4
# Checks that braces are used in if, else, when, for, do, and while statements. Exception: single line ternary operator statement
- name: NO_BRACES_IN_CONDITIONALS_AND_LOOPS
enabled: true
# Checks that annotation is on a single line
- name: ANNOTATION_NEW_LINE
enabled: true
# Checks that the long lambda has parameters
- name: TOO_MANY_LINES_IN_LAMBDA
enabled: true
configuration:
maxLambdaLength: 1 # max length of lambda without parameters
# Checks that the line length is < lineLength parameter
- name: LONG_LINE
enabled: true
configuration:
lineLength: '120'
# Checks trailing comma
- name: TRAILING_COMMA
enabled: true
configuration:
# VALUE_ARGUMENT
valueArgument: true
# VALUE_PARAMETER
valueParameter: true
# REFERENCE_EXPRESSION
indices: true
# WHEN_CONDITION_WITH_EXPRESSION
whenConditions: true
# STRING_TEMPLATE
collectionLiteral: true
# TYPE_PROJECTION
typeArgument: true
# TYPE_PARAMETER
typeParameter: true
# DESTRUCTURING_DECLARATION_ENTRY
destructuringDeclaration: true
#### DISABLED DEFAULT RULES ####
# Checks that the Class/Enum/Interface name matches Pascal case
- name: CLASS_NAME_INCORRECT
enabled: false
# all code blocks with MyAnnotation will be ignored and not checked
ignoreAnnotated: [ MyAnnotation ]
# Checks that CONSTANT (treated as const val from companion object or class level) is in non UPPER_SNAKE_CASE
- name: CONSTANT_UPPERCASE
enabled: false
# Checks that enum value is in upper SNAKE_CASE or in PascalCase depending on the config. UPPER_SNAKE_CASE is the default, but can be changed by 'enumStyle' config
- name: ENUM_VALUE
enabled: false
configuration:
# Two options: SNAKE_CASE (default), PascalCase
enumStyle: SNAKE_CASE
# Checks that class which extends any Exception class has Exception suffix
- name: EXCEPTION_SUFFIX
enabled: false
# Checks that file name has extension
- name: FILE_NAME_INCORRECT
enabled: false
# Checks that file name matches class name, if it is only one class in file
- name: FILE_NAME_MATCH_CLASS
enabled: false
# Checks that functions/methods which return boolean have special prefix like "is/should/e.t.c"
- name: FUNCTION_BOOLEAN_PREFIX
enabled: false
configuration:
allowedPrefixes: "" # A list of functions that return boolean and are allowed to use. Input is in a form "foo, bar".
# Checks that function/method name is in lowerCamelCase
- name: FUNCTION_NAME_INCORRECT_CASE
enabled: false
# Checks that typealias name is in PascalCase
- name: TYPEALIAS_NAME_INCORRECT_CASE
enabled: false
# Checks that generic name doesn't contain more than 1 letter (capital). It can be followed by numbers, example: T12, T
- name: GENERIC_NAME
enabled: false
# Identifier length should be in range [2,64] except names that used in industry like {i, j} and 'e' for catching exceptions
- name: IDENTIFIER_LENGTH
enabled: false
# Checks that the object matches PascalCase
- name: OBJECT_NAME_INCORRECT
enabled: false
# Checks that package name is in correct (lower) case
- name: PACKAGE_NAME_INCORRECT_CASE
enabled: false
# Checks that package name starts with the company's domain
- name: PACKAGE_NAME_INCORRECT_PREFIX
enabled: false
# Checks that package name does not have incorrect symbols like underscore or non-ASCII letters/digits
- name: PACKAGE_NAME_INCORRECT_SYMBOLS
enabled: false
# Checks that the path for a file matches with a package name
- name: PACKAGE_NAME_INCORRECT_PATH
enabled: false
# Checks that package name is in the file
- name: PACKAGE_NAME_MISSING
enabled: false
# Checks that variable does not have prefix (like mVariable or M_VARIABLE)
- name: VARIABLE_HAS_PREFIX
enabled: false
# Checks that variable does not contain one single letter, only exceptions are fixed names that used in industry like {i, j}
- name: VARIABLE_NAME_INCORRECT
enabled: false
# Checks that the name of variable is in lowerCamelCase and contains only ASCII letters
- name: VARIABLE_NAME_INCORRECT_FORMAT
enabled: false
# Checks that functions have kdoc
- name: MISSING_KDOC_ON_FUNCTION
enabled: false
# Checks that on file level internal or public class or function has missing KDoc
- name: MISSING_KDOC_TOP_LEVEL
enabled: false
# Checks that accessible internal elements (protected, public, internal) in a class are documented
- name: MISSING_KDOC_CLASS_ELEMENTS
enabled: false
# Checks that accessible method parameters are documented in KDoc
- name: KDOC_WITHOUT_PARAM_TAG
enabled: false
# Checks that accessible method explicit return type is documented in KDoc
- name: KDOC_WITHOUT_RETURN_TAG
enabled: false
# Checks that accessible method throw keyword is documented in KDoc
- name: KDOC_WITHOUT_THROWS_TAG
enabled: false
# Checks that KDoc is not empty
- name: KDOC_EMPTY_KDOC
enabled: false
# Checks that underscore is correctly used to split package naming
- name: INCORRECT_PACKAGE_SEPARATOR
enabled: false
# Checks that code block doesn't contain kdoc comments
- name: COMMENTED_BY_KDOC
enabled: false
# Checks that there is no @deprecated tag in kdoc
- name: KDOC_NO_DEPRECATED_TAG
enabled: false
# Checks that there is no empty content in kdoc tags
- name: KDOC_NO_EMPTY_TAGS
enabled: false
# Checks that there is only one space after kdoc tag
- name: KDOC_WRONG_SPACES_AFTER_TAG
enabled: false
# Checks tags order in kDoc. `@param`, `@return`, `@throws`
- name: KDOC_WRONG_TAGS_ORDER
enabled: false
# Checks that there is no newline of empty KDoc line (with leading asterisk) between `@param`, `@return`, `@throws` tags
- name: KDOC_NO_NEWLINES_BETWEEN_BASIC_TAGS
enabled: false
# Checks that block of tags @param, @return, @throws is separated from previous part of KDoc by exactly one empty line
- name: KDOC_NEWLINES_BEFORE_BASIC_TAGS
enabled: false
# Checks that special tags `@apiNote`, `@implNote`, `@implSpec` have exactly one empty line after
- name: KDOC_NO_NEWLINE_AFTER_SPECIAL_TAGS
enabled: false
# Checks that kdoc does not contain @author tag or date
- name: KDOC_CONTAINS_DATE_OR_AUTHOR
enabled: false
configuration:
versionRegex: \d+\.\d+\.\d+[-.\w\d]*
# Checks that KDoc does not contain single line with words 'return', 'get' or 'set'
- name: KDOC_TRIVIAL_KDOC_ON_FUNCTION
enabled: false
# Checks that there is newline after header KDoc
- name: HEADER_WRONG_FORMAT
enabled: false
# Checks that file with zero or >1 classes has header KDoc
- name: HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE
enabled: false
# Checks that copyright exists on top of file and is properly formatted (as a block comment)
- name: HEADER_MISSING_OR_WRONG_COPYRIGHT
enabled: false
configuration:
isCopyrightMandatory: false
copyrightText: 'Copyright (c) Your Company Name Here. 2010-;@currYear;'
# Checks that header kdoc is located before package directive
- name: HEADER_NOT_BEFORE_PACKAGE
enabled: false
# Checks that file does not contain lines > maxSize
- name: FILE_IS_TOO_LONG
enabled: false
configuration:
# number of lines
maxSize: '2000'
# Checks that file does not contain commented out code
- name: COMMENTED_OUT_CODE
enabled: false
# Checks that file does not contain only comments, imports and package directive
- name: FILE_CONTAINS_ONLY_COMMENTS
enabled: false
# Orders imports alphabetically
- name: FILE_UNORDERED_IMPORTS
enabled: false
configuration:
# use logical imports grouping with sorting inside of a group
useRecommendedImportsOrder: true
# Checks that general order of code parts is right
- name: FILE_INCORRECT_BLOCKS_ORDER
enabled: false
# Checks that there is exactly one line between code blocks
- name: FILE_NO_BLANK_LINE_BETWEEN_BLOCKS
enabled: false
# Checks that there is no wildcard imports. Exception: allowedWildcards
- name: FILE_WILDCARD_IMPORTS
enabled: false
configuration:
allowedWildcards: "" # Allowed wildcards for imports (e.g. "import org.cqfn.diktat.*, import org.jetbrains.kotlin.*")
useRecommendedImportsOrder: true
# Checks unused imports
- name: UNUSED_IMPORT
enabled: false
configuration:
deleteUnusedImport: true
# Checks that the declaration part of a class-like code structures (class/interface/etc.) is in the proper order
- name: WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES
enabled: false
# Checks that properties with comments are separated by a blank line
- name: BLANK_LINE_BETWEEN_PROPERTIES
enabled: false
# Checks top level order
- name: TOP_LEVEL_ORDER
enabled: false
# Checks that non-empty code blocks with braces follow the K&R style (1TBS or OTBS style)
- name: BRACES_BLOCK_STRUCTURE_ERROR
enabled: false
configuration:
openBraceNewline: 'True'
closeBraceNewline: 'True'
# Checks that there is no empty blocks in a file.
# If allowEmptyBlocks is true, checks that it follows correct style (have a newline)
- name: EMPTY_BLOCK_STRUCTURE_ERROR
enabled: false
configuration:
# Whether a newline after `{` is required in an empty block
styleEmptyBlockWithNewline: 'True'
allowEmptyBlocks: 'False'
# Checks that semicolons are not used at the end of a line
- name: REDUNDANT_SEMICOLON
enabled: false
# Checks that there are not too many consecutive spaces in line
- name: TOO_MANY_CONSECUTIVE_SPACES
enabled: false
configuration:
# Maximum allowed number of consecutive spaces (not counting indentation)
maxSpaces: '1'
# Whether formatting for enums should be kept without checking
saveInitialFormattingForEnums: false
# Inspection that checks if a long dot qualified expression is used in condition or as an argument
- name: COMPLEX_EXPRESSION
enabled: false
# Checks that blank lines are used correctly.
# For example: triggers when there are too many blank lines between function declaration
- name: TOO_MANY_BLANK_LINES
enabled: false
# Checks that usage of horizontal spaces doesn't violate code style guide
- name: WRONG_WHITESPACE
enabled: false
# Checks that backticks (``) are not used in the identifier name, except the case when it is test method (marked with @Test annotation)
- name: BACKTICKS_PROHIBITED
enabled: false
# Checks that a single line concatenation of strings is not used
- name: STRING_CONCATENATION
enabled: false
# Checks that each when statement have else in the end
- name: WHEN_WITHOUT_ELSE
enabled: false
# Checks that enum structure is correct: enum entries should be separated by comma and line break and last entry should have semicolon in the end.
- name: ENUMS_SEPARATED
enabled: false
# Checks that value on integer or float constant is not too big
- name: LONG_NUMERICAL_VALUES_SEPARATED
enabled: false
configuration:
# Maximum number of digits which are not split
maxNumberLength: '5'
# Maximum number of digits between separators
maxBlockLength: '3'
# Checks magic number
- name: MAGIC_NUMBER
enabled: false
configuration:
# Ignore numbers from test
ignoreTest: "true"
# Ignore numbers
ignoreNumbers: "-1, 1, 0, 2, 0U, 1U, 2U, -1L, 0L, 1L, 2L, 0UL, 1UL, 2UL"
# Is ignore override hashCode function
ignoreHashCodeFunction: "true"
# Is ignore property
ignorePropertyDeclaration: "false"
# Is ignore local variable
ignoreLocalVariableDeclaration: "false"
# Is ignore constant
ignoreConstantDeclaration: "true"
# Is ignore property in companion object
ignoreCompanionObjectPropertyDeclaration: "true"
# Is ignore numbers in enum
ignoreEnums: "false"
# Is ignore number in ranges
ignoreRanges: "false"
# Is ignore number in extension function
ignoreExtensionFunctions: "false"
# Checks that order of enum values or constant property inside companion is correct
- name: WRONG_DECLARATIONS_ORDER
enabled: false
configuration:
# Whether enum members should be sorted alphabetically
sortEnum: true
# Whether class properties should be sorted alphabetically
sortProperty: true
# Checks that multiple modifiers sequence is in the correct order
- name: WRONG_MULTIPLE_MODIFIERS_ORDER
enabled: false
# Checks that identifier has appropriate name (See table of rule 1.2 part 6)
- name: CONFUSING_IDENTIFIER_NAMING
enabled: false
# Checks year in the copyright
- name: WRONG_COPYRIGHT_YEAR
enabled: false
# Inspection that checks if local variables are declared close to the first usage site
- name: LOCAL_VARIABLE_EARLY_DECLARATION
enabled: false
# Try to avoid initialize val by null (e.g. val a: Int? = null -> val a: Int = 0)
- name: NULLABLE_PROPERTY_TYPE
enabled: false
# Inspection that checks if there is a blank line before kDoc and none after
- name: WRONG_NEWLINES_AROUND_KDOC
enabled: false
# Inspection that checks if there is no blank lines before first comment
- name: FIRST_COMMENT_NO_BLANK_LINE
enabled: false
# Inspection that checks if there are blank lines between code and comment and between code start token and comment's text
- name: COMMENT_WHITE_SPACE
enabled: false
configuration:
maxSpacesBeforeComment: 2
maxSpacesInComment: 1
# Inspection that checks if all comment's are inside if-else code blocks. Exception is general if comment
- name: IF_ELSE_COMMENTS
enabled: false
# Type aliases provide alternative names for existing types when type's reference text is longer 25 chars
- name: TYPE_ALIAS
enabled: false
configuration:
typeReferenceLength: '25' # max length of type reference
# Checks if casting can be omitted
- name: SMART_CAST_NEEDED
enabled: false
# Checks that variables of generic types have explicit type declaration
- name: GENERIC_VARIABLE_WRONG_DECLARATION
enabled: false
# Inspection that checks if string template has redundant curly braces
- name: STRING_TEMPLATE_CURLY_BRACES
enabled: false
# Variables with `val` modifier - are immutable (read-only). Usage of such variables instead of `var` variables increases
# robustness and readability of code, because `var` variables can be reassigned several times in the business logic.
# This rule prohibits usage of `var`s as local variables - the only exception is accumulators and counters
- name: SAY_NO_TO_VAR
enabled: false
# Inspection that checks if string template has redundant quotes
- name: STRING_TEMPLATE_QUOTES
enabled: false
# Check if there are redundant nested if-statements, which could be collapsed into a single one by concatenating their conditions
- name: COLLAPSE_IF_STATEMENTS
enabled: false
configuration:
startCollapseFromNestedLevel: 2
# Checks that floating-point values are not used in arithmetic expressions
- name: FLOAT_IN_ACCURATE_CALCULATIONS
enabled: false
# Checks that function length isn't too long
- name: TOO_LONG_FUNCTION
enabled: false
configuration:
maxFunctionLength: '30' # max length of function
isIncludeHeader: 'false' # count function's header
# Warns if there are nested functions
- name: AVOID_NESTED_FUNCTIONS
enabled: false
# Checks that lambda inside function parameters is in the end
- name: LAMBDA_IS_NOT_LAST_PARAMETER
enabled: false
# Checks that function doesn't contains too many parameters
- name: TOO_MANY_PARAMETERS
enabled: false
configuration:
maxParameterListSize: '5' # max parameters size
# Checks that function doesn't have too many nested blocks
- name: NESTED_BLOCK
enabled: false
configuration:
maxNestedBlockQuantity: '4'
# Checks that function use default values, instead overloading
- name: WRONG_OVERLOADING_FUNCTION_ARGUMENTS
enabled: false
# Checks that using runBlocking inside async block code
- name: RUN_BLOCKING_INSIDE_ASYNC
enabled: false
# Checks that property in constructor doesn't contain comment
- name: KDOC_NO_CONSTRUCTOR_PROPERTY
enabled: false
# Checks that using unnecessary, custom label
- name: CUSTOM_LABEL
enabled: false
# Check that lambda with inner lambda doesn't use implicit parameter
- name: PARAMETER_NAME_IN_OUTER_LAMBDA
enabled: false
# Checks that property in KDoc present in class
- name: KDOC_EXTRA_PROPERTY
enabled: false
# There's a property in KDoc which is already present
- name: KDOC_DUPLICATE_PROPERTY
enabled: false
# Checks that KDoc in constructor has property tag but with comment inside constructor
- name: KDOC_NO_CONSTRUCTOR_PROPERTY_WITH_COMMENT
enabled: false
# if a class has single constructor, it should be converted to a primary constructor
- name: SINGLE_CONSTRUCTOR_SHOULD_BE_PRIMARY
enabled: false
# Checks if class can be made as data class
- name: USE_DATA_CLASS
enabled: false
# Checks that never use the name of a variable in the custom getter or setter
- name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR
enabled: false
# Checks that classes have only one init block
- name: MULTIPLE_INIT_BLOCKS
enabled: false
# Checks that there are abstract functions in abstract class
- name: CLASS_SHOULD_NOT_BE_ABSTRACT
enabled: false
# Checks if there are any trivial getters or setters
- name: TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED
enabled: false
# Checks that no custom getters and setters are used for properties. It is a more wide rule than TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED
# Kotlin compiler automatically generates `get` and `set` methods for properties and also lets the possibility to override it.
# But in all cases it is very confusing when `get` and `set` are overridden for a developer who uses this particular class.
# Developer expects to get the value of the property, but receives some unknown value and some extra side effect hidden by the custom getter/setter.
# Use extra functions for it instead.
- name: CUSTOM_GETTERS_SETTERS
enabled: false
# Checks if null-check was used explicitly (for example: if (a == null))
# Try to avoid explicit null checks (explicit comparison with `null`)
# Kotlin is declared as [Null-safe](https://kotlinlang.org/docs/reference/null-safety.html) language.
# But Kotlin architects wanted Kotlin to be fully compatible with Java, that's why `null` keyword was also introduced in Kotlin.
# There are several code-structures that can be used in Kotlin to avoid null-checks. For example: `?:`, `.let {}`, `.also {}`, e.t.c
- name: AVOID_NULL_CHECKS
enabled: false
# Checks if class instantiation can be wrapped in `apply` for better readability
- name: COMPACT_OBJECT_INITIALIZATION
enabled: false
# Checks explicit supertype qualification
- name: USELESS_SUPERTYPE
enabled: false
# Checks if extension function with the same signature don't have related classes
- name: EXTENSION_FUNCTION_SAME_SIGNATURE
enabled: false
# Checks if there is empty primary constructor
- name: EMPTY_PRIMARY_CONSTRUCTOR
enabled: false
# In case of not using field keyword in property accessors,
# there should be explicit backing property with the name of real property
# Example: val table get() {if (_table == null) ...} -> table should have _table
- name: NO_CORRESPONDING_PROPERTY
enabled: false
# Checks if there is class/object that can be replace with extension function
- name: AVOID_USING_UTILITY_CLASS
enabled: false
# If there is stateless class it is preferred to use object
- name: OBJECT_IS_PREFERRED
enabled: false
# If there exists negated version of function you should prefer it instead of !functionCall
- name: INVERSE_FUNCTION_PREFERRED
enabled: false
# Checks if class can be converted to inline class
- name: INLINE_CLASS_CAN_BE_USED
enabled: false
# If file contains class, then it can't contain extension functions for the same class
- name: EXTENSION_FUNCTION_WITH_CLASS
enabled: false
# Check if kts script contains other functions except run code
- name: RUN_IN_SCRIPT
enabled: false
# Check if boolean expression can be simplified
- name: COMPLEX_BOOLEAN_EXPRESSION
enabled: false
# Check if range can replace with until or `rangeTo` function with range
- name: CONVENTIONAL_RANGE
enabled: false
configuration:
isRangeToIgnore: false
# Check if there is a call of print()\println() or console.log(). Assumption that it's a debug print
- name: DEBUG_PRINT
enabled: false
# Check that typealias name is in PascalCase
- name: TYPEALIAS_NAME_INCORRECT_CASE
enabled: false
# Should change property length - 1 to property lastIndex
- name: USE_LAST_INDEX
enabled: false
# Only properties from the primary constructor should be documented in a @property tag in class KDoc
- name: KDOC_NO_CLASS_BODY_PROPERTIES_IN_HEADER
enabled: false

View File

@ -1,4 +1,6 @@
kotlin.code.style=official
springBootVersion=2.5.3
springDependencyManagementVersion=1.0.11.RELEASE
detektGradlePluginVersion=1.18.0
diktatGradlePluginVersion=1.2.5
kotlinVersion=1.6.21

View File

@ -1,5 +1,5 @@
package ru.touchin.logger.dto
enum class LogLevel {
Trace, Info, Error
Trace, Debug, Info, Error
}

View File

@ -31,6 +31,14 @@ abstract class AbstractLog(clazz: Class<*>) : Log<LogData> {
}
}
override fun debug() {
if (logger.isDebugEnabled) {
val logMessage = getMessage()
logger.debug(logMessage.message, logMessage.error)
}
}
override fun info() {
if (logger.isInfoEnabled) {
val logMessage = getMessage()
@ -58,6 +66,7 @@ abstract class AbstractLog(clazz: Class<*>) : Log<LogData> {
override fun isEnabled(level: LogLevel): Boolean {
return when(level) {
LogLevel.Trace -> logger.isTraceEnabled
LogLevel.Debug -> logger.isDebugEnabled
LogLevel.Info -> logger.isInfoEnabled
LogLevel.Error -> logger.isErrorEnabled
}

View File

@ -6,6 +6,7 @@ interface Log<T> {
var logData: T
fun trace()
fun debug()
fun info()
fun error()

View File

@ -3,11 +3,15 @@ pluginManagement {
val kotlinVersion: String by settings
val springBootVersion: String by settings
val springDependencyManagementVersion: String by settings
val detektGradlePluginVersion: String by settings
val diktatGradlePluginVersion: String by settings
val versions = listOf(
"org.jetbrains.kotlin" to kotlinVersion,
"org.springframework.boot" to springBootVersion,
"io.spring.dependency-management" to springDependencyManagementVersion
"io.spring.dependency-management" to springDependencyManagementVersion,
"io.gitlab.arturbosch.detekt" to detektGradlePluginVersion,
"org.cqfn.diktat.diktat-gradle-plugin" to diktatGradlePluginVersion,
)
eachPlugin {
@ -35,6 +39,7 @@ include("common-geo")
include("common-geo-spatial4j-spring")
include("common-messaging")
include("captcha")
include("codestyle-archunit")
include("logger")
include("logger-spring")
include("logger-spring-web")