diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRule.kt new file mode 100644 index 0000000000..e5fbf97058 --- /dev/null +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRule.kt @@ -0,0 +1,63 @@ +package org.cqfn.diktat.ruleset.rules + +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 com.pinterest.ktlint.core.Rule +import org.jetbrains.kotlin.com.intellij.lang.ASTNode +import kotlin.system.exitProcess + +private typealias DiktatConfigRule = org.cqfn.diktat.common.config.rules.Rule + +/** + * This is a wrapper around Ktlint Rule + * + * @param id id of the rule + * @property configRules all rules from configuration + * @property inspections warnings that are used in the rule's code + */ +@Suppress("TooGenericExceptionCaught") +abstract class DiktatRule(id: String, + val configRules: List, + val inspections: List) : Rule(id) { + /** + * Default value is false + */ + var isFixMode: Boolean = false + + /** + * Will be initialized in visit + */ + lateinit var emitWarn: EmitType + + override fun visit(node: ASTNode, + autoCorrect: Boolean, + emit: EmitType) { + emitWarn = emit + isFixMode = autoCorrect + + if (areInspectionsDisabled()) { + return + } else { + try { + logic(node) + } catch (internalError: Throwable) { + log.error("Internal error has occurred in $id. Please make an issue on this bug at https://github.com/cqfn/diKTat/.", internalError) + log.error("As a workaround you can disable these inspections in yml config: $inspections") + exitProcess(1) + } + } + } + + private fun areInspectionsDisabled(): Boolean = + inspections.none { configRules.isRuleEnabled(it) } + + /** + * Logic of the rule + * + * @param node node that are coming from visit + */ + abstract fun logic(node: ASTNode) +} diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/FileNaming.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/FileNaming.kt index 16b71d2074..26fc069de3 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/FileNaming.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/FileNaming.kt @@ -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 @@ -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) : Rule("file-naming") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType +class FileNaming(configRules: List) : 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()) { 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 974d5c8ab6..f80c6a6561 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 @@ -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 @@ -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 @@ -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 @@ -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) : Rule("identifier-naming") { +class IdentifierNaming(configRules: List) : 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 @@ -93,17 +96,10 @@ class IdentifierNaming(private val configRules: List) : 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 diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/PackageNaming.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/PackageNaming.kt index 1506e73958..8756f3d898 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/PackageNaming.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter1/PackageNaming.kt @@ -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 @@ -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) : Rule("package-naming") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType +class PackageNaming(configRules: List) : 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 diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/CommentsRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/CommentsRule.kt index d3413646c0..38d860bcbd 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/CommentsRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/CommentsRule.kt @@ -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 @@ -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) : Rule("comments") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType +class CommentsRule(configRules: List) : 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) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt index 0ee9564756..05c5a95469 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt @@ -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 @@ -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 @@ -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) : 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) : 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)) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/CommentsFormatting.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/CommentsFormatting.kt index 1bad4117e3..cd085de763 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/CommentsFormatting.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/CommentsFormatting.kt @@ -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 @@ -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) : Rule("kdoc-comments-codeblocks-formatting") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - +class CommentsFormatting(configRules: List) : 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()) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt index 017ae3022c..8e16f44d0f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt @@ -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 @@ -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) : Rule("kdoc-comments") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - +class KdocComments(configRules: List) : 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))) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocFormatting.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocFormatting.kt index c51d35729e..5fd4df686b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocFormatting.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocFormatting.kt @@ -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 @@ -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 @@ -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 @@ -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) : Rule("kdoc-formatting") { +class KdocFormatting(configRules: List) : 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() diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocMethods.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocMethods.kt index 5ba0bed00c..2e13a98b9f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocMethods.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/kdoc/KdocMethods.kt @@ -2,12 +2,12 @@ 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.KDOC_TRIVIAL_KDOC_ON_FUNCTION import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_WITHOUT_PARAM_TAG import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_WITHOUT_RETURN_TAG import org.cqfn.diktat.ruleset.constants.Warnings.KDOC_WITHOUT_THROWS_TAG import org.cqfn.diktat.ruleset.constants.Warnings.MISSING_KDOC_ON_FUNCTION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType @@ -30,7 +30,6 @@ import org.cqfn.diktat.ruleset.utils.kDocTags import org.cqfn.diktat.ruleset.utils.parameterNames import org.cqfn.diktat.ruleset.utils.splitPathToDirs -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.CALLABLE_REFERENCE_EXPRESSION @@ -66,21 +65,15 @@ import org.jetbrains.kotlin.psi.psiUtil.referenceExpression * Currently only `throw` keyword from this methods body is supported for `@throws` check. */ @Suppress("ForbiddenComment") -class KdocMethods(private val configRules: List) : Rule("kdoc-methods") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - +class KdocMethods(configRules: List) : DiktatRule("kdoc-methods", configRules, + listOf(KDOC_TRIVIAL_KDOC_ON_FUNCTION, KDOC_WITHOUT_PARAM_TAG, KDOC_WITHOUT_RETURN_TAG, + KDOC_WITHOUT_THROWS_TAG, MISSING_KDOC_ON_FUNCTION)) { /** * @param node * @param autoCorrect * @param emit */ - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit - + override fun logic(node: ASTNode) { if (node.elementType == FUN && node.getFirstChildWithType(MODIFIER_LIST).isAccessibleOutside() && !node.isOverridden()) { val config = configRules.getCommonConfiguration().value val filePath = node.getRootNode().getFilePath() diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/AnnotationNewLineRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/AnnotationNewLineRule.kt index 2d1e43229b..dbd1f16b1a 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/AnnotationNewLineRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/AnnotationNewLineRule.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.ANNOTATION_NEW_LINE +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.ANNOTATION_ENTRY import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.FUN @@ -20,16 +19,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) : Rule("annotation-new-line") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class AnnotationNewLineRule(configRules: List) : DiktatRule("annotation-new-line", configRules, listOf(ANNOTATION_NEW_LINE)) { + override fun logic(node: ASTNode) { when (node.elementType) { CLASS, FUN, PRIMARY_CONSTRUCTOR, SECONDARY_CONSTRUCTOR -> checkAnnotation(node) else -> return @@ -56,7 +47,7 @@ class AnnotationNewLineRule(private val configRules: List) : Rule(" private fun deleteSpaces(node: ASTNode, rightSide: Boolean) { - Warnings.ANNOTATION_NEW_LINE.warnAndFix(configRules, emitWarn, isFixMode, "${node.text} not on a single line", + ANNOTATION_NEW_LINE.warnAndFix(configRules, emitWarn, isFixMode, "${node.text} not on a single line", node.startOffset, node) { if (rightSide) { if (node.treeNext?.isWhiteSpace() == true) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BlockStructureBraces.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BlockStructureBraces.kt index 055d0b1cfb..fd1b254786 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BlockStructureBraces.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BlockStructureBraces.kt @@ -3,11 +3,10 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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.BRACES_BLOCK_STRUCTURE_ERROR +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.BODY import com.pinterest.ktlint.core.ast.ElementType.CATCH @@ -50,16 +49,8 @@ import org.jetbrains.kotlin.psi.KtTryExpression * - opening brace of lambda * - braces around `else`/`catch`/`finally`/`while` (in `do-while` loop) */ -class BlockStructureBraces(private val configRules: List) : Rule("block-structure") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class BlockStructureBraces(configRules: List) : DiktatRule("block-structure", configRules, listOf(BRACES_BLOCK_STRUCTURE_ERROR)) { + override fun logic(node: ASTNode) { val configuration = BlockStructureBracesConfiguration( configRules.getRuleConfig(BRACES_BLOCK_STRUCTURE_ERROR)?.configuration ?: emptyMap() ) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BracesInConditionalsAndLoopsRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BracesInConditionalsAndLoopsRule.kt index bde41f027d..d03b9a7dab 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BracesInConditionalsAndLoopsRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/BracesInConditionalsAndLoopsRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.NO_BRACES_IN_CONDITIONALS_AND_LOOPS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findChildrenMatching import org.cqfn.diktat.ruleset.utils.isSingleLineIfElse import org.cqfn.diktat.ruleset.utils.loopType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.DO_KEYWORD @@ -35,16 +34,8 @@ import org.jetbrains.kotlin.psi.psiUtil.astReplace /** * Rule that checks that all conditionals and loops have braces. */ -class BracesInConditionalsAndLoopsRule(private val configRules: List) : Rule("braces-rule") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class BracesInConditionalsAndLoopsRule(configRules: List) : DiktatRule("braces-rule", configRules, listOf(NO_BRACES_IN_CONDITIONALS_AND_LOOPS)) { + override fun logic(node: ASTNode) { when (node.elementType) { IF -> checkIfNode(node) WHEN -> checkWhenBranches(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ClassLikeStructuresOrderRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ClassLikeStructuresOrderRule.kt index a0e260122b..d3ef6941cc 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ClassLikeStructuresOrderRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ClassLikeStructuresOrderRule.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.BLANK_LINE_BETWEEN_PROPERTIES import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES +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 @@ -42,16 +41,9 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings /** * Rule that checks order of declarations inside classes, interfaces and objects. */ -class ClassLikeStructuresOrderRule(private val configRules: List) : Rule("class-like-structures") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ClassLikeStructuresOrderRule(configRules: List) : DiktatRule("class-like-structures", configRules, + listOf(BLANK_LINE_BETWEEN_PROPERTIES, WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS_BODY) { checkDeclarationsOrderInClass(node) } else if (node.elementType == PROPERTY) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ConsecutiveSpacesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ConsecutiveSpacesRule.kt index 43020086b9..caac371b96 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ConsecutiveSpacesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/ConsecutiveSpacesRule.kt @@ -3,10 +3,9 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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.TOO_MANY_CONSECUTIVE_SPACES +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ENUM_ENTRY import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE @@ -21,16 +20,8 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement * 2) If saveInitialFormattingForEnums is true then white spaces in enums will not be affected * */ -class ConsecutiveSpacesRule(private val configRules: List) : Rule("too-many-spaces") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ConsecutiveSpacesRule(configRules: List) : DiktatRule("too-many-spaces", configRules, listOf(TOO_MANY_CONSECUTIVE_SPACES)) { + override fun logic(node: ASTNode) { val configuration = TooManySpacesRuleConfiguration( configRules.getRuleConfig(TOO_MANY_CONSECUTIVE_SPACES)?.configuration ?: emptyMap()) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EmptyBlock.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EmptyBlock.kt index 1b8ccfe088..4525e11ea7 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EmptyBlock.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EmptyBlock.kt @@ -3,8 +3,8 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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.EMPTY_BLOCK_STRUCTURE_ERROR +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findLBrace import org.cqfn.diktat.ruleset.utils.findLeafWithSpecificType import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType @@ -13,7 +13,6 @@ import org.cqfn.diktat.ruleset.utils.isBlockEmpty import org.cqfn.diktat.ruleset.utils.isOverridden import org.cqfn.diktat.ruleset.utils.isPascalCase -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_LITERAL import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER @@ -26,16 +25,8 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl /** * Rule that checks if empty code blocks (`{ }`) are used and checks their formatting. */ -class EmptyBlock(private val configRules: List) : Rule("empty-block-structure") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class EmptyBlock(configRules: List) : DiktatRule("empty-block-structure", configRules, listOf(EMPTY_BLOCK_STRUCTURE_ERROR)) { + override fun logic(node: ASTNode) { val configuration = EmptyBlockStyleConfiguration( configRules.getRuleConfig(EMPTY_BLOCK_STRUCTURE_ERROR)?.configuration ?: emptyMap() ) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EnumsSeparated.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EnumsSeparated.kt index f3572561ca..cbe6e1c8e9 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EnumsSeparated.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/EnumsSeparated.kt @@ -1,15 +1,14 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.ENUMS_SEPARATED +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.allSiblings import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.isClassEnum -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.COMMA @@ -27,16 +26,8 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl /** * Rule that checks enum classes formatting */ -class EnumsSeparated(private val configRules: List) : Rule("enum-separated") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class EnumsSeparated(configRules: List) : DiktatRule("enum-separated", configRules, listOf(ENUMS_SEPARATED)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS && node.hasChildOfType(CLASS_BODY)) { if (node.isClassEnum()) { checkEnumEntry(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt index 608abb0106..92612f05be 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt @@ -3,14 +3,13 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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.LONG_LINE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace import org.cqfn.diktat.ruleset.utils.calculateLineColByOffset import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.BOOLEAN_CONSTANT @@ -58,17 +57,10 @@ import java.net.URL * Rule can fix long binary expressions in condition inside `if` and in property declarations and one line functions */ @Suppress("ForbiddenComment") -class LineLength(private val configRules: List) : Rule("line-length") { - private var isFixMode: Boolean = false +class LineLength(configRules: List) : DiktatRule("line-length", configRules, listOf(LONG_LINE)) { private lateinit var positionByOffset: (Int) -> Pair - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { val configuration = LineLengthConfiguration( configRules.getRuleConfig(LONG_LINE)?.configuration ?: emptyMap()) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LongNumericalValuesSeparatedRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LongNumericalValuesSeparatedRule.kt index 9a4435361f..93da60e617 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LongNumericalValuesSeparatedRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LongNumericalValuesSeparatedRule.kt @@ -3,10 +3,9 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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 +import org.cqfn.diktat.ruleset.constants.Warnings.LONG_NUMERICAL_VALUES_SEPARATED +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.FLOAT_LITERAL import com.pinterest.ktlint.core.ast.ElementType.INTEGER_LITERAL import org.jetbrains.kotlin.com.intellij.lang.ASTNode @@ -17,22 +16,14 @@ import java.lang.StringBuilder /** * Rule that checks if numerical separators (`_`) are used for long numerical literals */ -class LongNumericalValuesSeparatedRule(private val configRules: List) : Rule("long-numerical-values") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class LongNumericalValuesSeparatedRule(configRules: List) : DiktatRule("long-numerical-values", configRules, listOf(LONG_NUMERICAL_VALUES_SEPARATED)) { + override fun logic(node: ASTNode) { val configuration = LongNumericalValuesConfiguration( - configRules.getRuleConfig(Warnings.LONG_NUMERICAL_VALUES_SEPARATED)?.configuration ?: emptyMap()) + configRules.getRuleConfig(LONG_NUMERICAL_VALUES_SEPARATED)?.configuration ?: emptyMap()) if (node.elementType == INTEGER_LITERAL) { if (!isValidConstant(node.text, configuration, node)) { - Warnings.LONG_NUMERICAL_VALUES_SEPARATED.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { + LONG_NUMERICAL_VALUES_SEPARATED.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { fixIntegerConstant(node, configuration.maxBlockLength) } } @@ -42,7 +33,7 @@ class LongNumericalValuesSeparatedRule(private val configRules: List configuration.maxBlockLength) { - Warnings.LONG_NUMERICAL_VALUES_SEPARATED.warn(configRules, emitWarn, false, "this block is too long $it", node.startOffset, node) + LONG_NUMERICAL_VALUES_SEPARATED.warn(configRules, emitWarn, false, "this block is too long $it", node.startOffset, node) } } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/MultipleModifiersSequence.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/MultipleModifiersSequence.kt index b4c9d2b676..113c2b9077 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/MultipleModifiersSequence.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/MultipleModifiersSequence.kt @@ -1,10 +1,9 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_MULTIPLE_MODIFIERS_ORDER +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ANNOTATION_ENTRY import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE @@ -16,16 +15,8 @@ import org.jetbrains.kotlin.psi.psiUtil.children /** * @property configRules */ -class MultipleModifiersSequence(private val configRules: List) : Rule("multiple-modifiers") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class MultipleModifiersSequence(configRules: List) : DiktatRule("multiple-modifiers", configRules, listOf(WRONG_MULTIPLE_MODIFIERS_ORDER)) { + override fun logic(node: ASTNode) { if (node.elementType == MODIFIER_LIST) { checkModifierList(node) checkAnnotation(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/NullableTypeRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/NullableTypeRule.kt index 813781ae0a..8215f3b5a5 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/NullableTypeRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/NullableTypeRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.NULLABLE_PROPERTY_TYPE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BOOLEAN_CONSTANT import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.CHARACTER_CONSTANT @@ -38,16 +37,8 @@ import org.jetbrains.kotlin.com.intellij.psi.tree.IElementType /** * Rule that checks if nullable types are used and suggest to substitute them with non-nullable */ -class NullableTypeRule(private val configRules: List) : Rule("nullable-type") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit - +class NullableTypeRule(configRules: List) : DiktatRule("nullable-type", configRules, listOf(NULLABLE_PROPERTY_TYPE)) { + override fun logic(node: ASTNode) { if (node.elementType == PROPERTY) { checkProperty(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SingleLineStatementsRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SingleLineStatementsRule.kt index 48e0b7c178..806dafa989 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SingleLineStatementsRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SingleLineStatementsRule.kt @@ -1,14 +1,13 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.MORE_THAN_ONE_STATEMENT_PER_LINE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace import org.cqfn.diktat.ruleset.utils.extractLineOfText import org.cqfn.diktat.ruleset.utils.isBeginByNewline import org.cqfn.diktat.ruleset.utils.isFollowedByNewline -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ENUM_ENTRY import com.pinterest.ktlint.core.ast.ElementType.SEMICOLON import com.pinterest.ktlint.core.ast.parent @@ -19,16 +18,8 @@ import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet /** * Rule that looks for multiple statements on a single line separated with a `;` and splits them in multiple lines. */ -class SingleLineStatementsRule(private val configRules: List) : Rule("statement") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class SingleLineStatementsRule(configRules: List) : DiktatRule("statement", configRules, listOf(MORE_THAN_ONE_STATEMENT_PER_LINE)) { + override fun logic(node: ASTNode) { checkSemicolon(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt index d2cd57178d..8f9179558f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt @@ -3,12 +3,11 @@ package org.cqfn.diktat.ruleset.rules.chapter3 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.WRONG_DECLARATIONS_ORDER +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.isClassEnum -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.COMMA @@ -27,16 +26,8 @@ import org.jetbrains.kotlin.psi.KtObjectDeclaration /** * Rule that sorts class properties and enum members alphabetically */ -class SortRule(private val configRules: List) : Rule("sort-rule") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class SortRule(configRules: List) : DiktatRule("sort-rule", configRules, listOf(WRONG_DECLARATIONS_ORDER)) { + override fun logic(node: ASTNode) { val configuration = SortRuleConfiguration( configRules.getRuleConfig(WRONG_DECLARATIONS_ORDER)?.configuration ?: emptyMap() ) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt index e3b4918316..cdd52d046d 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.STRING_CONCATENATION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.OPERATION_REFERENCE import com.pinterest.ktlint.core.ast.ElementType.PLUS @@ -20,16 +19,8 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode * // FixMe: fixes will be added * // FixMe: .toString() method and functions that return strings are not supported */ -class StringConcatenationRule(private val configRules: List) : Rule("string-concatenation") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class StringConcatenationRule(configRules: List) : DiktatRule("string-concatenation", configRules, listOf(STRING_CONCATENATION)) { + override fun logic(node: ASTNode) { if (node.elementType == BINARY_EXPRESSION) { // searching top-level binary expression to detect any operations with "plus" (+) // string concatenation is prohibited only for single line statements diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringTemplateFormatRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringTemplateFormatRule.kt index f12edd04ab..00563eaf29 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringTemplateFormatRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringTemplateFormatRule.kt @@ -2,11 +2,12 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.STRING_TEMPLATE_CURLY_BRACES +import org.cqfn.diktat.ruleset.constants.Warnings.STRING_TEMPLATE_QUOTES +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.hasAnyChildOfTypes -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ARRAY_ACCESS_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.CLOSING_QUOTE import com.pinterest.ktlint.core.ast.ElementType.FLOAT_CONSTANT @@ -27,16 +28,9 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement * * FixMe: The important caveat here: in "$foo" kotlin compiler adds implicit call to foo.toString() in case foo type is not string. */ -class StringTemplateFormatRule(private val configRules: List) : Rule("string-template-format") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class StringTemplateFormatRule(configRules: List) : DiktatRule("string-template-format", configRules, + listOf(STRING_TEMPLATE_CURLY_BRACES, STRING_TEMPLATE_QUOTES)) { + override fun logic(node: ASTNode) { when (node.elementType) { LONG_STRING_TEMPLATE_ENTRY -> handleLongStringTemplate(node) SHORT_STRING_TEMPLATE_ENTRY -> handleShortStringTemplate(node) @@ -49,7 +43,7 @@ class StringTemplateFormatRule(private val configRules: List) : Rul private fun handleLongStringTemplate(node: ASTNode) { // Checking if in long templates {a.foo()} there are function calls or class toString call if (bracesCanBeOmitted(node)) { - Warnings.STRING_TEMPLATE_CURLY_BRACES.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { + STRING_TEMPLATE_CURLY_BRACES.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { val identifierName = node.findChildByType(REFERENCE_EXPRESSION) identifierName?.let { val shortTemplate = CompositeElement(SHORT_STRING_TEMPLATE_ENTRY) @@ -76,7 +70,7 @@ class StringTemplateFormatRule(private val configRules: List) : Rul val identifierName = node.findChildByType(REFERENCE_EXPRESSION)?.text if (identifierName != null && node.treeParent.text.trim('"', '$') == identifierName) { - Warnings.STRING_TEMPLATE_QUOTES.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { + STRING_TEMPLATE_QUOTES.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { val identifier = node.findChildByType(REFERENCE_EXPRESSION)!!.copyElement() // node.treeParent is String template that we need to delete node.treeParent.treeParent.addChild(identifier, node.treeParent) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt index cfdeb9b962..4d2d29c23a 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt @@ -4,11 +4,10 @@ import org.cqfn.diktat.common.config.rules.RuleConfiguration import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.common.config.rules.getCommonConfiguration import org.cqfn.diktat.common.config.rules.getRuleConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.TRAILING_COMMA +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.log -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.COLLECTION_LITERAL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.COMMA import com.pinterest.ktlint.core.ast.ElementType.DESTRUCTURING_DECLARATION @@ -50,8 +49,7 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings * [12] Destructuring declarations */ @Suppress("TOO_LONG_FUNCTION") -class TrailingCommaRule(private val configRules: List) : Rule("trailing-comma") { - private var isFixMode: Boolean = false +class TrailingCommaRule(configRules: List) : DiktatRule("trailing-comma", configRules, listOf(TRAILING_COMMA)) { private val commonConfig by configRules.getCommonConfiguration() private val trailingConfig = this.configRules.getRuleConfig(TRAILING_COMMA)?.configuration ?: emptyMap() private val configuration by lazy { @@ -61,16 +59,8 @@ class TrailingCommaRule(private val configRules: List) : Rule("trai } TrailingCommaConfiguration(trailingConfig) } - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (commonConfig.kotlinVersion >= ktVersion) { val (type, config) = when (node.elementType) { VALUE_ARGUMENT_LIST -> Pair(VALUE_ARGUMENT, configuration.getParam("valueArgument")) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/WhenMustHaveElseRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/WhenMustHaveElseRule.kt index 31e600f083..f40c874d7f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/WhenMustHaveElseRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/WhenMustHaveElseRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter3 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.WHEN_WITHOUT_ELSE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace import org.cqfn.diktat.ruleset.utils.hasParent import org.cqfn.diktat.ruleset.utils.isBeginByNewline -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.ARROW import com.pinterest.ktlint.core.ast.ElementType.BLOCK @@ -37,16 +36,8 @@ import org.jetbrains.kotlin.psi.KtWhenExpression * The compiler can issue a warning when it is missing. */ @Suppress("ForbiddenComment") -class WhenMustHaveElseRule(private val configRules: List) : Rule("no-else-in-when") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class WhenMustHaveElseRule(configRules: List) : DiktatRule("no-else-in-when", configRules, listOf(WHEN_WITHOUT_ELSE)) { + override fun logic(node: ASTNode) { if (node.elementType == ElementType.WHEN && isStatement(node)) { checkEntries(node) } @@ -54,7 +45,7 @@ class WhenMustHaveElseRule(private val configRules: List) : Rule("n private fun checkEntries(node: ASTNode) { if (!hasElse(node)) { - Warnings.WHEN_WITHOUT_ELSE.warnAndFix(configRules, emitWarn, isFixMode, "else was not found", node.startOffset, node) { + WHEN_WITHOUT_ELSE.warnAndFix(configRules, emitWarn, isFixMode, "else was not found", node.startOffset, node) { val whenEntryElse = CompositeElement(WHEN_ENTRY) if (!node.lastChildNode.isBeginByNewline()) { node.appendNewlineMergingWhiteSpace(node.lastChildNode.treePrev, node.lastChildNode) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/BlankLinesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/BlankLinesRule.kt index d602e7c8bb..2cd8be0c2e 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/BlankLinesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/BlankLinesRule.kt @@ -1,20 +1,17 @@ package org.cqfn.diktat.ruleset.rules.chapter3.files import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.TOO_MANY_BLANK_LINES -import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.leaveExactlyNumNewLines import org.cqfn.diktat.ruleset.utils.leaveOnlyOneNewLine import org.cqfn.diktat.ruleset.utils.numNewLines -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.FILE import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_LITERAL -import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.LBRACE import com.pinterest.ktlint.core.ast.ElementType.RBRACE import com.pinterest.ktlint.core.ast.ElementType.SCRIPT @@ -26,16 +23,8 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode * 1. Checks that no more than two consecutive blank lines are used in a row * 2. Checks that blank lines are not put in the beginning or at the end of code blocks with curly braces */ -class BlankLinesRule(private val configRules: List) : Rule("blank-lines") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class BlankLinesRule(configRules: List) : DiktatRule("blank-lines", configRules, listOf(TOO_MANY_BLANK_LINES)) { + override fun logic(node: ASTNode) { if (node.elementType == WHITE_SPACE) { // note that no blank lines counts as one newline if (node.numNewLines() == 2) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileSize.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileSize.kt index 2aacf55407..e9d8086b2b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileSize.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileSize.kt @@ -3,12 +3,11 @@ package org.cqfn.diktat.ruleset.rules.chapter3.files 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.FILE_IS_TOO_LONG +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getFilePath import org.cqfn.diktat.ruleset.utils.splitPathToDirs -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.slf4j.LoggerFactory @@ -16,20 +15,14 @@ import org.slf4j.LoggerFactory /** * Rule that checks number of lines in a file */ -class FileSize(private val configRules: List) : Rule("file-size") { - private var isFixMode: Boolean = false +class FileSize(configRules: List) : DiktatRule("file-size", configRules, listOf(FILE_IS_TOO_LONG)) { private val configuration by lazy { FileSizeConfiguration( this.configRules.getRuleConfig(FILE_IS_TOO_LONG)?.configuration ?: emptyMap() ) } - private lateinit var emitWarn: EmitType - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType == ElementType.FILE) { val filePathParts = node.getFilePath().splitPathToDirs() if (SRC_PATH !in filePathParts) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileStructureRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileStructureRule.kt index af0d204bb2..76ec154d8f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileStructureRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/FileStructureRule.kt @@ -4,13 +4,13 @@ import org.cqfn.diktat.common.config.rules.RuleConfiguration import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.common.config.rules.getCommonConfiguration import org.cqfn.diktat.common.config.rules.getRuleConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.FILE_CONTAINS_ONLY_COMMENTS import org.cqfn.diktat.ruleset.constants.Warnings.FILE_INCORRECT_BLOCKS_ORDER import org.cqfn.diktat.ruleset.constants.Warnings.FILE_NO_BLANK_LINE_BETWEEN_BLOCKS import org.cqfn.diktat.ruleset.constants.Warnings.FILE_UNORDERED_IMPORTS import org.cqfn.diktat.ruleset.constants.Warnings.FILE_WILDCARD_IMPORTS import org.cqfn.diktat.ruleset.constants.Warnings.UNUSED_IMPORT +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.rules.chapter1.PackageNaming.Companion.PACKAGE_SEPARATOR import org.cqfn.diktat.ruleset.utils.StandardPlatforms import org.cqfn.diktat.ruleset.utils.copyrightWords @@ -19,7 +19,6 @@ import org.cqfn.diktat.ruleset.utils.handleIncorrectOrder import org.cqfn.diktat.ruleset.utils.moveChildBefore import org.cqfn.diktat.ruleset.utils.operatorMap -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 @@ -56,8 +55,9 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings * 4. Ensures imports are ordered alphabetically without blank lines * 5. Ensures there are no wildcard imports */ -class FileStructureRule(private val configRules: List) : Rule("file-structure") { - private var isFixMode: Boolean = false +class FileStructureRule(configRules: List) : DiktatRule("file-structure", configRules, + listOf(FILE_CONTAINS_ONLY_COMMENTS, FILE_INCORRECT_BLOCKS_ORDER, FILE_NO_BLANK_LINE_BETWEEN_BLOCKS, + FILE_UNORDERED_IMPORTS, FILE_WILDCARD_IMPORTS, UNUSED_IMPORT)) { private val domainName by lazy { configRules .getCommonConfiguration() @@ -73,14 +73,8 @@ class FileStructureRule(private val configRules: List) : Rule("file } private val refSet: MutableSet = mutableSetOf() private var packageName = "" - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit + override fun logic(node: ASTNode) { if (node.elementType == FILE) { val wildcardImportsConfig = WildCardImportsConfig( this.configRules.getRuleConfig(FILE_WILDCARD_IMPORTS)?.configuration ?: emptyMap() 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 1af2aa40ec..79a3aac6cc 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 @@ -6,8 +6,8 @@ package org.cqfn.diktat.ruleset.rules.chapter3.files 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.WRONG_INDENTATION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getAllLeafsWithSpecificType import org.cqfn.diktat.ruleset.utils.getFilePath @@ -26,7 +26,6 @@ import org.cqfn.diktat.ruleset.utils.indentation.ValueParameterListChecker import org.cqfn.diktat.ruleset.utils.leaveOnlyOneNewLine import org.cqfn.diktat.ruleset.utils.log -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.ELSE @@ -65,21 +64,14 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult * Additionally, a set of CustomIndentationChecker objects checks all WHITE_SPACE node if they are exceptions from general rules. * @see CustomIndentationChecker */ -class IndentationRule(private val configRules: List) : Rule("indentation") { - private var isFixMode: Boolean = false +class IndentationRule(configRules: List) : DiktatRule("indentation", configRules, listOf(WRONG_INDENTATION)) { private val configuration: IndentationConfig by lazy { IndentationConfig(configRules.getRuleConfig(WRONG_INDENTATION)?.configuration ?: emptyMap()) } private lateinit var filePath: String - private lateinit var emitWarn: EmitType private lateinit var customIndentationCheckers: List - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit - + override fun logic(node: ASTNode) { if (node.elementType == FILE) { filePath = node.getFilePath() diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt index 60d9d0a211..d75eedfcaa 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt @@ -3,14 +3,13 @@ package org.cqfn.diktat.ruleset.rules.chapter3.files 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.ListOfList import org.cqfn.diktat.ruleset.constants.Warnings.COMPLEX_EXPRESSION import org.cqfn.diktat.ruleset.constants.Warnings.REDUNDANT_SEMICOLON import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_NEWLINES +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.ANDAND import com.pinterest.ktlint.core.ast.ElementType.ARROW import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION @@ -96,19 +95,11 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings * 10. Complex expression inside condition replaced with new variable */ @Suppress("ForbiddenComment") -class NewlinesRule(private val configRules: List) : Rule("newlines") { +class NewlinesRule(configRules: List) : DiktatRule("newlines", configRules, listOf(COMPLEX_EXPRESSION, REDUNDANT_SEMICOLON, WRONG_NEWLINES)) { private val configuration by lazy { NewlinesRuleConfiguration(configRules.getRuleConfig(WRONG_NEWLINES)?.configuration ?: emptyMap()) } - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit - + override fun logic(node: ASTNode) { when (node.elementType) { SEMICOLON -> handleSemicolon(node) OPERATION_REFERENCE, EQ -> handleOperatorWithLineBreakAfter(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/WhiteSpaceRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/WhiteSpaceRule.kt index 7a56d93ec2..b05694f620 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/WhiteSpaceRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/WhiteSpaceRule.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter3.files import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_WHITESPACE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.log -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ANNOTATION_ENTRY import com.pinterest.ktlint.core.ast.ElementType.ARROW import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION @@ -93,16 +92,9 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf * 10. There should be no spaces between prefix/postfix operator (like `!!` or `++`) and it's operand */ @Suppress("ForbiddenComment") -class WhiteSpaceRule(private val configRules: List) : Rule("horizontal-whitespace") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType +class WhiteSpaceRule(configRules: List) : DiktatRule("horizontal-whitespace", configRules, listOf(WRONG_WHITESPACE)) { @Suppress("ComplexMethod") - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - + override fun logic(node: ASTNode) { when (node.elementType) { // keywords CONSTRUCTOR_KEYWORD -> handleConstructor(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt index 9d34d51248..6f5c2880c9 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt @@ -1,8 +1,8 @@ package org.cqfn.diktat.ruleset.rules.chapter3.identifiers import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.LOCAL_VARIABLE_EARLY_DECLARATION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.containsOnlyConstants import org.cqfn.diktat.ruleset.utils.getDeclarationScope import org.cqfn.diktat.ruleset.utils.getLineNumber @@ -10,7 +10,6 @@ import org.cqfn.diktat.ruleset.utils.lastLineNumber import org.cqfn.diktat.ruleset.utils.numNewLines import org.cqfn.diktat.ruleset.utils.search.findAllVariablesWithUsages -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.FILE import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import com.pinterest.ktlint.core.ast.isPartOfComment @@ -38,16 +37,8 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset * * Only properties without initialization or initialized with expressions based on constants are supported. * * Properties initialized with constructor calls cannot be distinguished from method call and are no supported. */ -class LocalVariablesRule(private val configRules: List) : Rule("local-variables") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class LocalVariablesRule(configRules: List) : DiktatRule("local-variables", configRules, listOf(LOCAL_VARIABLE_EARLY_DECLARATION)) { + override fun logic(node: ASTNode) { if (node.elementType == FILE) { // collect all local properties and associate with corresponding references val propertiesToUsages = collectLocalPropertiesWithUsages(node) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/ImmutableValNoVarRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/ImmutableValNoVarRule.kt index d55abfcca1..1c1c41889b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/ImmutableValNoVarRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/ImmutableValNoVarRule.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter4 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.SAY_NO_TO_VAR +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.search.findAllVariablesWithAssignments import org.cqfn.diktat.ruleset.utils.search.findAllVariablesWithUsages -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.psi.KtBlockExpression @@ -20,16 +19,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType * because `var` variables can be reassigned several times in the business logic. Of course, in some scenarios with loops or accumulators only `var`s can be used and are allowed. * FixMe: here we should also raise warnings for a reassignment of a var (if var has no assignments except in declaration - it can be final) */ -class ImmutableValNoVarRule(private val configRules: List) : Rule("no-var-rule") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ImmutableValNoVarRule(configRules: List) : DiktatRule("no-var-rule", configRules, listOf(SAY_NO_TO_VAR)) { + override fun logic(node: ASTNode) { if (node.elementType == ElementType.FILE) { // we will raise warning for cases when var property has no assignments val varNoAssignments = node diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/NullChecksRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/NullChecksRule.kt index 79dff69830..366cff96d0 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/NullChecksRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/NullChecksRule.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter4 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.AVOID_NULL_CHECKS +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 import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.CONDITION @@ -27,16 +26,8 @@ import org.jetbrains.kotlin.psi.KtIfExpression * This rule check and fixes explicit null checks (explicit comparison with `null`) * There are several code-structures that can be used in Kotlin to avoid null-checks. For example: `?:`, `.let {}`, `.also {}`, e.t.c */ -class NullChecksRule(private val configRules: List) : Rule("null-checks") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class NullChecksRule(configRules: List) : DiktatRule("null-checks", configRules, listOf(AVOID_NULL_CHECKS)) { + override fun logic(node: ASTNode) { if (node.elementType == CONDITION) { node.parent(IF)?.let { // excluding complex cases with else-if statements, because they look better with explicit null-check diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/SmartCastRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/SmartCastRule.kt index 6d140c3929..45bbe16327 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/SmartCastRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/SmartCastRule.kt @@ -1,8 +1,8 @@ package org.cqfn.diktat.ruleset.rules.chapter4 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.SMART_CAST_NEEDED +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType @@ -12,7 +12,6 @@ import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.hasParent import org.cqfn.diktat.ruleset.utils.search.findAllVariablesWithUsages -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BINARY_WITH_TYPE import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION @@ -40,16 +39,8 @@ import org.jetbrains.kotlin.psi.psiUtil.parents /** * Rule that detects redundant explicit casts */ -class SmartCastRule(private val configRules: List) : Rule("smart-cast-rule") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class SmartCastRule(configRules: List) : DiktatRule("smart-cast-rule", configRules, listOf(SMART_CAST_NEEDED)) { + override fun logic(node: ASTNode) { if (node.elementType == FILE) { val usages = collectLocalPropertiesWithUsages(node) val properMap = collectReferenceList(usages) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/TypeAliasRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/TypeAliasRule.kt index c4aa2239ad..41e46615b6 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/TypeAliasRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/TypeAliasRule.kt @@ -3,11 +3,10 @@ package org.cqfn.diktat.ruleset.rules.chapter4 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.TYPE_ALIAS +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.LT import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_LIST import com.pinterest.ktlint.core.ast.ElementType.TYPEALIAS @@ -20,16 +19,8 @@ import org.jetbrains.kotlin.psi.psiUtil.parents * This rule checks if variable has long type reference and two or more nested generics. * Length type reference can be configured */ -class TypeAliasRule(private val configRules: List) : Rule("type-alias") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class TypeAliasRule(configRules: List) : DiktatRule("type-alias", configRules, listOf(TYPE_ALIAS)) { + override fun logic(node: ASTNode) { if (node.elementType == TYPE_REFERENCE && node .parents() .map { it.elementType } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/VariableGenericTypeDeclarationRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/VariableGenericTypeDeclarationRule.kt index 55ca6458c6..07a24644c7 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/VariableGenericTypeDeclarationRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/VariableGenericTypeDeclarationRule.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter4 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.GENERIC_VARIABLE_WRONG_DECLARATION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.PROPERTY @@ -22,16 +21,9 @@ import org.jetbrains.kotlin.psi.KtProperty * Recommended: val myVariable: Map = emptyMap() */ // FIXME: we now don't have access to return types, so we can perform this check only if explicit type is present, but should be able also if it's not. -class VariableGenericTypeDeclarationRule(private val configRules: List) : Rule("variable-generic-type") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class VariableGenericTypeDeclarationRule(configRules: List) : DiktatRule("variable-generic-type", configRules, + listOf(GENERIC_VARIABLE_WRONG_DECLARATION)) { + override fun logic(node: ASTNode) { when (node.elementType) { PROPERTY, VALUE_PARAMETER -> handleProperty(node) else -> { @@ -63,14 +55,14 @@ class VariableGenericTypeDeclarationRule(private val configRules: List first.text == second.text }) { - Warnings.GENERIC_VARIABLE_WRONG_DECLARATION.warnAndFix(configRules, emitWarn, isFixMode, + GENERIC_VARIABLE_WRONG_DECLARATION.warnAndFix(configRules, emitWarn, isFixMode, "type arguments are unnecessary in ${callExpr.text}", node.startOffset, node) { callExpr.removeChild(callExpr.findChildByType(TYPE_ARGUMENT_LIST)!!) } } if (leftSide == null && rightSide != null) { - Warnings.GENERIC_VARIABLE_WRONG_DECLARATION.warn(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) + GENERIC_VARIABLE_WRONG_DECLARATION.warn(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) } } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/calculations/AccurateCalculationsRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/calculations/AccurateCalculationsRule.kt index 5bff177c52..cb40295a68 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/calculations/AccurateCalculationsRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter4/calculations/AccurateCalculationsRule.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter4.calculations import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.FLOAT_IN_ACCURATE_CALCULATIONS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findLocalDeclaration import org.cqfn.diktat.ruleset.utils.getFunctionName -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.PsiElement @@ -25,10 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset * Exception: allows arithmetic operations only when absolute value of result is immediately used in comparison * Fixme: detect variables by type, not only floating-point literals */ -class AccurateCalculationsRule(private val configRules: List) : Rule("accurate-calculations") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - +class AccurateCalculationsRule(configRules: List) : DiktatRule("accurate-calculations", configRules, listOf(FLOAT_IN_ACCURATE_CALCULATIONS)) { private fun KtCallExpression?.isAbsOfFloat() = this ?.run { (calleeExpression as? KtNameReferenceExpression) @@ -114,12 +110,7 @@ class AccurateCalculationsRule(private val configRules: List) : Rul * @param autoCorrect * @param emit */ - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - + override fun logic(node: ASTNode) { when (val psi = node.psi) { is KtBinaryExpression -> handleBinaryExpression(psi) is KtDotQualifiedExpression -> handleFunction(psi) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AsyncAndSyncRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AsyncAndSyncRule.kt index 99b899dcf9..927b6fb637 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AsyncAndSyncRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AsyncAndSyncRule.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.RUN_BLOCKING_INSIDE_ASYNC +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.FUN import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_ARGUMENT @@ -18,17 +17,10 @@ import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier /** * This rule finds if using runBlocking in asynchronous code */ -class AsyncAndSyncRule(private val configRules: List) : Rule("sync-in-async") { +class AsyncAndSyncRule(configRules: List) : DiktatRule("sync-in-async", configRules, listOf(RUN_BLOCKING_INSIDE_ASYNC)) { private val asyncList = listOf("async", "launch") - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.isRunBlocking()) { checkRunBlocking(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AvoidNestedFunctionsRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AvoidNestedFunctionsRule.kt index 22cd128edd..e597764640 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AvoidNestedFunctionsRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/AvoidNestedFunctionsRule.kt @@ -1,14 +1,13 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.AVOID_NESTED_FUNCTIONS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.hasParent -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.FUN import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER @@ -25,16 +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) : Rule("avoid-nested-functions") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class AvoidNestedFunctionsRule(configRules: List) : DiktatRule("avoid-nested-functions", configRules, listOf(AVOID_NESTED_FUNCTIONS)) { + override fun logic(node: ASTNode) { if (node.elementType == FUN) { handleNestedFunctions(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CheckInverseMethodRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CheckInverseMethodRule.kt index ef009953fb..8c92f48a18 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CheckInverseMethodRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CheckInverseMethodRule.kt @@ -1,10 +1,9 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.INVERSE_FUNCTION_PREFERRED +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER @@ -23,16 +22,8 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings * This rule checks if inverse method can be used. * For example if there is !isEmpty() on collection call that it changes it to isNotEmpty() */ -class CheckInverseMethodRule(private val configRules: List) : Rule("inverse-method") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class CheckInverseMethodRule(configRules: List) : DiktatRule("inverse-method", configRules, listOf(INVERSE_FUNCTION_PREFERRED)) { + override fun logic(node: ASTNode) { if (node.elementType == CALL_EXPRESSION && node.text in methodMap.keys) { checkCallExpressionName(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CustomLabel.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CustomLabel.kt index 175572475b..518040b1b3 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CustomLabel.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/CustomLabel.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.CUSTOM_LABEL +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.loopType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BREAK import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.CONTINUE @@ -18,19 +17,12 @@ import org.jetbrains.kotlin.psi.psiUtil.parents /** * Rule that checks using custom label */ -class CustomLabel(private val configRules: List) : Rule("custom-label") { - private var isFixMode: Boolean = false +class CustomLabel(configRules: List) : DiktatRule("custom-label", configRules, listOf(CUSTOM_LABEL)) { private val forEachReference = listOf("forEach", "forEachIndexed") private val labels = listOf("@loop", "@forEach", "@forEachIndexed") private val stopWords = listOf(RETURN, BREAK, CONTINUE) - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType == LABEL_QUALIFIER && node.text !in labels && node.treeParent.elementType in stopWords) { val nestedCount = node.parents().count { it.elementType in loopType || diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionArgumentsSize.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionArgumentsSize.kt index 3d66bc5fea..5f07f8a9f2 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionArgumentsSize.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionArgumentsSize.kt @@ -3,10 +3,9 @@ package org.cqfn.diktat.ruleset.rules.chapter5 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.TOO_MANY_PARAMETERS +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER import org.jetbrains.kotlin.com.intellij.lang.ASTNode @@ -15,19 +14,12 @@ import org.jetbrains.kotlin.psi.KtFunction /** * Rule that checks that function doesn't contains too many parameters */ -class FunctionArgumentsSize(private val configRules: List) : Rule("argument-size") { - private var isFixMode: Boolean = false +class FunctionArgumentsSize(configRules: List) : DiktatRule("argument-size", configRules, listOf(TOO_MANY_PARAMETERS)) { private val configuration: FunctionArgumentsSizeConfiguration by lazy { FunctionArgumentsSizeConfiguration(configRules.getRuleConfig(TOO_MANY_PARAMETERS)?.configuration ?: emptyMap()) } - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType == ElementType.FUN) { checkFun(node, configuration.maxParameterSize) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionLength.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionLength.kt index 907111ad8e..670fef2377 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionLength.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/FunctionLength.kt @@ -3,11 +3,10 @@ package org.cqfn.diktat.ruleset.rules.chapter5 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.TOO_LONG_FUNCTION +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.FUN import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.psi.KtFunction @@ -15,16 +14,8 @@ import org.jetbrains.kotlin.psi.KtFunction /** * Rule 5.1.1 check function length */ -class FunctionLength(private val configRules: List) : Rule("function-length") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class FunctionLength(configRules: List) : DiktatRule("function-length", configRules, listOf(TOO_LONG_FUNCTION)) { + override fun logic(node: ASTNode) { val configuration = FunctionLengthConfiguration( configRules.getRuleConfig(TOO_LONG_FUNCTION)?.configuration ?: emptyMap() ) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaLengthRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaLengthRule.kt index 69f5d77969..f231535a74 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaLengthRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaLengthRule.kt @@ -3,34 +3,24 @@ package org.cqfn.diktat.ruleset.rules.chapter5 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 +import org.cqfn.diktat.ruleset.constants.Warnings.TOO_MANY_LINES_IN_LAMBDA +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 import org.jetbrains.kotlin.com.intellij.lang.ASTNode /** * Rule 5.2.5 check lambda length without parameters */ -class LambdaLengthRule(private val configRules: List) : Rule("lambda-length") { +class LambdaLengthRule(configRules: List) : DiktatRule("lambda-length", configRules, listOf(TOO_MANY_LINES_IN_LAMBDA)) { private val configuration by lazy { LambdaLengthConfiguration( - this.configRules.getRuleConfig(Warnings.TOO_MANY_LINES_IN_LAMBDA)?.configuration ?: emptyMap() + this.configRules.getRuleConfig(TOO_MANY_LINES_IN_LAMBDA)?.configuration ?: emptyMap() ) } - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType == ElementType.LAMBDA_EXPRESSION) { checkLambda(node, configuration) } @@ -48,7 +38,7 @@ class LambdaLengthRule(private val configRules: List) : Rule("lambd val isIt = copyNode.findAllNodesWithSpecificType(ElementType.REFERENCE_EXPRESSION).map { re -> re.text }.contains("it") val parameters = node.findChildByType(ElementType.FUNCTION_LITERAL)?.findChildByType(ElementType.VALUE_PARAMETER_LIST) if (parameters == null && isIt) { - Warnings.TOO_MANY_LINES_IN_LAMBDA.warn(configRules, emitWarn, isFixMode, + TOO_MANY_LINES_IN_LAMBDA.warn(configRules, emitWarn, isFixMode, "max length lambda without arguments is ${configuration.maxLambdaLength}, but you have $sizeLambda", node.startOffset, node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaParameterOrder.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaParameterOrder.kt index 486948f80a..28bf1a9082 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaParameterOrder.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/LambdaParameterOrder.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.LAMBDA_IS_NOT_LAST_PARAMETER +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_TYPE import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER @@ -16,16 +15,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty /** * Rule that checks if parameter with function type is the last in parameter list */ -class LambdaParameterOrder(private val configRules: List) : Rule("lambda-parameter-order") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class LambdaParameterOrder(configRules: List) : DiktatRule("lambda-parameter-order", configRules, listOf(LAMBDA_IS_NOT_LAST_PARAMETER)) { + override fun logic(node: ASTNode) { if (node.elementType == ElementType.FUN) { checkArguments(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/NestedFunctionBlock.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/NestedFunctionBlock.kt index 5fe828fb2a..dc537c668a 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/NestedFunctionBlock.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/NestedFunctionBlock.kt @@ -3,12 +3,11 @@ package org.cqfn.diktat.ruleset.rules.chapter5 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.NESTED_BLOCK +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.FUN import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_LITERAL @@ -21,19 +20,12 @@ import org.jetbrains.kotlin.psi.psiUtil.parents /** * Rule 5.1.2 Nested blokcs */ -class NestedFunctionBlock(private val configRules: List) : Rule("nested-block") { +class NestedFunctionBlock(configRules: List) : DiktatRule("nested-block", configRules, listOf(NESTED_BLOCK)) { private val configuration: NestedBlockConfiguration by lazy { NestedBlockConfiguration(configRules.getRuleConfig(NESTED_BLOCK)?.configuration ?: emptyMap()) } - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType in nullificationType) { countNestedBlocks(node, configuration.maxNestedBlockQuantity) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/OverloadingArgumentsFunction.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/OverloadingArgumentsFunction.kt index db03967186..632db0609e 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/OverloadingArgumentsFunction.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter5/OverloadingArgumentsFunction.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter5 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_OVERLOADING_FUNCTION_ARGUMENTS +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 -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.FUN import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER import com.pinterest.ktlint.core.ast.ElementType.TYPE_REFERENCE @@ -18,16 +17,9 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset /** * Rule that suggests to use functions with default parameters instead of multiple overloads */ -class OverloadingArgumentsFunction(private val configRules: List) : Rule("overloading-default-values") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - isFixMode = autoCorrect - emitWarn = emit - +class OverloadingArgumentsFunction(configRules: List) : DiktatRule("overloading-default-values", configRules, + listOf(WRONG_OVERLOADING_FUNCTION_ARGUMENTS)) { + override fun logic(node: ASTNode) { if (node.elementType == FUN) { checkFun(node.psi as KtFunction) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidEmptyPrimaryConstructor.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidEmptyPrimaryConstructor.kt index 7f26d48443..d90f3ae304 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidEmptyPrimaryConstructor.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/AvoidEmptyPrimaryConstructor.kt @@ -1,10 +1,9 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.EMPTY_PRIMARY_CONSTRUCTOR +import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.psi.KtClass @@ -12,16 +11,8 @@ import org.jetbrains.kotlin.psi.KtClass /** * This rule checks if a class has an empty primary constructor. */ -class AvoidEmptyPrimaryConstructor(private val configRules: List) : Rule("avoid-empty-primary-constructor") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class AvoidEmptyPrimaryConstructor(configRules: List) : DiktatRule("avoid-empty-primary-constructor", configRules, listOf(EMPTY_PRIMARY_CONSTRUCTOR)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS) { checkClass(node.psi as KtClass) } 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 c2898168bb..79635772ae 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 @@ -2,11 +2,10 @@ package org.cqfn.diktat.ruleset.rules.chapter6 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.AVOID_USING_UTILITY_CLASS +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 @@ -25,15 +24,8 @@ import org.jetbrains.kotlin.psi.psiUtil.children /** * Rule 6.4.1 checks that class/object, with a word "util" in its name, has only functions. */ -class AvoidUtilityClass(private val configRules: List) : Rule("avoid-utility-class") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect +class AvoidUtilityClass(configRules: List) : DiktatRule("avoid-utility-class", configRules, listOf(AVOID_USING_UTILITY_CLASS)) { + override fun logic(node: ASTNode) { val config by configRules.getCommonConfiguration() val filePath = node.getRootNode().getFilePath() if (!(node.hasTestAnnotation() || isLocatedInTest(filePath.splitPathToDirs(), config.testAnchors))) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/CustomGetterSetterRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/CustomGetterSetterRule.kt index a04266d072..9002f51737 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/CustomGetterSetterRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/CustomGetterSetterRule.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.CUSTOM_GETTERS_SETTERS +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.GET_KEYWORD import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST import com.pinterest.ktlint.core.ast.ElementType.PRIVATE_KEYWORD @@ -16,16 +15,8 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode /** * Inspection that checks that no custom getters and setters are used for properties. */ -class CustomGetterSetterRule(private val configRules: List) : Rule("custom-getter-setter") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class CustomGetterSetterRule(configRules: List) : DiktatRule("custom-getter-setter", configRules, listOf(CUSTOM_GETTERS_SETTERS)) { + override fun logic(node: ASTNode) { if (node.elementType == PROPERTY_ACCESSOR) { checkForCustomGetersSetters(node) } @@ -39,12 +30,12 @@ class CustomGetterSetterRule(private val configRules: List) : Rule( setter?.let { // only private custom setters are allowed if (!isPrivateSetter) { - Warnings.CUSTOM_GETTERS_SETTERS.warn(configRules, emitWarn, isFixMode, setter.text, setter.startOffset, node) + CUSTOM_GETTERS_SETTERS.warn(configRules, emitWarn, isFixMode, setter.text, setter.startOffset, node) } } getter?.let { - Warnings.CUSTOM_GETTERS_SETTERS.warn(configRules, emitWarn, isFixMode, getter.text, getter.startOffset, node) + CUSTOM_GETTERS_SETTERS.warn(configRules, emitWarn, isFixMode, getter.text, getter.startOffset, node) } } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsInFileRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsInFileRule.kt index e9a025ee13..e3a66b4389 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsInFileRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsInFileRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.EXTENSION_FUNCTION_WITH_CLASS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.FUN @@ -21,16 +20,9 @@ import org.jetbrains.kotlin.psi.KtFunction /** * This rule checks if there are any extension functions for the class in the same file, where it is defined */ -class ExtensionFunctionsInFileRule(private val configRules: List) : Rule("extension-functions-class-file") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ExtensionFunctionsInFileRule(configRules: List) : DiktatRule("extension-functions-class-file", configRules, + listOf(EXTENSION_FUNCTION_WITH_CLASS)) { + override fun logic(node: ASTNode) { if (node.elementType == ElementType.FILE) { val classNames = collectAllClassNames(node) @@ -48,7 +40,7 @@ class ExtensionFunctionsInFileRule(private val configRules: List) : } private fun fireWarning(node: ASTNode) { - Warnings.EXTENSION_FUNCTION_WITH_CLASS.warn(configRules, emitWarn, isFixMode, "fun ${(node.psi as KtFunction).name}", node.startOffset, node) + EXTENSION_FUNCTION_WITH_CLASS.warn(configRules, emitWarn, isFixMode, "fun ${(node.psi as KtFunction).name}", node.startOffset, node) } private fun collectAllExtensionFunctionsWithSameClassName(node: ASTNode, classNames: List): List = diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsSameNameRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsSameNameRule.kt index 59205894d0..58e4ea2f72 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsSameNameRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ExtensionFunctionsSameNameRule.kt @@ -1,8 +1,8 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.EXTENSION_FUNCTION_SAME_SIGNATURE +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.findChildAfter import org.cqfn.diktat.ruleset.utils.findChildBefore @@ -11,7 +11,6 @@ import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.COLON import com.pinterest.ktlint.core.ast.ElementType.DOT @@ -33,16 +32,9 @@ internal typealias SimilarSignatures = List) : Rule("extension-functions-same-name") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ExtensionFunctionsSameNameRule(configRules: List) : DiktatRule("extension-functions-same-name", configRules, + listOf(EXTENSION_FUNCTION_SAME_SIGNATURE)) { + override fun logic(node: ASTNode) { /** * 1) Collect all classes that extend other classes (collect related classes) * 2) Collect all extension functions with same signature diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ImplicitBackingPropertyRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ImplicitBackingPropertyRule.kt index 06ceee31fb..be46671279 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ImplicitBackingPropertyRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/ImplicitBackingPropertyRule.kt @@ -1,14 +1,13 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.NO_CORRESPONDING_PROPERTY +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasAnyChildOfTypes import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION @@ -25,16 +24,9 @@ import org.jetbrains.kotlin.psi.KtProperty /** * This rule checks if there is a backing property for field with property accessors, in case they don't use field keyword */ -class ImplicitBackingPropertyRule(private val configRules: List) : Rule("implicit-backing-property") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class ImplicitBackingPropertyRule(configRules: List) : DiktatRule("implicit-backing-property", configRules, + listOf(NO_CORRESPONDING_PROPERTY)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS_BODY) { findAllProperties(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/PropertyAccessorFields.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/PropertyAccessorFields.kt index 23ffd8fdd3..cdd75f4376 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/PropertyAccessorFields.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/PropertyAccessorFields.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.isGoingAfter -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER @@ -21,18 +20,8 @@ import org.jetbrains.kotlin.psi.KtProperty /** * Rule check that never use the name of a variable in the custom getter or setter */ -class PropertyAccessorFields(private val configRules: List) : Rule("getter-setter-fields") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - isFixMode = autoCorrect - emitWarn = emit - +class PropertyAccessorFields(configRules: List) : DiktatRule("getter-setter-fields", configRules, listOf(WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR)) { + override fun logic(node: ASTNode) { if (node.elementType == PROPERTY_ACCESSOR) { checkPropertyAccessor(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/TrivialPropertyAccessors.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/TrivialPropertyAccessors.kt index fec5142e9a..c2c821a9c1 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/TrivialPropertyAccessors.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/TrivialPropertyAccessors.kt @@ -1,14 +1,13 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.getIdentifierName import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT @@ -27,16 +26,9 @@ import org.jetbrains.kotlin.psi.KtPropertyAccessor /** * This rule checks if there are any trivial getters and setters and, if so, deletes them */ -class TrivialPropertyAccessors(private val configRules: List) : Rule("trivial-property-accessors") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class TrivialPropertyAccessors(configRules: List) : DiktatRule("trivial-property-accessors", configRules, + listOf(TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED)) { + override fun logic(node: ASTNode) { if (node.elementType == PROPERTY_ACCESSOR) { handlePropertyAccessors(node) } @@ -85,7 +77,7 @@ class TrivialPropertyAccessors(private val configRules: List) : Rul } private fun raiseWarning(node: ASTNode) { - Warnings.TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { + TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { val property = (node.psi as KtPropertyAccessor).property.node if (node.treePrev.isWhiteSpace()) { property.removeChild(node.treePrev) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/UselessSupertype.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/UselessSupertype.kt index 2e57fec2ca..c740b623aa 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/UselessSupertype.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/UselessSupertype.kt @@ -1,11 +1,10 @@ package org.cqfn.diktat.ruleset.rules.chapter6 import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.USELESS_SUPERTYPE +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.CALL_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY @@ -32,16 +31,8 @@ import java.util.HashMap * Explicit supertype qualification should not be used if there is not clash between called methods * fixme can't fix supertypes that are defined in other files. */ -class UselessSupertype(private val configRules: List) : Rule("useless-override") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class UselessSupertype(configRules: List) : DiktatRule("useless-override", configRules, listOf(USELESS_SUPERTYPE)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS) { checkClass(node) } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt index 927f4757d4..4755f42b55 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ABSTRACT_KEYWORD import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY @@ -20,16 +19,8 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode /** * Checks if abstract class has any abstract method. If not, warns that class should not be abstract */ -class AbstractClassesRule(private val configRule: List) : Rule("abstract-classes") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class AbstractClassesRule(configRules: List) : DiktatRule("abstract-classes", configRules, listOf(CLASS_SHOULD_NOT_BE_ABSTRACT)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS) { val classBody = node.getFirstChildWithType(CLASS_BODY) ?: return @@ -49,7 +40,7 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs val identifier = classNode.getFirstChildWithType(IDENTIFIER)!!.text if (functions.isNotEmpty() && functions.none { hasAbstractModifier(it) }) { - CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRule, emitWarn, isFixMode, identifier, node.startOffset, node) { + CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRules, emitWarn, isFixMode, identifier, node.startOffset, node) { val modList = classNode.getFirstChildWithType(MODIFIER_LIST)!! if (modList.getChildren(null).size > 1) { val abstractKeyword = modList.getFirstChildWithType(ABSTRACT_KEYWORD)!! diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt index 4c64fa4f95..807459f103 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.COMPACT_OBJECT_INITIALIZATION +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.getFunctionName import org.cqfn.diktat.ruleset.utils.log -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.LBRACE import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import com.pinterest.ktlint.core.ast.isPartOfComment @@ -28,19 +27,10 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset * FixMe: When assigned variable's name is also a `this@apply`'s property, it should be changed to qualified name, * e.g `this@Foo`. But for this we need a mechanism to determine declaration scope and it's label. */ -class CompactInitialization(private val configRules: List) : Rule("class-compact-initialization") { - private var isFixMode: Boolean = false +class CompactInitialization(configRules: List) : DiktatRule("class-compact-initialization", configRules, listOf(COMPACT_OBJECT_INITIALIZATION)) { private val kotlinParser by lazy { KotlinParser() } - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { node .psi .let { it as? KtProperty } @@ -72,7 +62,7 @@ class CompactInitialization(private val configRules: List) : Rule(" } .toList() .forEach { (assignment, field) -> - Warnings.COMPACT_OBJECT_INITIALIZATION.warnAndFix( + COMPACT_OBJECT_INITIALIZATION.warnAndFix( configRules, emitWarn, isFixMode, field.text, assignment.startOffset, assignment.node ) { diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/DataClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/DataClassesRule.kt index 884a85a02a..f89eb1239b 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/DataClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/DataClassesRule.kt @@ -1,13 +1,12 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.USE_DATA_CLASS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.ABSTRACT_KEYWORD import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.CLASS @@ -32,16 +31,8 @@ import org.jetbrains.kotlin.psi.KtPrimaryConstructor /** * This rule checks if class can be made as data class */ -class DataClassesRule(private val configRule: List) : Rule("data-classes") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class DataClassesRule(configRules: List) : DiktatRule("data-classes", configRules, listOf(USE_DATA_CLASS)) { + override fun logic(node: ASTNode) { if (node.elementType == CLASS) { handleClass(node) } @@ -59,7 +50,7 @@ class DataClassesRule(private val configRule: List) : Rule("data-cl // fixme: Need to know types of vars and props to create data class private fun raiseWarn(node: ASTNode) { - USE_DATA_CLASS.warn(configRule, emitWarn, isFixMode, "${(node.psi as KtClass).name}", node.startOffset, node) + USE_DATA_CLASS.warn(configRules, emitWarn, isFixMode, "${(node.psi as KtClass).name}", node.startOffset, node) } @Suppress("UnsafeCallOnNullableType", "FUNCTION_BOOLEAN_PREFIX", "ComplexMethod") diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/InlineClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/InlineClassesRule.kt index dd254abdb1..1665c8481e 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/InlineClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/InlineClassesRule.kt @@ -2,12 +2,11 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes 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.INLINE_CLASS_CAN_BE_USED +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CONSTRUCTOR_CALLEE import com.pinterest.ktlint.core.ast.ElementType.FINAL_KEYWORD @@ -26,19 +25,9 @@ import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType /** * This rule checks if inline class can be used. */ -class InlineClassesRule(private val configRule: List) : Rule("inline-classes") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect - - val configuration by configRule.getCommonConfiguration() +class InlineClassesRule(configRules: List) : DiktatRule("inline-classes", configRules, listOf(INLINE_CLASS_CAN_BE_USED)) { + override fun logic(node: ASTNode) { + val configuration by configRules.getCommonConfiguration() if (node.elementType == CLASS && configuration.kotlinVersion >= ktVersion) { handleClasses(node.psi as KtClass) } @@ -50,7 +39,7 @@ class InlineClassesRule(private val configRule: List) : Rule("inlin !isExtendingClass(classPsi.node) && classPsi.node.getFirstChildWithType(MODIFIER_LIST)?.getChildren(null)?.all { it.elementType in goodModifiers } != false) { // Fixme: since it's an experimental feature we shouldn't do fixer - INLINE_CLASS_CAN_BE_USED.warn(configRule, emitWarn, isFixMode, "class ${classPsi.name}", classPsi.node.startOffset, classPsi.node) + INLINE_CLASS_CAN_BE_USED.warn(configRules, emitWarn, isFixMode, "class ${classPsi.name}", classPsi.node.startOffset, classPsi.node) } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleConstructorRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleConstructorRule.kt index 37713e15f4..802c2fde9c 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleConstructorRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleConstructorRule.kt @@ -1,15 +1,14 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType import org.cqfn.diktat.ruleset.constants.Warnings.SINGLE_CONSTRUCTOR_SHOULD_BE_PRIMARY +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.KotlinParser import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getIdentifierName import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.isGoingAfter -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST @@ -34,19 +33,10 @@ import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType * This rule ensures that if a class has a single constructor, this constructor is primary. * Secondary constructor is converted into primary, statements that are not assignments are moved into an `init` block. */ -class SingleConstructorRule(private val config: List) : Rule("single-constructor") { - private var isFixMode: Boolean = false +class SingleConstructorRule(configRules: List) : DiktatRule("single-constructor", configRules, listOf(SINGLE_CONSTRUCTOR_SHOULD_BE_PRIMARY)) { private val kotlinParser by lazy { KotlinParser() } - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect + override fun logic(node: ASTNode) { if (node.elementType == CLASS) { handleClassConstructors(node) } @@ -61,7 +51,7 @@ class SingleConstructorRule(private val config: List) : Rule("singl ?.singleOrNull() ?.let { secondaryCtor -> SINGLE_CONSTRUCTOR_SHOULD_BE_PRIMARY.warnAndFix( - config, emitWarn, isFixMode, "in class <${node.getIdentifierName()?.text}>", + configRules, emitWarn, isFixMode, "in class <${node.getIdentifierName()?.text}>", node.startOffset, node ) { convertConstructorToPrimary(node, secondaryCtor) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleInitRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleInitRule.kt index 0bb834b155..eaa56a3620 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleInitRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/SingleInitRule.kt @@ -1,12 +1,11 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.MULTIPLE_INIT_BLOCKS +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getIdentifierName -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.BLOCK import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.CLASS_INITIALIZER @@ -26,18 +25,8 @@ import org.jetbrains.kotlin.psi.psiUtil.children /** * The rule that checks whether a class has a single `init` block or multiple. Having multiple `init` blocks is a bad practice. */ -class SingleInitRule(private val configRule: List) : Rule("multiple-init-block") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit( - node: ASTNode, - autoCorrect: Boolean, - emit: EmitType - ) { - emitWarn = emit - isFixMode = autoCorrect - +class SingleInitRule(configRules: List) : DiktatRule("multiple-init-block", configRules, listOf(MULTIPLE_INIT_BLOCKS)) { + override fun logic(node: ASTNode) { when (node.elementType) { CLASS_BODY -> handleInitBlocks(node) else -> return @@ -53,7 +42,7 @@ class SingleInitRule(private val configRule: List) : Rule("multiple .takeIf { it.size > 1 } ?.let { initBlocks -> val className = node.treeParent.getIdentifierName()?.text - Warnings.MULTIPLE_INIT_BLOCKS.warnAndFix(configRule, emitWarn, isFixMode, + MULTIPLE_INIT_BLOCKS.warnAndFix(configRules, emitWarn, isFixMode, "in class <$className> found ${initBlocks.size} `init` blocks", node.startOffset, node) { mergeInitBlocks(initBlocks) } @@ -107,7 +96,7 @@ class SingleInitRule(private val configRule: List) : Rule("multiple } .takeIf { it.isNotEmpty() } ?.let { map -> - Warnings.MULTIPLE_INIT_BLOCKS.warnAndFix(configRule, emitWarn, isFixMode, + MULTIPLE_INIT_BLOCKS.warnAndFix(configRules, emitWarn, isFixMode, "`init` block has assignments that can be moved to declarations", initBlock.startOffset, initBlock ) { map.forEach { (property, assignments) -> diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/StatelessClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/StatelessClassesRule.kt index 358fa4c337..7ed2903736 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/StatelessClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/StatelessClassesRule.kt @@ -1,14 +1,13 @@ package org.cqfn.diktat.ruleset.rules.chapter6.classes import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ruleset.constants.EmitType -import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.constants.Warnings.OBJECT_IS_PREFERRED +import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType import org.cqfn.diktat.ruleset.utils.getFirstChildWithType import org.cqfn.diktat.ruleset.utils.hasChildOfType -import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.CLASS import com.pinterest.ktlint.core.ast.ElementType.CLASS_KEYWORD import com.pinterest.ktlint.core.ast.ElementType.FILE @@ -28,16 +27,8 @@ import org.jetbrains.kotlin.psi.KtClass /** * This rule checks if class is stateless and if so changes it to object. */ -class StatelessClassesRule(private val configRule: List) : Rule("stateless-class") { - private var isFixMode: Boolean = false - private lateinit var emitWarn: EmitType - - override fun visit(node: ASTNode, - autoCorrect: Boolean, - emit: EmitType) { - emitWarn = emit - isFixMode = autoCorrect - +class StatelessClassesRule(configRules: List) : DiktatRule("stateless-class", configRules, listOf(OBJECT_IS_PREFERRED)) { + override fun logic(node: ASTNode) { // Fixme: We should find interfaces in all project and then check them if (node.elementType == FILE) { val interfacesNodes = node @@ -53,7 +44,7 @@ class StatelessClassesRule(private val configRule: List) : Rule("st @Suppress("UnsafeCallOnNullableType") private fun handleClass(node: ASTNode, interfaces: List) { if (isClassExtendsValidInterface(node, interfaces) && isStatelessClass(node)) { - Warnings.OBJECT_IS_PREFERRED.warnAndFix(configRule, emitWarn, isFixMode, + OBJECT_IS_PREFERRED.warnAndFix(configRules, emitWarn, isFixMode, "class ${(node.psi as KtClass).name!!}", node.startOffset, node) { val newObjectNode = CompositeElement(OBJECT_DECLARATION) node.treeParent.addChild(newObjectNode, node) diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt index d6d58f0ebf..58ef54f4ee 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt @@ -45,6 +45,6 @@ class DiktatRuleSetProviderTest { } companion object { - private val ignoreFile = listOf("DiktatRuleSetProvider") + private val ignoreFile = listOf("DiktatRuleSetProvider", "DiktatRule") } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleTest.kt new file mode 100644 index 0000000000..4fd87c9d8f --- /dev/null +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleTest.kt @@ -0,0 +1,43 @@ +package org.cqfn.diktat.util + +import org.cqfn.diktat.common.config.rules.RulesConfig +import org.cqfn.diktat.ruleset.constants.Warnings.BLANK_LINE_BETWEEN_PROPERTIES +import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES +import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID +import org.cqfn.diktat.ruleset.rules.chapter3.ClassLikeStructuresOrderRule + +import com.pinterest.ktlint.core.LintError +import org.junit.jupiter.api.Test + +class DiktatRuleTest : LintTestBase(::ClassLikeStructuresOrderRule) { + private val ruleId = "$DIKTAT_RULE_SET_ID:class-like-structures" + private val codeTemplate = """ + |class Example { + | private val FOO = 42 + | private val log = LoggerFactory.getLogger(Example.javaClass) + | // blank line between property + | private val some = 2 + |} + """.trimMargin() + private val rulesConfigAllDisabled = listOf( + RulesConfig(BLANK_LINE_BETWEEN_PROPERTIES.name, enabled = false), + RulesConfig(WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES.name, enabled = false) + ) + private val rulesConfigOneRuleIsEnabled = listOf( + RulesConfig(BLANK_LINE_BETWEEN_PROPERTIES.name, enabled = true), + RulesConfig(WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES.name, enabled = false) + ) + + @Test + fun `check that if all inspections are disabled then rule won't run`() { + lintMethod(codeTemplate, rulesConfigList = rulesConfigAllDisabled) + } + + @Test + fun `check that if one inspection is enabled then rule will run`() { + lintMethod(codeTemplate, + LintError(4, 4, ruleId, "${BLANK_LINE_BETWEEN_PROPERTIES.warnText()} some", true), + rulesConfigList = rulesConfigOneRuleIsEnabled + ) + } +}