diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e60cd6a6b2..1611f5e3e5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,11 +36,6 @@ jobs: # a pull request then we can checkout the head. fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 diff --git a/diktat-analysis.yml b/diktat-analysis.yml index 1f107ac579..ddab5fee1c 100644 --- a/diktat-analysis.yml +++ b/diktat-analysis.yml @@ -7,7 +7,7 @@ # testDirs: test disabledChapters: "" testDirs: test - kotlinVersion: 1.4.30 + kotlinVersion: 1.5 srcDirectories: "main" # Checks that the Class/Enum/Interface name does not match Pascal case - name: CLASS_NAME_INCORRECT @@ -38,9 +38,6 @@ # Checks that function/method name is in lowerCamelCase - name: FUNCTION_NAME_INCORRECT_CASE enabled: true -# Checks that typealias name is in PascalCase -- name: TYPEALIAS_NAME_INCORRECT_CASE - enabled: true # 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: true diff --git a/diktat-common/src/main/kotlin/org/cqfn/diktat/common/config/rules/RulesConfigReader.kt b/diktat-common/src/main/kotlin/org/cqfn/diktat/common/config/rules/RulesConfigReader.kt index a4f831f712..a812ca7108 100644 --- a/diktat-common/src/main/kotlin/org/cqfn/diktat/common/config/rules/RulesConfigReader.kt +++ b/diktat-common/src/main/kotlin/org/cqfn/diktat/common/config/rules/RulesConfigReader.kt @@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory import java.io.BufferedReader import java.io.File +import java.util.Locale import java.util.concurrent.atomic.AtomicInteger import kotlinx.serialization.Serializable @@ -107,7 +108,7 @@ data class CommonConfiguration(private val configuration: Map?) */ val testAnchors: List by lazy { val testDirs = (configuration ?: emptyMap()).getOrDefault("testDirs", "test").split(',') - if (testDirs.any { !it.toLowerCase().endsWith("test") }) { + if (testDirs.any { !it.lowercase(Locale.getDefault()).endsWith("test") }) { log.error("test directory names should end with `test`") } testDirs @@ -144,7 +145,7 @@ data class CommonConfiguration(private val configuration: Map?) */ val srcDirectories: List by lazy { val srcDirs = configuration?.get("srcDirectories")?.split(",")?.map { it.trim() } ?: listOf("main") - if (srcDirs.any { !it.toLowerCase().endsWith("main") }) { + if (srcDirs.any { !it.lowercase(Locale.getDefault()).endsWith("main") }) { log.error("source directory names should end with `main`") } srcDirs diff --git a/diktat-gradle-plugin/build.gradle.kts b/diktat-gradle-plugin/build.gradle.kts index 4fd41e5386..7bee2e520b 100644 --- a/diktat-gradle-plugin/build.gradle.kts +++ b/diktat-gradle-plugin/build.gradle.kts @@ -3,7 +3,7 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurr plugins { `java-gradle-plugin` - kotlin("jvm") version "1.3.72" + kotlin("jvm") version "1.4.20" jacoco id("pl.droidsonroids.jacoco.testkit") version "1.0.7" id("org.gradle.test-retry") version "1.2.1" @@ -20,9 +20,9 @@ repositories { // default value is needed for correct gradle loading in IDEA; actual value from maven is used during build val ktlintVersion = project.properties.getOrDefault("ktlintVersion", "0.39.0") as String -val diktatVersion = project.version.takeIf { it.toString() != Project.DEFAULT_VERSION } ?: "0.4.0" +val diktatVersion = project.version.takeIf { it.toString() != Project.DEFAULT_VERSION } ?: "0.5.2" val junitVersion = project.properties.getOrDefault("junitVersion", "5.7.0") as String -val jacocoVersion = project.properties.getOrDefault("jacocoVersion", "0.8.6") as String +val jacocoVersion = project.properties.getOrDefault("jacocoVersion", "0.8.7") as String dependencies { implementation(kotlin("gradle-plugin-api")) diff --git a/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties index 4d9ca16491..549d84424d 100644 --- a/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties +++ b/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/diktat-maven-plugin/pom.xml b/diktat-maven-plugin/pom.xml index f95d087271..34690e02ba 100644 --- a/diktat-maven-plugin/pom.xml +++ b/diktat-maven-plugin/pom.xml @@ -109,10 +109,6 @@ - - 1.4 - 1.4 - org.apache.maven.plugins diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/IdentifierNaming.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/IdentifierNaming.kt index 821a979570..a409247238 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/IdentifierNaming.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/IdentifierNaming.kt @@ -63,6 +63,7 @@ import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.psiUtil.isPrivate import org.jetbrains.kotlin.psi.psiUtil.parents +import java.util.Locale /** * This visitor covers rules: 1.2, 1.3, 1.4, 1.5 of Huawei code style. It covers following rules: @@ -172,7 +173,8 @@ class IdentifierNaming(configRules: List) : DiktatRule( } // check if identifier of a property has a confusing name if (confusingIdentifierNames.contains(variableName.text) && !isValidCatchIdentifier(variableName) && - node.elementType == ElementType.PROPERTY) { + node.elementType == ElementType.PROPERTY + ) { warnConfusingName(variableName) } // check for constant variables - check for val from companion object or on global file level @@ -245,7 +247,8 @@ class IdentifierNaming(configRules: List) : DiktatRule( destructingDeclaration.getAllChildrenWithType(DESTRUCTURING_DECLARATION_ENTRY) .map { it.getIdentifierName()!! } } else if (node.parents().count() > 1 && node.treeParent.elementType == VALUE_PARAMETER_LIST && - node.treeParent.treeParent.elementType == FUNCTION_TYPE) { + node.treeParent.treeParent.elementType == FUNCTION_TYPE + ) { listOfNotNull(node.getIdentifierName()) } else { listOf(node.getIdentifierName()!!) @@ -298,7 +301,7 @@ class IdentifierNaming(configRules: List) : DiktatRule( } } - private fun hasExceptionSuffix(text: String) = text.toLowerCase().endsWith("exception") + private fun hasExceptionSuffix(text: String) = text.lowercase(Locale.getDefault()).endsWith("exception") /** * basic check for object naming of code blocks (PascalCase) @@ -323,8 +326,10 @@ class IdentifierNaming(configRules: List) : DiktatRule( private fun checkEnumValues(node: ASTNode): List { val enumValues: List = node.getChildren(null).filter { it.elementType == ElementType.IDENTIFIER } enumValues.forEach { value -> - val configuration = IdentifierNamingConfiguration(configRules.getRuleConfig(ENUM_VALUE)?.configuration - ?: emptyMap()) + val configuration = IdentifierNamingConfiguration( + configRules.getRuleConfig(ENUM_VALUE)?.configuration + ?: emptyMap() + ) val validator = when (configuration.enumStyle) { Style.PASCAL_CASE -> String::isPascalCase Style.SNAKE_CASE -> String::isUpperSnakeCase @@ -412,13 +417,16 @@ class IdentifierNaming(configRules: List) : DiktatRule( /** * identifier name length should not be longer than 64 symbols and shorter than 2 symbols */ - private fun checkIdentifierLength(nodes: List, - isVariable: Boolean) { + private fun checkIdentifierLength( + nodes: List, + isVariable: Boolean + ) { nodes.forEach { if (it.text != "_" && !(it.isTextLengthInRange(MIN_IDENTIFIER_LENGTH..MAX_IDENTIFIER_LENGTH) || oneCharIdentifiers.contains(it.text) && isVariable || isValidCatchIdentifier(it) - )) { + ) + ) { IDENTIFIER_LENGTH.warn(configRules, emitWarn, isFixMode, it.text, it.startOffset, it) } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/IndentationRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/IndentationRule.kt index 237f4ce4e4..ff8b059edc 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/IndentationRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/IndentationRule.kt @@ -339,7 +339,7 @@ class IndentationRule(configRules: List) : DiktatRule( /** * @return full current indent */ - fun indent() = regularIndent + exceptionalIndents.sumBy { it.indent } + fun indent() = regularIndent + exceptionalIndents.sumOf { it.indent } /** * @param initiator a node that caused exceptional indentation diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidUtilityClass.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidUtilityClass.kt index c4c7153f87..242423794a 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidUtilityClass.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidUtilityClass.kt @@ -20,6 +20,7 @@ import com.pinterest.ktlint.core.ast.ElementType.RBRACE import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.psi.psiUtil.children +import java.util.Locale /** * Rule 6.4.1 checks that class/object, with a word "util" in its name, has only functions. @@ -43,7 +44,7 @@ class AvoidUtilityClass(configRules: List) : DiktatRule( private fun checkClass(node: ASTNode) { // checks that class/object doesn't contain primary constructor and its identifier doesn't has "utli" if (!node.hasChildOfType(IDENTIFIER) || node.hasChildOfType(PRIMARY_CONSTRUCTOR) || - !node.findChildByType(IDENTIFIER)!!.text.toLowerCase().contains("util")) { + !node.findChildByType(IDENTIFIER)!!.text.lowercase(Locale.getDefault()).contains("util")) { return } node.findChildByType(CLASS_BODY) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/AstNodeUtils.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/AstNodeUtils.kt index 75041aaa24..2feed40a6f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/AstNodeUtils.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/AstNodeUtils.kt @@ -55,6 +55,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.siblings import org.slf4j.Logger import org.slf4j.LoggerFactory +import java.util.Locale /** * A [Logger] that can be used throughout diktat @@ -373,7 +374,7 @@ fun ASTNode.isVarProperty() = * Replaces text of [this] node with lowercase text */ fun ASTNode.toLower() { - (this as LeafPsiElement).replaceWithText(this.text.toLowerCase()) + (this as LeafPsiElement).replaceWithText(this.text.lowercase(Locale.getDefault())) } /** diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringCaseUtils.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringCaseUtils.kt index e05f8eee58..4fac0d518b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringCaseUtils.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringCaseUtils.kt @@ -5,6 +5,8 @@ package org.cqfn.diktat.ruleset.utils import com.google.common.base.CaseFormat import org.slf4j.LoggerFactory +import java.util.Locale + private val log = LoggerFactory.getLogger("StringCaseUtils") /** @@ -56,7 +58,7 @@ fun String.toUpperSnakeCase(): String { } // lower -> LOWER if (this.all { it.isLowerCase() }) { - return this.toUpperCase() + return this.uppercase(Locale.getDefault()) } // lowerCamel -> LOWER_CAMEL if (this.isLowerCamelCase()) { @@ -71,7 +73,7 @@ fun String.toUpperSnakeCase(): String { if (idx != -1) { // any other format -> UPPER_SNAKE_CASE // [p]a[SC]a[_]l -> [P]A_[SC]_A_[L] - return this[idx].toUpperCase().toString() + convertUnknownCaseToUpperSnake(this.substring(idx + 1)) + return this[idx].uppercaseChar().toString() + convertUnknownCaseToUpperSnake(this.substring(idx + 1)) } log.error("Not able to fix case format for: $this") @@ -91,7 +93,7 @@ fun String.toLowerCamelCase(): String { } // lower -> LOWER if (this.all { it.isUpperCase() }) { - return this.toLowerCase() + return this.lowercase(Locale.getDefault()) } // lowerCamel -> LOWER_CAMEL if (this.isUpperSnakeCase()) { @@ -108,7 +110,7 @@ fun String.toLowerCamelCase(): String { // changing first letter to uppercase and replacing several uppercase letters in raw to lowercase: // example of change: [P]a[SC]a[_]l -> [p]a[Sc]a[L] // FixMe: there is some discussion on how lowerN_Case should be resolved: to lowerNcase or to lowernCase or lowerNCase (current version) - return this[idx].toLowerCase().toString() + convertUnknownCaseToCamel(this.substring(idx + 1), this[idx].isUpperCase()) + return this[idx].lowercaseChar().toString() + convertUnknownCaseToCamel(this.substring(idx + 1), this[idx].isUpperCase()) } log.error("Not able to fix case format for: $this") @@ -124,11 +126,11 @@ fun String.toLowerCamelCase(): String { fun String.toPascalCase(): String = when { all { it.isUpperCase() } -> { // all letters UPPER -> Upper - this[0] + substring(1).toLowerCase() + this[0] + substring(1).lowercase(Locale.getDefault()) } all { it.isLowerCase() } -> { // all letters lower -> Lower - this[0].toUpperCase() + substring(1) + this[0].uppercaseChar() + substring(1) } isUpperSnakeCase() -> { // lowerCamel -> LowerCamel @@ -145,7 +147,7 @@ fun String.toPascalCase(): String = when { // changing first letter to uppercase and replacing several uppercase letters in raw to lowercase: // example of change: [p]a[SC]a[_]l -> [P]a[Sc]a[L] // FixMe: there is some discussion on how PascalN_Case should be resolved: to PascalNcase or to PascalnCase or PascalNCase (current version) - this[idx].toUpperCase().toString() + convertUnknownCaseToCamel(substring(idx + 1), true) + this[idx].uppercaseChar().toString() + convertUnknownCaseToCamel(substring(idx + 1), true) } else { log.error("Not able to fix case format for: $this") this @@ -165,7 +167,7 @@ private fun convertUnknownCaseToCamel(str: String, isFirstLetterCapital: Boolean var isPreviousLetterUnderscore = false return str.map { char -> if (char.isUpperCase()) { - val result = if (isPreviousLetterCapital && !isPreviousLetterUnderscore) char.toLowerCase() else char + val result = if (isPreviousLetterCapital && !isPreviousLetterUnderscore) char.lowercaseChar() else char isPreviousLetterCapital = true isPreviousLetterUnderscore = false result.toString() @@ -178,7 +180,7 @@ private fun convertUnknownCaseToCamel(str: String, isFirstLetterCapital: Boolean isPreviousLetterUnderscore -> { isPreviousLetterCapital = true isPreviousLetterUnderscore = false - char.toUpperCase().toString() + char.uppercaseChar().toString() } else -> { isPreviousLetterCapital = false @@ -204,7 +206,7 @@ private fun convertUnknownCaseToUpperSnake(str: String): String { } } else { alreadyInsertedUnderscore = (char == '_') - char.toUpperCase().toString() + char.uppercaseChar().toString() } }.joinToString("") } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringUtils.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringUtils.kt index c45db4fce7..259fad1a7b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringUtils.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/StringUtils.kt @@ -98,7 +98,7 @@ fun String.hasPrefix(): Boolean { fun String.removePrefix(): String { // FixMe: there can be cases when after you will change variable name - it becomes a keyword if (this.isLowerCamelCase()) { - return this[1].toLowerCase() + this.substring(2) + return this[1].lowercaseChar() + this.substring(2) } if (this.isUpperSnakeCase()) { return this.substring(2) diff --git a/diktat-rules/src/main/resources/diktat-analysis-huawei.yml b/diktat-rules/src/main/resources/diktat-analysis-huawei.yml index 7ea3341699..17583be793 100644 --- a/diktat-rules/src/main/resources/diktat-analysis-huawei.yml +++ b/diktat-rules/src/main/resources/diktat-analysis-huawei.yml @@ -7,7 +7,7 @@ # testDirs: test disabledChapters: "" testDirs: test - kotlinVersion: 1.4.30 + kotlinVersion: 1.5 srcDirectories: "main" # Checks that the Class/Enum/Interface name does not match Pascal case - name: CLASS_NAME_INCORRECT diff --git a/diktat-rules/src/main/resources/diktat-analysis.yml b/diktat-rules/src/main/resources/diktat-analysis.yml index b6a1f62d55..d53410af99 100644 --- a/diktat-rules/src/main/resources/diktat-analysis.yml +++ b/diktat-rules/src/main/resources/diktat-analysis.yml @@ -5,7 +5,7 @@ domainName: your.name.here testDirs: test disabledChapters: "" - kotlinVersion: 1.4 + kotlinVersion: 1.5 srcDirectories: "main" # Checks that the Class/Enum/Interface name does not match Pascal case - name: CLASS_NAME_INCORRECT diff --git a/examples/gradle-groovy-dsl/diktat-analysis.yml b/examples/gradle-groovy-dsl/diktat-analysis.yml index b6a1f62d55..d53410af99 100644 --- a/examples/gradle-groovy-dsl/diktat-analysis.yml +++ b/examples/gradle-groovy-dsl/diktat-analysis.yml @@ -5,7 +5,7 @@ domainName: your.name.here testDirs: test disabledChapters: "" - kotlinVersion: 1.4 + kotlinVersion: 1.5 srcDirectories: "main" # Checks that the Class/Enum/Interface name does not match Pascal case - name: CLASS_NAME_INCORRECT diff --git a/pom.xml b/pom.xml index 6b5cf32af5..a9243716b5 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 1.8 1.8 UTF-8 - 1.4.32 + 1.5.0 true 1.1.0 0.39.0 @@ -92,6 +92,11 @@ kotlin-stdlib-jdk8 ${kotlin.version} + + org.jetbrains.kotlin + kotlin-stdlib-common + ${kotlin.version} + org.jetbrains.kotlin kotlin-compiler-embeddable @@ -224,7 +229,6 @@ src/main/resources - -Xuse-ir -Werror -Xopt-in=kotlin.RequiresOptIn @@ -305,7 +309,6 @@ detekt-config.yml ${maven.compile.classpath} - 1.4 1.8 **/resources/**/*.kt,**/resources/**/*.kts @@ -418,7 +421,6 @@ ${project.basedir}/src/main/kotlin - 1.3 org.jetbrains.dokka