Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/configurable-dot-qualified
Browse files Browse the repository at this point in the history
  • Loading branch information
nulls committed Mar 20, 2023
2 parents 62d0bbc + 3a0cc50 commit 74c6535
Show file tree
Hide file tree
Showing 41 changed files with 416 additions and 108 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ DiKTat is a strict [coding standard ](info/guide/diktat-coding-convention.md) fo
as AST visitors on the top of [KTlint](https://ktlint.github.io/). It can be used for detecting and autofixing code smells in CI/CD process.
The full list of available supported rules and inspections can be found [here](info/available-rules.md).

Now diKTat was already added to the lists of [static analysis tools](https://github.com/analysis-tools-dev/static-analysis), to [kotlin-awesome](https://github.com/KotlinBy/awesome-kotlin) and to [kompar](https://catalog.kompar.tools/Analyzer/diKTat/1.2.4.2). Thanks to the community for this support!
Now diKTat was already added to the lists of [static analysis tools](https://github.com/analysis-tools-dev/static-analysis), to [kotlin-awesome](https://github.com/KotlinBy/awesome-kotlin) and to [kompar](https://catalog.kompar.tools/Analyzer/diKTat/1.2.5). Thanks to the community for this support!

## See first

Expand Down Expand Up @@ -56,11 +56,11 @@ Main features of diktat are the following:
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.46.1/ktlint && chmod a+x ktlint
```

1. Load diKTat manually: [here](https://github.com/saveourtool/diKTat/releases/download/v1.2.4.2/diktat-1.2.4.2.jar)
1. Load diKTat manually: [here](https://github.com/saveourtool/diKTat/releases/download/v1.2.5/diktat-1.2.5.jar)

**OR** use `curl`:
```console
$ curl -sSLO https://github.com/saveourtool/diKTat/releases/download/v1.2.4.2/diktat-1.2.4.2.jar
$ curl -sSLO https://github.com/saveourtool/diKTat/releases/download/v1.2.5/diktat-1.2.5.jar
```

### Run diKTat
Expand Down Expand Up @@ -182,7 +182,7 @@ This plugin is available since version 0.1.5. You can see how the plugin is conf

```kotlin
plugins {
id("org.cqfn.diktat.diktat-gradle-plugin") version "1.2.4.2"
id("org.cqfn.diktat.diktat-gradle-plugin") version "1.2.5"
}
```

Expand All @@ -193,7 +193,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.cqfn.diktat:diktat-gradle-plugin:1.2.4.2")
classpath("org.cqfn.diktat:diktat-gradle-plugin:1.2.5")
}
}

Expand All @@ -215,9 +215,9 @@ Also in `diktat` extension you can configure different reporters and their outpu
If `output` is set, it should be a file path. If not set, results will be printed to stdout.
```kotlin
diktat {
// since 1.2.4.2 to keep in line with maven properties
// since 1.2.5 to keep in line with maven properties
reporter = "json" // "html", "json", "plain" (default), "sarif"
// before 1.2.4.2
// before 1.2.5
// reporterType = "json" // "html", "json", "plain" (default), "sarif"

output = "someFile.json"
Expand Down Expand Up @@ -259,7 +259,7 @@ spotless {
```kotlin
spotless {
kotlin {
diktat("1.2.4.2").configFile("full/path/to/diktat-analysis.yml")
diktat("1.2.5").configFile("full/path/to/diktat-analysis.yml")
}
}
```
Expand Down Expand Up @@ -290,7 +290,7 @@ Diktat can be run via spotless-maven-plugin since version 2.8.0

```xml
<diktat>
<version>1.2.4.2</version> <!-- optional -->
<version>1.2.5</version> <!-- optional -->
<configFile>full/path/to/diktat-analysis.yml</configFile> <!-- optional, configuration file path -->
</diktat>
```
Expand Down
2 changes: 1 addition & 1 deletion diktat-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>org.cqfn.diktat</groupId>
<artifactId>diktat-parent</artifactId>
<version>1.2.4.3-SNAPSHOT</version>
<version>1.2.6-SNAPSHOT</version>
</parent>

<dependencies>
Expand Down
4 changes: 2 additions & 2 deletions diktat-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurr

plugins {
`java-gradle-plugin`
kotlin("jvm") version "1.8.0"
kotlin("jvm") version "1.8.10"
jacoco
id("pl.droidsonroids.jacoco.testkit") version "1.0.9"
id("org.gradle.test-retry") version "1.5.1"
id("org.gradle.test-retry") version "1.5.2"
}

repositories {
Expand Down
2 changes: 1 addition & 1 deletion diktat-gradle-plugin/gradle-plugin-marker/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>diktat-gradle-plugin</artifactId>
<groupId>org.cqfn.diktat</groupId>
<version>1.2.4.3-SNAPSHOT</version>
<version>1.2.6-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 1 addition & 1 deletion diktat-gradle-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>diktat-parent</artifactId>
<groupId>org.cqfn.diktat</groupId>
<version>1.2.4.3-SNAPSHOT</version>
<version>1.2.6-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
18 changes: 4 additions & 14 deletions diktat-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
<parent>
<artifactId>diktat-parent</artifactId>
<groupId>org.cqfn.diktat</groupId>
<version>1.2.4.3-SNAPSHOT</version>
<version>1.2.6-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>diktat-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

<properties>
<maven.api.version>3.8.6</maven.api.version>
<maven.api.version>3.9.1</maven.api.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.itf.version>0.11.0</maven.itf.version>
<maven.itf.version>0.12.0</maven.itf.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -281,16 +281,6 @@
<profile>
<!-- enable maven plugin documentation generation only for release builds to speed up ordinary builds -->
<id>release</id>
<pluginRepositories>
<pluginRepository>
<id>kotlin-maven-plugin-tools</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/gantsign/kotlin-maven-plugin-tools</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
Expand Down Expand Up @@ -322,7 +312,7 @@
<dependency>
<groupId>com.github.gantsign.maven.plugin-tools</groupId>
<artifactId>kotlin-maven-plugin-tools</artifactId>
<version>0.9.26</version>
<version>1.1.0</version>
</dependency>
</dependencies>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInfo
import java.io.File
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.Path
import kotlin.io.path.deleteIfExists
import kotlin.io.path.div
Expand All @@ -37,7 +36,6 @@ import kotlin.io.path.readText
* `JAVA_HOME` to the _run configuration_, so that the parent and the forked
* JVMs have the same version.
*/
@OptIn(ExperimentalPathApi::class)
@MavenJupiterExtension
class DiktatMavenPluginIntegrationTest {
@BeforeEach
Expand All @@ -59,7 +57,7 @@ class DiktatMavenPluginIntegrationTest {
assertThat(mavenLog).contains("[FILE_NAME_MATCH_CLASS]")

val method = testInfo.testMethod.get()
File(result.mavenProjectResult.targetProjectDirectory, "target/jacoco-it.exec").copyTo(
File(result.mavenProjectResult.targetProjectDirectory.toFile(), "target/jacoco-it.exec").copyTo(
File("target/jacoco-it-${method.name}.exec")
)
}
Expand All @@ -84,7 +82,7 @@ class DiktatMavenPluginIntegrationTest {
}

val method = testInfo.testMethod.get()
File(result.mavenProjectResult.targetProjectDirectory, "target/jacoco-it.exec").copyTo(
File(result.mavenProjectResult.targetProjectDirectory.toFile(), "target/jacoco-it.exec").copyTo(
File("target/jacoco-it-${method.name}.exec")
)
}
Expand Down
2 changes: 1 addition & 1 deletion diktat-rules/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>org.cqfn.diktat</groupId>
<artifactId>diktat-parent</artifactId>
<version>1.2.4.3-SNAPSHOT</version>
<version>1.2.6-SNAPSHOT</version>
</parent>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ abstract class DiktatRule(
// we are very sorry for throwing common Error here, but unfortunately we are not able to throw
// any existing Exception, as they will be caught in ktlint framework and the logging will be confusing:
// in this case it will incorrectly ask you to report issues in diktat to ktlint repository
throw Error("Internal error in diktat application")
throw Error("Internal error in diktat application", internalError)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,11 @@ class ClassLikeStructuresOrderRule(configRules: List<RulesConfig>) : DiktatRule(
* @property properties all other properties
* @property lateInitProperties `lateinit var`s
*/
private data class AllProperties(val loggers: List<ASTNode>,
val constProperties: List<ASTNode>,
val properties: List<ASTNode>,
val lateInitProperties: List<ASTNode>
private data class AllProperties(
val loggers: List<ASTNode>,
val constProperties: List<ASTNode>,
val properties: List<ASTNode>,
val lateInitProperties: List<ASTNode>
) {
companion object {
/**
Expand All @@ -197,6 +198,7 @@ class ClassLikeStructuresOrderRule(configRules: List<RulesConfig>) : DiktatRule(
val allProperties = node.getAllChildrenWithType(PROPERTY)
val constProperties = allProperties.filterByModifier(CONST_KEYWORD)
val lateInitProperties = allProperties.filterByModifier(LATEINIT_KEYWORD)
val referencesFromSameScope = allProperties.mapNotNull { it.getIdentifierName()?.text }
val loggers = allProperties.filterByModifier(PRIVATE_KEYWORD)
.filterNot { astNode ->
/*
Expand All @@ -213,9 +215,27 @@ class ClassLikeStructuresOrderRule(configRules: List<RulesConfig>) : DiktatRule(
.filter { astNode ->
astNode.getIdentifierName()?.text?.matches(loggerPropertyRegex) ?: false
}
.let {
getLoggerDependencyNames(it)
}
.filter { (_, dependencyReferences) ->
dependencyReferences.all {
it !in referencesFromSameScope
}
}
.keys
.toList()

val properties = allProperties.filter { it !in lateInitProperties && it !in loggers && it !in constProperties }
return AllProperties(loggers, constProperties, properties, lateInitProperties)
}

@Suppress("TYPE_ALIAS")
private fun getLoggerDependencyNames(loggers: List<ASTNode>): Map<ASTNode, List<String>> = loggers.map { astNode ->
astNode to astNode.findAllDescendantsWithSpecificType(REFERENCE_EXPRESSION, false)
}.associate { (astNode, possibleDependencies) ->
astNode to possibleDependencies.map { it.text }
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ class FileStructureRule(configRules: List<RulesConfig>) : DiktatRule(
val otherNodesBeforeCode = firstCodeNode.siblings(forward = false)
.filterNot {
it.isWhiteSpace() ||
it == copyrightComment || it == headerKdoc || it == fileAnnotations
it == copyrightComment || it == headerKdoc || it == fileAnnotations ||
it.elementType == PACKAGE_DIRECTIVE
}
.toList()
.reversed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,10 @@ class NewlinesRule(configRules: List<RulesConfig>) : DiktatRule(
private fun handleReturnStatement(node: ASTNode) {
val blockNode = node.treeParent.takeIf { it.elementType == BLOCK && it.treeParent.elementType == FUN }
val returnsUnit = node.children().count() == 1 // the only child is RETURN_KEYWORD
if (blockNode == null || returnsUnit) {
val hasMultipleReturn = node.findAllDescendantsWithSpecificType(RETURN_KEYWORD).count() > 1
if (blockNode == null || returnsUnit || hasMultipleReturn) {
// function is either already with expression body or definitely can't be converted to it
// or the function has more than one keyword `return` inside it
return
}
blockNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER
import com.pinterest.ktlint.core.ast.ElementType.TYPE_REFERENCE
import com.pinterest.ktlint.core.ast.prevSibling
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens.EXTERNAL_KEYWORD
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.psiUtil.allChildren

/**
* This rule checks if there are any extension functions for the class in the same file, where it is defined
Expand All @@ -35,11 +40,29 @@ class ExtensionFunctionsInFileRule(configRules: List<RulesConfig>) : DiktatRule(
}
}

@Suppress("UnsafeCallOnNullableType")
private fun collectAllClassNames(node: ASTNode): List<String> {
val classes = node.findAllDescendantsWithSpecificType(CLASS)
/**
* Collects all class names in the [file], except those with modifiers from
* the [ignore list][ignoredModifierTypes].
*
* @throws IllegalArgumentException if [file] is not a
* [FILE][ElementType.FILE] node.
*/
private fun collectAllClassNames(file: ASTNode): List<String> {
require(file.elementType == ElementType.FILE)

val classes = file.findAllDescendantsWithSpecificType(CLASS)

return classes.map { (it.psi as KtClass).name!! }
return classes.asSequence()
.map(ASTNode::getPsi)
.filterIsInstance(KtClass::class.java)
.filter { clazz ->
clazz.modifierTypes().none { modifierType ->
modifierType in ignoredModifierTypes
}
}
.map(KtClass::getName)
.filterNotNull()
.toList()
}

private fun fireWarning(node: ASTNode) {
Expand All @@ -55,5 +78,30 @@ class ExtensionFunctionsInFileRule(configRules: List<RulesConfig>) : DiktatRule(

companion object {
const val NAME_ID = "extension-functions-class-file"

/**
* Types of class/interface modifiers which, if present, don't trigger
* the warning.
*
* @since 1.2.5
*/
private val ignoredModifierTypes: Array<out KtModifierKeywordToken> = arrayOf(
EXTERNAL_KEYWORD,
)

/**
* @since 1.2.5
*/
private fun KtClass.modifiers(): Sequence<PsiElement> =
modifierList?.allChildren ?: emptySequence()

/**
* @since 1.2.5
*/
private fun KtClass.modifierTypes(): Sequence<KtModifierKeywordToken> =
modifiers()
.filterIsInstance<LeafPsiElement>()
.map(LeafPsiElement::getElementType)
.filterIsInstance<KtModifierKeywordToken>()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ fun ASTNode.getAllChildrenWithType(elementType: IElementType): List<ASTNode> =
/**
* Generates a sequence of this ASTNode's children in reversed order
*
* @return a reevrsed sequence of children
* @return a reversed sequence of children
*/
fun ASTNode.reversedChildren(): Sequence<ASTNode> = sequence {
var node = lastChildNode
Expand Down Expand Up @@ -595,8 +595,8 @@ fun ASTNode.moveChildBefore(
beforeThisNode: ASTNode?,
withNextNode: Boolean = false
): ReplacementResult {
require(childToMove in children()) { "can only move child of this node" }
require(beforeThisNode == null || beforeThisNode in children()) { "can only place node before another child of this node" }
require(childToMove in children()) { "can only move child ($childToMove) of this node $this" }
require(beforeThisNode == null || beforeThisNode in children()) { "can only place node before another child ($beforeThisNode) of this node $this" }
val movedChild = childToMove.clone() as ASTNode
val nextMovedChild = childToMove.treeNext?.takeIf { withNextNode }?.let { it.clone() as ASTNode }
val nextOldChild = childToMove.treeNext.takeIf { withNextNode && it != null }
Expand Down
Loading

0 comments on commit 74c6535

Please sign in to comment.