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

Feature. Ktlint rule wrapper #744

Merged
merged 14 commits into from
Feb 4, 2021
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.cqfn.diktat.ruleset.rules

import com.pinterest.ktlint.core.Rule
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.isRuleEnabled
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.utils.log
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

typealias DiktatConfigRule = org.cqfn.diktat.common.config.rules.Rule
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
typealias DiktatConfigRule = org.cqfn.diktat.common.config.rules.Rule
private typealias DiktatConfigRule = org.cqfn.diktat.common.config.rules.Rule

Is it used only in this file?


abstract class DiktatRule(id: String, val configRules: List<RulesConfig>, val rules: List<DiktatConfigRule>): Rule(id) {
var isFixMode: Boolean = false
lateinit var emitWarn: EmitType

override fun visit(node: ASTNode, autoCorrect: Boolean, emit: EmitType) {
emitWarn = emit
isFixMode = autoCorrect

if (check()) return
else {
try {
logic(node)
} catch (e: Exception) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} catch (e: Exception) {
} catch (e: Throwable) {

log.error("Internal error has occurred in $id. Please make an issue on this bug at https://github.com/cqfn/diKTat/.\n Error: ${e.message}")
}
}
}

private fun check(): Boolean {
return rules.none { configRules.isRuleEnabled(it) }
}
abstract fun logic(node: ASTNode)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.cqfn.diktat.ruleset.rules.chapter1

import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.FILE_NAME_INCORRECT
import org.cqfn.diktat.ruleset.constants.Warnings.FILE_NAME_MATCH_CLASS
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType
import org.cqfn.diktat.ruleset.utils.getFilePath
import org.cqfn.diktat.ruleset.utils.getFirstChildWithType
import org.cqfn.diktat.ruleset.utils.isKotlinScript
import org.cqfn.diktat.ruleset.utils.isPascalCase

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.CLASS
import com.pinterest.ktlint.core.ast.ElementType.FILE
import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER
Expand All @@ -27,17 +26,10 @@ import java.io.File
* Aggressive: In case file contains only one class on upper level - it should be named with the same name
*/
@Suppress("ForbiddenComment")
class FileNaming(private val configRules: List<RulesConfig>) : Rule("file-naming") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType
class FileNaming(configRules: List<RulesConfig>) : DiktatRule("file-naming", configRules, listOf(FILE_NAME_INCORRECT, FILE_NAME_MATCH_CLASS)) {
private lateinit var filePath: String

override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType) {
emitWarn = emit
isFixMode = autoCorrect

override fun logic(node: ASTNode) {
if (node.elementType == FILE) {
filePath = node.getFilePath()
if (!filePath.isKotlinScript()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.cqfn.diktat.ruleset.rules.chapter1
import org.cqfn.diktat.common.config.rules.RuleConfiguration
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getRuleConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.BACKTICKS_PROHIBITED
import org.cqfn.diktat.ruleset.constants.Warnings.CLASS_NAME_INCORRECT
import org.cqfn.diktat.ruleset.constants.Warnings.CONFUSING_IDENTIFIER_NAMING
Expand All @@ -18,6 +17,7 @@ import org.cqfn.diktat.ruleset.constants.Warnings.OBJECT_NAME_INCORRECT
import org.cqfn.diktat.ruleset.constants.Warnings.VARIABLE_HAS_PREFIX
import org.cqfn.diktat.ruleset.constants.Warnings.VARIABLE_NAME_INCORRECT
import org.cqfn.diktat.ruleset.constants.Warnings.VARIABLE_NAME_INCORRECT_FORMAT
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.Style
import org.cqfn.diktat.ruleset.utils.containsOneLetterOrZero
import org.cqfn.diktat.ruleset.utils.findChildAfter
Expand All @@ -42,7 +42,6 @@ import org.cqfn.diktat.ruleset.utils.toLowerCamelCase
import org.cqfn.diktat.ruleset.utils.toPascalCase
import org.cqfn.diktat.ruleset.utils.toUpperSnakeCase

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType
import com.pinterest.ktlint.core.ast.ElementType.CATCH
import com.pinterest.ktlint.core.ast.ElementType.CATCH_KEYWORD
Expand Down Expand Up @@ -80,7 +79,11 @@ import org.jetbrains.kotlin.psi.psiUtil.parents
* // FixMe: because it fixes only declaration without the usages
*/
@Suppress("ForbiddenComment", "MISSING_KDOC_CLASS_ELEMENTS")
class IdentifierNaming(private val configRules: List<RulesConfig>) : Rule("identifier-naming") {
class IdentifierNaming(configRules: List<RulesConfig>) : DiktatRule("identifier-naming", configRules,
listOf(BACKTICKS_PROHIBITED, VARIABLE_NAME_INCORRECT, VARIABLE_NAME_INCORRECT_FORMAT, CONSTANT_UPPERCASE,
VARIABLE_HAS_PREFIX, CONFUSING_IDENTIFIER_NAMING, GENERIC_NAME, CLASS_NAME_INCORRECT,
ENUM_VALUE, EXCEPTION_SUFFIX, FUNCTION_BOOLEAN_PREFIX, FUNCTION_NAME_INCORRECT_CASE,
IDENTIFIER_LENGTH, OBJECT_NAME_INCORRECT)) {
private val allMethodPrefixes by lazy {
if (configuration.allowedBooleanPrefixes.isNullOrEmpty()) {
booleanMethodPrefixes
Expand All @@ -93,17 +96,10 @@ class IdentifierNaming(private val configRules: List<RulesConfig>) : Rule("ident
this.configRules.getRuleConfig(FUNCTION_BOOLEAN_PREFIX)?.configuration ?: emptyMap()
)
}
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType

override fun visit(
node: ASTNode,
autoCorrect: Boolean,
emit: EmitType
override fun logic(
node: ASTNode
) {
isFixMode = autoCorrect
emitWarn = emit

// backticks are prohibited for identifier declarations everywhere except test methods that are marked with @Test annotation
if (isIdentifierWithBackticks(node)) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package org.cqfn.diktat.ruleset.rules.chapter1

import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getCommonConfiguration
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.INCORRECT_PACKAGE_SEPARATOR
import org.cqfn.diktat.ruleset.constants.Warnings.PACKAGE_NAME_INCORRECT_CASE
import org.cqfn.diktat.ruleset.constants.Warnings.PACKAGE_NAME_INCORRECT_PATH
import org.cqfn.diktat.ruleset.constants.Warnings.PACKAGE_NAME_INCORRECT_PREFIX
import org.cqfn.diktat.ruleset.constants.Warnings.PACKAGE_NAME_INCORRECT_SYMBOLS
import org.cqfn.diktat.ruleset.constants.Warnings.PACKAGE_NAME_MISSING
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.*

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER
import com.pinterest.ktlint.core.ast.ElementType.PACKAGE_DIRECTIVE
Expand All @@ -34,17 +33,12 @@ import java.util.concurrent.atomic.AtomicInteger
* package a.b.c.D -> then class D should be placed in a/b/c/ directories
*/
@Suppress("ForbiddenComment", "TOO_MANY_LINES_IN_LAMBDA")
class PackageNaming(private val configRules: List<RulesConfig>) : Rule("package-naming") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType
class PackageNaming(configRules: List<RulesConfig>) : DiktatRule("package-naming", configRules,
listOf(INCORRECT_PACKAGE_SEPARATOR, PACKAGE_NAME_INCORRECT_CASE, PACKAGE_NAME_MISSING,
PACKAGE_NAME_INCORRECT_PATH, PACKAGE_NAME_INCORRECT_PREFIX, PACKAGE_NAME_INCORRECT_SYMBOLS)) {
private lateinit var domainName: String

override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType) {
isFixMode = autoCorrect
emitWarn = emit

override fun logic(node: ASTNode) {
val configuration by configRules.getCommonConfiguration()
configuration.domainName?.let {
domainName = it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package org.cqfn.diktat.ruleset.rules.chapter2.comments

import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.ListOfPairs
import org.cqfn.diktat.ruleset.constants.Warnings.COMMENTED_OUT_CODE
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.FILE
Expand All @@ -24,18 +23,10 @@ import org.jetbrains.kotlin.resolve.ImportPath
* No commented out code is allowed, including imports.
*/
@Suppress("ForbiddenComment")
class CommentsRule(private val configRules: List<RulesConfig>) : Rule("comments") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType
class CommentsRule(configRules: List<RulesConfig>) : DiktatRule("comments", configRules, listOf(COMMENTED_OUT_CODE)) {
private lateinit var ktPsiFactory: KtPsiFactory

override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType
) {
emitWarn = emit
isFixMode = autoCorrect

override fun logic(node: ASTNode) {
ktPsiFactory = KtPsiFactory(node.psi.project, false) // regarding markGenerated see KDoc in Kotlin sources
if (node.elementType == FILE) {
checkCommentedCode(node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package org.cqfn.diktat.ruleset.rules.chapter2.comments
import org.cqfn.diktat.common.config.rules.RuleConfiguration
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getRuleConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE
import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_MISSING_OR_WRONG_COPYRIGHT
import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_NOT_BEFORE_PACKAGE
import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_WRONG_FORMAT
import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_COPYRIGHT_YEAR
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.copyrightWords
import org.cqfn.diktat.ruleset.utils.findChildAfter
import org.cqfn.diktat.ruleset.utils.findChildBefore
Expand All @@ -17,7 +17,6 @@ import org.cqfn.diktat.ruleset.utils.getFirstChildWithType
import org.cqfn.diktat.ruleset.utils.log
import org.cqfn.diktat.ruleset.utils.moveChildBefore

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType
import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.FILE
Expand All @@ -40,16 +39,10 @@ import java.time.LocalDate
* 4) Ensure files with many or zero classes have proper description
*/
@Suppress("ForbiddenComment")
class HeaderCommentRule(private val configRules: List<RulesConfig>) : Rule("header-comment") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType

override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType) {
isFixMode = autoCorrect
emitWarn = emit

class HeaderCommentRule(configRules: List<RulesConfig>) : DiktatRule("header-comment", configRules,
listOf(HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE, HEADER_MISSING_OR_WRONG_COPYRIGHT, HEADER_NOT_BEFORE_PACKAGE,
HEADER_NOT_BEFORE_PACKAGE, HEADER_WRONG_FORMAT, WRONG_COPYRIGHT_YEAR)) {
override fun logic(node: ASTNode) {
if (node.elementType == FILE) {
checkCopyright(node)
if (checkHeaderKdocPosition(node)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package org.cqfn.diktat.ruleset.rules.chapter2.kdoc
import org.cqfn.diktat.common.config.rules.RuleConfiguration
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getRuleConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.COMMENT_WHITE_SPACE
import org.cqfn.diktat.ruleset.constants.Warnings.FIRST_COMMENT_NO_SPACES
import org.cqfn.diktat.ruleset.constants.Warnings.IF_ELSE_COMMENTS
import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_NEWLINES_AROUND_KDOC
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.*

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.BLOCK
import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.CLASS
Expand Down Expand Up @@ -50,21 +49,15 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl
* * Leave one single space between the comment on the right side of the code and the code.
* * Comments in if else should be inside code blocks. Exception: General if comment
*/
class CommentsFormatting(private val configRules: List<RulesConfig>) : Rule("kdoc-comments-codeblocks-formatting") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType

class CommentsFormatting(configRules: List<RulesConfig>) : DiktatRule("kdoc-comments-codeblocks-formatting", configRules,
listOf(COMMENT_WHITE_SPACE, FIRST_COMMENT_NO_SPACES,
IF_ELSE_COMMENTS, WRONG_NEWLINES_AROUND_KDOC)) {
/**
* @param node
* @param autoCorrect
* @param emit
*/
override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType) {
isFixMode = autoCorrect
emitWarn = emit

override fun logic(node: ASTNode) {
val configuration = CommentsFormattingConfiguration(
configRules.getRuleConfig(COMMENT_WHITE_SPACE)?.configuration ?: emptyMap())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package org.cqfn.diktat.ruleset.rules.chapter2.kdoc

import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getCommonConfiguration
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_EXTRA_PROPERTY
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NO_CONSTRUCTOR_PROPERTY
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NO_CONSTRUCTOR_PROPERTY_WITH_COMMENT
import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_CLASS_ELEMENTS
import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_TOP_LEVEL
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.*

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.CLASS
import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY
Expand Down Expand Up @@ -45,23 +44,15 @@ import org.jetbrains.kotlin.psi.psiUtil.parents
* 2) All internal elements in class like class, property or function should be documented with KDoc
* 3) All properties declared in the primary constructor are documented using `@property` tag in class KDoc
*/
class KdocComments(private val configRules: List<RulesConfig>) : Rule("kdoc-comments") {
private var isFixMode: Boolean = false
private lateinit var emitWarn: EmitType

class KdocComments(configRules: List<RulesConfig>) : DiktatRule("kdoc-comments", configRules,
listOf(KDOC_EXTRA_PROPERTY, KDOC_NO_CONSTRUCTOR_PROPERTY,
KDOC_NO_CONSTRUCTOR_PROPERTY_WITH_COMMENT, MISSING_KDOC_CLASS_ELEMENTS, MISSING_KDOC_TOP_LEVEL)) {
/**
* @param node
* @param autoCorrect
* @param emit
*/
override fun visit(
node: ASTNode,
autoCorrect: Boolean,
emit: EmitType
) {
emitWarn = emit
isFixMode = autoCorrect

override fun logic(node: ASTNode) {
val config = configRules.getCommonConfiguration().value
val filePath = node.getRootNode().getFilePath()
if (!(node.hasTestAnnotation() || isLocatedInTest(filePath.splitPathToDirs(), config.testAnchors))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.cqfn.diktat.ruleset.rules.chapter2.kdoc
import org.cqfn.diktat.common.config.rules.RuleConfiguration
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.getRuleConfig
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_CONTAINS_DATE_OR_AUTHOR
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_EMPTY_KDOC
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NEWLINES_BEFORE_BASIC_TAGS
Expand All @@ -13,6 +12,7 @@ import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NO_NEWLINES_BETWEEN_BASIC
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_NO_NEWLINE_AFTER_SPECIAL_TAGS
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_WRONG_SPACES_AFTER_TAG
import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_WRONG_TAGS_ORDER
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.allSiblings
import org.cqfn.diktat.ruleset.utils.findChildAfter
import org.cqfn.diktat.ruleset.utils.findChildBefore
Expand All @@ -23,7 +23,6 @@ import org.cqfn.diktat.ruleset.utils.hasChildMatching
import org.cqfn.diktat.ruleset.utils.kDocTags
import org.cqfn.diktat.ruleset.utils.leaveOnlyOneNewLine

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType
import com.pinterest.ktlint.core.ast.ElementType.KDOC
import com.pinterest.ktlint.core.ast.ElementType.KDOC_LEADING_ASTERISK
Expand Down Expand Up @@ -60,24 +59,20 @@ import java.time.temporal.ChronoField
* 7) ensuring @since tag contains only versions and not dates
*/
@Suppress("ForbiddenComment")
class KdocFormatting(private val configRules: List<RulesConfig>) : Rule("kdoc-formatting") {
class KdocFormatting(configRules: List<RulesConfig>) : DiktatRule("kdoc-formatting", configRules,
listOf(KDOC_CONTAINS_DATE_OR_AUTHOR, KDOC_EMPTY_KDOC, KDOC_NEWLINES_BEFORE_BASIC_TAGS, KDOC_NO_DEPRECATED_TAG,
KDOC_NO_EMPTY_TAGS, KDOC_NO_NEWLINES_BETWEEN_BASIC_TAGS, KDOC_NO_NEWLINE_AFTER_SPECIAL_TAGS,
KDOC_WRONG_SPACES_AFTER_TAG, KDOC_WRONG_TAGS_ORDER)) {
private val basicTagsList = listOf(KDocKnownTag.PARAM, KDocKnownTag.RETURN, KDocKnownTag.THROWS)
private val specialTagNames = setOf("implSpec", "implNote", "apiNote")
private var isFixMode: Boolean = false
private var versionRegex: Regex? = null
private lateinit var emitWarn: EmitType

/**
* @param node
* @param autoCorrect
* @param emit
*/
override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: EmitType) {
isFixMode = autoCorrect
emitWarn = emit

override fun logic(node: ASTNode) {
versionRegex ?: run {
versionRegex = KdocFormatConfiguration(
configRules.getRuleConfig(KDOC_CONTAINS_DATE_OR_AUTHOR)?.configuration ?: emptyMap()
Expand Down
Loading