All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cqfn.diktat.ruleset.rules.chapter3.AnnotationNewLineRule.kt Maven / Gradle / Ivy

There is a newer version: 1.2.5
Show newest version
package org.cqfn.diktat.ruleset.rules.chapter3

import org.cqfn.diktat.common.config.rules.RulesConfig
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.ast.ElementType.ANNOTATION_ENTRY
import com.pinterest.ktlint.core.ast.ElementType.CLASS
import com.pinterest.ktlint.core.ast.ElementType.FUN
import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST
import com.pinterest.ktlint.core.ast.ElementType.PRIMARY_CONSTRUCTOR
import com.pinterest.ktlint.core.ast.ElementType.SECONDARY_CONSTRUCTOR
import com.pinterest.ktlint.core.ast.isWhiteSpace
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
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(configRules: List) : DiktatRule(
    NAME_ID,
    configRules,
    listOf(ANNOTATION_NEW_LINE)
) {
    override fun logic(node: ASTNode) {
        when (node.elementType) {
            CLASS, FUN, PRIMARY_CONSTRUCTOR, SECONDARY_CONSTRUCTOR -> checkAnnotation(node)
            else -> return
        }
    }

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

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

        node.getAllChildrenWithType(ANNOTATION_ENTRY).forEach {
            if (!it.isFollowedByNewlineWithComment() || !it.isBeginNewLineWithComment()) {
                deleteSpaces(it, !it.isFollowedByNewlineWithComment())
            }
        }
    }

    private fun deleteSpaces(node: ASTNode,
                             rightSide: Boolean) {
        ANNOTATION_NEW_LINE.warnAndFix(configRules, emitWarn, isFixMode, "${node.text} not on a single line",
            node.startOffset, node) {
            if (rightSide) {
                if (node.treeNext?.isWhiteSpace() == true) {
                    node.removeChild(node.treeNext)
                }
                node.treeParent.addChild(PsiWhiteSpaceImpl("\n"), node.treeNext)
            }

            if (node == node.treeParent.getFirstChildWithType(node.elementType)) {
                // Current node is ANNOTATION_ENTRY. treeParent(ModifierList) -> treeParent(PRIMARY_CONSTRUCTOR)
                // Checks if there is a white space before grandparent node
                val hasSpaceBeforeGrandparent = node
                    .treeParent
                    .treeParent
                    .treePrev
                    .isWhiteSpace()
                if (hasSpaceBeforeGrandparent) {
                    (node.treeParent.treeParent.treePrev as LeafPsiElement).rawReplaceWithText("\n")
                }
            }
        }
    }

    companion object {
        const val NAME_ID = "abo-annotation-new-line"
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy