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 c04234ed56..d29451c8d7 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 @@ -10,15 +10,14 @@ 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.chapter1.PackageNaming.Companion.PACKAGE_SEPARATOR import org.cqfn.diktat.ruleset.utils.StandardPlatforms import org.cqfn.diktat.ruleset.utils.copyrightWords -import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.handleIncorrectOrder import org.cqfn.diktat.ruleset.utils.moveChildBefore -import org.cqfn.diktat.ruleset.rules.chapter1.PackageNaming.Companion.PACKAGE_SEPARATOR 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.EOL_COMMENT import com.pinterest.ktlint.core.ast.ElementType.FILE_ANNOTATION_LIST @@ -39,7 +38,6 @@ import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtPackageDirective import org.jetbrains.kotlin.psi.psiUtil.siblings /** @@ -66,14 +64,6 @@ class FileStructureRule(private val configRules: List) : Rule("file .mapValues { (_, value) -> value.map { it.split(PACKAGE_SEPARATOR).map(Name::identifier) } } - private val refSet: MutableSet = mutableSetOf() - private var packageName = "" - private val operatorMap = mapOf( - "unaryPlus" to "+", "unaryMinus" to "-", "not" to "!", - "plus" to "+", "minus" to "-", "times" to "*", "div" to "/", "rem" to "%", "mod" to "%", "rangeTo" to "..", - "inc" to "++", "dec" to "--", "contains" to "in", - "plusAssign" to "+=", "minusAssign" to "-=", "timesAssign" to "*=", "divAssign" to "/=", "modAssign" to "%=" - ) private lateinit var emitWarn: EmitType override fun visit(node: ASTNode, @@ -82,17 +72,13 @@ class FileStructureRule(private val configRules: List) : Rule("file isFixMode = autoCorrect emitWarn = emit - if (node.elementType == FILE) { + if (node.elementType == ElementType.FILE) { val wildcardImportsConfig = WildCardImportsConfig( this.configRules.getRuleConfig(FILE_WILDCARD_IMPORTS)?.configuration ?: emptyMap() ) val importsGroupingConfig = ImportsGroupingConfig( this.configRules.getRuleConfig(FILE_UNORDERED_IMPORTS)?.configuration ?: emptyMap() ) - val unusedImportConfig = UnusedImportConfig( - this.configRules.getRuleConfig(UNUSED_IMPORT)?.configuration ?: emptyMap() - ) - checkUnusedImport(node, unusedImportConfig) node.findChildByType(IMPORT_LIST) ?.let { checkImportsOrder(it, wildcardImportsConfig, importsGroupingConfig) } if (checkFileHasCode(node)) { @@ -193,6 +179,7 @@ class FileStructureRule(private val configRules: List) : Rule("file importsGroupingConfig: ImportsGroupingConfig ) { val imports = node.getChildren(TokenSet.create(IMPORT_DIRECTIVE)).toList() + // importPath can be null if import name cannot be parsed, which should be a very rare case, therefore !! should be safe here imports .filter { @@ -201,6 +188,7 @@ class FileStructureRule(private val configRules: List) : Rule("file } } .forEach { FILE_WILDCARD_IMPORTS.warn(configRules, emitWarn, isFixMode, it.text, it.startOffset, it) } + val sortedImportsGroups = if (importsGroupingConfig.useRecommendedImportsOrder) { regroupImports(imports.map { it.psi as KtImportDirective }) .map { group -> group.map { it.node } } @@ -208,6 +196,7 @@ class FileStructureRule(private val configRules: List) : Rule("file listOf(imports) } .map { group -> group.sortedBy { it.text } } + if (sortedImportsGroups.flatten() != imports) { FILE_UNORDERED_IMPORTS.warnAndFix(configRules, emitWarn, isFixMode, "${sortedImportsGroups.flatten().first().text}...", node.startOffset, node) { rearrangeImports(node, imports, sortedImportsGroups) @@ -215,76 +204,6 @@ class FileStructureRule(private val configRules: List) : Rule("file } } - @Suppress("UnsafeCallOnNullableType") - private fun checkUnusedImport( - node: ASTNode, - unusedImportConfig: UnusedImportConfig - ) { - findAllReferences(node) - packageName = (node.findChildByType(PACKAGE_DIRECTIVE)?.psi as KtPackageDirective).qualifiedName - node.findChildByType(IMPORT_LIST)?.getChildren(TokenSet.create(IMPORT_DIRECTIVE))?.toList() - ?.forEach { import -> - val ktImportDirective = import.psi as KtImportDirective - val importName = ktImportDirective.importPath?.importedName?.asString() - val importPath = ktImportDirective.importPath?.pathStr!! // importPath - ifNOtParsed & Nullable - if (ktImportDirective.aliasName == null && - packageName.isNotEmpty() && importPath.startsWith("$packageName.") && - importPath.substring(packageName.length + 1).indexOf('.') == -1 - ) { - if (unusedImportConfig.deleteUnusedImport) { - Warnings.UNUSED_IMPORT.warnAndFix( - configRules, emitWarn, isFixMode, - "$importPath - unused import", - node.startOffset, node - ) { ktImportDirective.delete() } - } - } else if (importName != null && !refSet.contains(importName)) { - if (unusedImportConfig.deleteUnusedImport) { - Warnings.UNUSED_IMPORT.warnAndFix( - configRules, emitWarn, isFixMode, - "$importPath - unused import", - node.startOffset, node - ) { ktImportDirective.delete() } - } - } - } - // this branch corresponds to imports from the same package - deleteImport(importPath, node, ktImportDirective) - } else if (importName != null && !refSet.contains(operatorMap.getOrDefault(importName, null)) && !refSet.contains( - importName - ) - ) { - // this import is not used anywhere - deleteImport(importPath, node, ktImportDirective) - } - } - } - - private fun deleteImport( - importPath: String, - node: ASTNode, - ktImportDirective: KtImportDirective - ) { - UNUSED_IMPORT.warnAndFix( - configRules, emitWarn, isFixMode, - "$importPath - unused import", - node.startOffset, node - ) { ktImportDirective.delete() } - } - - private fun findAllReferences(node: ASTNode) { - node.findAllNodesWithSpecificType(REFERENCE_EXPRESSION)?.forEach { - if (!it.isPartOf(IMPORT_DIRECTIVE)) { - refSet.add(it.text) - } - } - node.findAllNodesWithSpecificType(OPERATION_REFERENCE)?.forEach { - if (!it.isPartOf(IMPORT_DIRECTIVE)) { - refSet.add(it.text) - } - } - } - private fun rearrangeImports( node: ASTNode, imports: List,