Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make diktat consistent with own code style #404

Merged
merged 5 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@
configuration: {}
- name: FILE_WILDCARD_IMPORTS
enabled: true
configuration: {}
configuration:
allowedWildcards: "kotlinx.serialization.*"
- name: NO_BRACES_IN_CONDITIONALS_AND_LOOPS
enabled: true
configuration: {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package org.cqfn.diktat.common.cli

import org.apache.commons.cli.Option
import kotlinx.serialization.*
import org.apache.commons.cli.Option

/**
* This class is used to serialize/deserialize json representation
* that is used to store command line arguments
* @property shortName short argument representation like -h
* @property longName long argument representation like --help
* @property hasArgs indicates if option should have explicit argument
*/
@Serializable
data class CliArgument (
// short argument representation like -h
data class CliArgument(
private val shortName: String,
private val helpDescr: String,
// long argument representation like --help
private val longName: String,
// indicates if option should have explicit argument
private val hasArgs: Boolean,
private val isRequired: Boolean) {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ package org.cqfn.diktat.common.config.rules

import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlConfiguration
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import java.io.BufferedReader
import java.io.File
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import org.cqfn.diktat.common.config.reader.JsonResourceConfigReader
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand All @@ -28,6 +28,9 @@ interface Rule {

/**
* Configuration of individual [Rule]
* @property name name of the rule
* @property enabled
* @property configuration a map of strings with configuration options
*/
@Serializable
data class RulesConfig(
Expand All @@ -38,12 +41,14 @@ data class RulesConfig(

/**
* Configuration that allows customizing additional options of particular rules.
* @property config a map of strings with configuration options for a particular rule
*/
open class RuleConfiguration(protected val config: Map<String, String>)
object EmptyConfiguration : RuleConfiguration(mapOf())

/**
* class returns the list of configurations that we have read from a yml: diktat-analysis.yml
* @property classLoader a [ClassLoader] used to load configuration file
*/
open class RulesConfigReader(override val classLoader: ClassLoader) : JsonResourceConfigReader<List<RulesConfig>>() {
private val yamlSerializer by lazy { Yaml(configuration = YamlConfiguration(strictMode = true)) }
Expand All @@ -54,10 +59,8 @@ open class RulesConfigReader(override val classLoader: ClassLoader) : JsonResour
* @param fileStream a [BufferedReader] representing loaded rules config file
* @return list of [RulesConfig]
*/
override fun parseResource(fileStream: BufferedReader): List<RulesConfig> {
return fileStream.use { stream ->
yamlSerializer.decodeFromString(stream.readLines().joinToString(separator = "\n"))
}
override fun parseResource(fileStream: BufferedReader): List<RulesConfig> = fileStream.use { stream ->
yamlSerializer.decodeFromString(stream.readLines().joinToString(separator = "\n"))
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode
* This class represent individual inspections of diktat code style.
* A [Warnings] entry contains rule name, warning message and is used in code check.
*/
@Suppress("ForbiddenComment", "MagicNumber")
@Suppress("ForbiddenComment", "MagicNumber", "WRONG_DECLARATIONS_ORDER")
enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: String) : Rule {
// ======== chapter 1 ========
PACKAGE_NAME_MISSING(true, "no package name declared in a file"),
Expand Down Expand Up @@ -107,7 +107,6 @@ enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: S
// FixMe: change float literal to BigDecimal? Or kotlin equivalent?
FLOAT_IN_ACCURATE_CALCULATIONS(false, "floating-point values shouldn't be used in accurate calculations"),


// ======== chapter 5 ========
TOO_LONG_FUNCTION(false, "function is too long: split it or make more primitive"),
AVOID_NESTED_FUNCTIONS(true, "try to avoid using nested functions"),
Expand Down Expand Up @@ -147,7 +146,6 @@ enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: S
freeText: String,
offset: Int,
node: ASTNode) {

if (configs.isRuleEnabled(this) && !node.hasSuppress(name)) {
val trimmedFreeText = freeText
.lines()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.cqfn.diktat.ruleset.rules.comments.HeaderCommentRule.Companion.afterC
import org.cqfn.diktat.ruleset.rules.comments.HeaderCommentRule.Companion.curYear
import org.cqfn.diktat.ruleset.rules.comments.HeaderCommentRule.Companion.hyphenRegex

private val AUTO_GENERATION_COMMENT =
private val autoGenerationComment =
"""
| This document was auto generated, please don't modify it.
| This document contains all enum properties from Warnings.kt as Strings.
Expand All @@ -25,7 +25,8 @@ private fun generateWarningNames() {
val enumValNames = Warnings.values().map { it.name }

val propertyList = enumValNames.map {
PropertySpec.builder(it, String::class)
PropertySpec
.builder(it, String::class)
.addModifiers(KModifier.CONST)
.initializer("\"$it\"")
.build()
Expand All @@ -40,10 +41,10 @@ private fun generateWarningNames() {
.builder("generated", "WarningNames")
.addType(fileBody)
.indent(" ")
.addComment(AUTO_GENERATION_COMMENT)
.addComment(autoGenerationComment)
.build()

kotlinFile.writeTo(File("diktat-rules/src/main/kotlin")) // fixme: need to add it to pom
kotlinFile.writeTo(File("diktat-rules/src/main/kotlin")) // fixme: need to add it to pom
}

private fun validateYear() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl
* This rule makes each annotation applied to a class, method or constructor is on its own line. Except: if first annotation of constructor, class or method
*/
class AnnotationNewLineRule(private val configRules: List<RulesConfig>) : Rule("annotation-new-line") {

private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)
private var isFixMode: Boolean = false
private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)

override fun visit(node: ASTNode,
autoCorrect: Boolean,
Expand All @@ -38,22 +37,22 @@ class AnnotationNewLineRule(private val configRules: List<RulesConfig>) : Rule("
}
}


private fun checkAnnotation(node: ASTNode) {
node.findChildByType(MODIFIER_LIST)?.let { modList ->
fixAnnotation(modList)
}
}

private fun fixAnnotation(node: ASTNode) {
if (node.getAllChildrenWithType(ANNOTATION_ENTRY).size <= 1)
if (node.getAllChildrenWithType(ANNOTATION_ENTRY).size <= 1) {
return
}

node.getAllChildrenWithType(ANNOTATION_ENTRY).forEach {
if (!it.isFollowedByNewline() || !it.isBeginByNewline())
if (!it.isFollowedByNewline() || !it.isBeginByNewline()) {
deleteSpaces(it, !it.isFollowedByNewline(), !it.isBeginByNewline())
}
}

}

private fun deleteSpaces(node: ASTNode, rightSide: Boolean, leftSide: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import org.jetbrains.kotlin.psi.psiUtil.parents
* This rule checks for nested functions and warns if it finds any.
*/
class AvoidNestedFunctionsRule(private val configRules: List<RulesConfig>) : Rule("avoid-nested-functions") {
private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)
private var isFixMode: Boolean = false
private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)

override fun visit(node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
emitWarn = emit
Expand All @@ -46,7 +46,10 @@ class AvoidNestedFunctionsRule(private val configRules: List<RulesConfig>) : Rul
canBeAutoCorrected = checkFunctionReferences(node)) {
// We take last nested function, then add and remove child from bottom to top
val lastFunc = node.findAllNodesWithSpecificType(FUN).last()
val funcSeq = lastFunc.parents().filter { it.elementType == FUN }.toMutableList()
val funcSeq = lastFunc
.parents()
.filter { it.elementType == FUN }
.toMutableList()
funcSeq.add(0, lastFunc)
val firstFunc = funcSeq.last()
funcSeq.dropLast(1).forEachIndexed { index, it ->
Expand All @@ -65,9 +68,11 @@ class AvoidNestedFunctionsRule(private val configRules: List<RulesConfig>) : Rul
private fun isNestedFunction(node: ASTNode): Boolean =
node.hasParent(FUN) && node.hasFunParentUntil(CLASS_BODY) && !node.hasChildOfType(MODIFIER_LIST)


private fun ASTNode.hasFunParentUntil(stopNode: IElementType): Boolean =
parents().asSequence().takeWhile { it.elementType != stopNode }.any { it.elementType == FUN }
parents()
.asSequence()
.takeWhile { it.elementType != stopNode }
.any { it.elementType == FUN }

/**
* Checks if local function has no usage of outside properties
Expand All @@ -85,10 +90,10 @@ class AvoidNestedFunctionsRule(private val configRules: List<RulesConfig>) : Rul

/**
* Collects all function parameters' names
*
* @return List of names
*/
@Suppress("UnsafeCallOnNullableType")
private fun getParameterNames(node: ASTNode): List<String> =
(node.psi as KtFunction).valueParameters.map { it.name!! }

(node.psi as KtFunction).valueParameters.map { it.name!! }
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.pinterest.ktlint.core.ast.ElementType.WHILE
import com.pinterest.ktlint.core.ast.ElementType.WHILE_KEYWORD
import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
import com.pinterest.ktlint.core.ast.isWhiteSpaceWithNewline
import java.lang.Exception
import org.cqfn.diktat.common.config.rules.RuleConfiguration
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getRuleConfig
Expand All @@ -44,12 +45,10 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl
import org.jetbrains.kotlin.com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.KtTryExpression
import java.lang.Exception

class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("block-structure") {

private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)
private var isFixMode: Boolean = false
private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)

override fun visit(node: ASTNode,
autoCorrect: Boolean,
Expand All @@ -74,8 +73,9 @@ class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("b

private fun checkLambda(node: ASTNode, configuration: BlockStructureBracesConfiguration) {
val isSingleLineLambda = node.text.lines().size == 1
if (!isSingleLineLambda)
if (!isSingleLineLambda) {
checkCloseBrace(node, configuration)
}
}

@Suppress("UnsafeCallOnNullableType")
Expand Down Expand Up @@ -123,8 +123,11 @@ class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("b

private fun checkWhen(node: ASTNode, configuration: BlockStructureBracesConfiguration) {
/// WHEN expression doesn't contain BLOCK element and LBRECE isn't the first child, so we should to find it.
val childrenAfterLBrace = node.getChildren(null).toList().run { subList(indexOfFirst { it.elementType == LBRACE }, size) }
if (!emptyBlockList.containsAll(childrenAfterLBrace.distinct().map { it.elementType })) {
val childrenAfterLbrace = node
.getChildren(null)
.toList()
.run { subList(indexOfFirst { it.elementType == LBRACE }, size) }
if (!emptyBlockList.containsAll(childrenAfterLbrace.distinct().map { it.elementType })) {
checkOpenBraceOnSameLine(node, LBRACE, configuration)
checkCloseBrace(node, configuration)
}
Expand Down Expand Up @@ -160,7 +163,9 @@ class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("b
}

private fun checkOpenBraceOnSameLine(node: ASTNode, beforeType: IElementType, configuration: BlockStructureBracesConfiguration) {
if (!configuration.openBrace) return
if (!configuration.openBrace) {
return
}
val nodeBefore = node.findChildByType(beforeType)
val braceSpace = nodeBefore?.treePrev
if (braceSpace == null || checkBraceNode(braceSpace, true)) {
Expand Down Expand Up @@ -210,9 +215,11 @@ class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("b

@Suppress("UnsafeCallOnNullableType")
private fun checkCloseBrace(node: ASTNode, configuration: BlockStructureBracesConfiguration) {
if (!configuration.closeBrace) return
if (!configuration.closeBrace) {
return
}
val space = node.findChildByType(RBRACE)!!.treePrev
if (checkBraceNode(space))
if (checkBraceNode(space)) {
BRACES_BLOCK_STRUCTURE_ERROR.warnAndFix(configRules, emitWarn, isFixMode, "no newline before closing brace",
(space.treeNext ?: node.findChildByType(RBRACE))!!.startOffset, node) {
if (space.elementType != WHITE_SPACE) {
Expand All @@ -221,6 +228,7 @@ class BlockStructureBraces(private val configRules: List<RulesConfig>) : Rule("b
(space as LeafPsiElement).replaceWithText("\n")
}
}
}
}

private fun checkBraceNode(node: ASTNode, shouldContainNewline: Boolean = false) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@ import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.psiUtil.astReplace

class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig>) : Rule("braces-rule") {
companion object {
private const val indentStep = 4
}

private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)
private var isFixMode: Boolean = false
private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)

override fun visit(node: ASTNode,
autoCorrect: Boolean,
Expand All @@ -62,9 +58,16 @@ class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig
val thenNode = ifPsi.then?.node
val elseKeyword = ifPsi.elseKeyword
val elseNode = ifPsi.`else`?.node
val indent = node.prevSibling { it.elementType == WHITE_SPACE }?.text?.lines()?.last()?.count { it == ' ' } ?: 0
val indent = node
.prevSibling { it.elementType == WHITE_SPACE }
?.text
?.lines()
?.last()
?.count { it == ' ' } ?: 0

if (node.isSingleLineIfElse()) return
if (node.isSingleLineIfElse()) {
return
}

if (thenNode?.elementType != BLOCK) {
NO_BRACES_IN_CONDITIONALS_AND_LOOPS.warnAndFix(configRules, emitWarn, isFixMode, "IF",
Expand Down Expand Up @@ -101,7 +104,11 @@ class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig
if (loopBodyNode == null || loopBodyNode.elementType != BLOCK) {
NO_BRACES_IN_CONDITIONALS_AND_LOOPS.warnAndFix(configRules, emitWarn, isFixMode, node.elementType.toString(), node.startOffset, node) {
// fixme proper way to calculate indent? or get step size (instead of hardcoded 4)
val indent = node.prevSibling { it.elementType == WHITE_SPACE }!!.text.lines().last().count { it == ' ' }
val indent = node.prevSibling { it.elementType == WHITE_SPACE }!!
.text
.lines()
.last()
.count { it == ' ' }
if (loopBody != null) {
loopBody.replaceWithBlock(indent)
} else {
Expand All @@ -118,7 +125,9 @@ class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig

@Suppress("UnsafeCallOnNullableType")
private fun checkWhenBranches(node: ASTNode) {
(node.psi as KtWhenExpression).entries.asSequence()
(node.psi as KtWhenExpression)
.entries
.asSequence()
.filter { it.expression != null && it.expression!!.node.elementType == BLOCK }
.map { it.expression as KtBlockExpression }
.filter { it.statements.size == 1 }
Expand All @@ -131,7 +140,7 @@ class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig

private fun KtElement.replaceWithBlock(indent: Int) {
this.astReplace(KtBlockExpression(
"{\n${" ".repeat(indent + indentStep)}$text\n${" ".repeat(indent)}}"
"{\n${" ".repeat(indent + INDENT_STEP)}$text\n${" ".repeat(indent)}}"
))
}

Expand All @@ -146,4 +155,7 @@ class BracesInConditionalsAndLoopsRule(private val configRules: List<RulesConfig
replaceChild(secondChild, PsiWhiteSpaceImpl(" "))
}
}
companion object {
private const val INDENT_STEP = 4
}
}
Loading