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

org.cqfn.diktat.ruleset.rules.chapter6.RunInScript.kt Maven / Gradle / Ivy

package org.cqfn.diktat.ruleset.rules.chapter6

import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.common.config.rules.qualifiedWithRuleSetId
import org.cqfn.diktat.ruleset.constants.EmitType
import org.cqfn.diktat.ruleset.constants.Warnings.RUN_IN_SCRIPT
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.DOT_QUALIFIED_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_ARGUMENT
import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.PARENTHESIZED
import com.pinterest.ktlint.core.ast.ElementType.SCRIPT_INITIALIZER
import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT
import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT_LIST
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement

/**
 * Rule that checks if kts script contains other functions except run code
 * In .kts files allow use only property declaration, function, classes, and code inside `run` block
 * In gradle.kts files allow to call binary expression with EQ, expression and dot qualified expression in addition to everything used in .kts files
 */
class RunInScript(private val configRules: List) : Rule(NAME_ID.qualifiedWithRuleSetId()) {
    private var isFixMode: Boolean = false
    private lateinit var emitWarn: EmitType

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

        if (node.elementType == SCRIPT_INITIALIZER && node.getFilePath().isKotlinScript()) {
            if (node.getFilePath().isGradleScript()) {
                checkGradleNode(node)
            } else {
                checkScript(node)
            }
        }
    }

    private fun checkGradleNode(node: ASTNode) {
        val astNode = if (node.hasEqBinaryExpression()) {
            return
        } else {
            when (node.firstChildNode.elementType) {
                PARENTHESIZED -> node.firstChildNode
                else -> node
            }
        }
        if (!astNode.hasChildOfType(CALL_EXPRESSION) && !astNode.hasChildOfType(DOT_QUALIFIED_EXPRESSION)) {
            warnRunInScript(astNode)
        }
    }

    private fun checkScript(node: ASTNode) {
        val isLambdaArgument = node.firstChildNode.hasChildOfType(LAMBDA_ARGUMENT)
        val isLambdaInsideValueArgument = node.firstChildNode
            .findChildByType(VALUE_ARGUMENT_LIST)
            ?.findChildByType(VALUE_ARGUMENT)
            ?.findChildByType(LAMBDA_EXPRESSION) != null
        if (!isLambdaArgument && !isLambdaInsideValueArgument) {
            warnRunInScript(node)
        }
    }

    private fun warnRunInScript(node: ASTNode) {
        RUN_IN_SCRIPT.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) {
            if (node.firstChildNode.elementType != DOT_QUALIFIED_EXPRESSION) {
                val parent = node.treeParent
                val newNode = KotlinParser().createNode("run {\n ${node.text}\n} \n")
                val newScript = CompositeElement(SCRIPT_INITIALIZER)
                parent.addChild(newScript, node)
                newScript.addChild(newNode)
                parent.removeChild(node)
            }
        }
    }

    companion object {
        const val NAME_ID = "run-script"
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy