Repository: analysis-dev/diktat (kotlin)

Issue:
False positives in UNUSED_IMPORT
## Describe the bug
Unused imports rule should not check `get` and `set` methods that can use brackets notation:
```kotlin
import com.example.get

val a = list[1]  // equivalent to list.get(1) using com.example.get
```

## Environment information
* diktat version: 0.4.0

Pull request description:
### What's done:
  * Fixed bug


This pull request closes #742

Patch:
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 76ec154d8f..6adda7c8ea 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
@@ -73,6 +73,7 @@ class FileStructureRule(configRules: List<RulesConfig>) : DiktatRule("file-struc
         }
     private val refSet: MutableSet<String> = mutableSetOf()
     private var packageName = ""
+    private val ignoreImports = setOf("invoke", "get", "set")
 
     override fun logic(node: ASTNode) {
         if (node.elementType == FILE) {
@@ -222,7 +223,7 @@ class FileStructureRule(configRules: List<RulesConfig>) : DiktatRule("file-struc
                 ) {
                     // this branch corresponds to imports from the same package
                     deleteImport(importPath, node, ktImportDirective)
-                } else if (importName != null && !refSet.contains(
+                } else if (importName != null && !ignoreImports.contains(importName) && !refSet.contains(
                     importName
                 )
                 ) {
@@ -245,14 +246,21 @@ class FileStructureRule(configRules: List<RulesConfig>) : DiktatRule("file-struc
     }
 
     private fun findAllReferences(node: ASTNode) {
-        node.findAllNodesWithSpecificType(OPERATION_REFERENCE)?.forEach { ref ->
+        node.findAllNodesWithSpecificType(OPERATION_REFERENCE).forEach { ref ->
             if (!ref.isPartOf(IMPORT_DIRECTIVE)) {
-                operatorMap.filterValues { it == ref.text }.keys.forEach { key -> refSet.add(key) }
+                val references = operatorMap.filterValues { it == ref.text }
+                if (references.isNotEmpty()) {
+                    references.keys.forEach { key -> refSet.add(key) }
+                } else {
+                    // this is needed to check infix functions that relate to operation reference
+                    refSet.add(ref.text)
+                }
             }
         }
-        node.findAllNodesWithSpecificType(REFERENCE_EXPRESSION)?.forEach {
+        node.findAllNodesWithSpecificType(REFERENCE_EXPRESSION).forEach {
             if (!it.isPartOf(IMPORT_DIRECTIVE)) {
-                refSet.add(it.text)
+                // the importedName method removes the quotes, but the node.text method does not
+                refSet.add(it.text.replace("`", ""))
             }
         }
     }


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt
index 4d9a90d103..9ac9122706 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt
@@ -327,4 +327,71 @@ class FileStructureRuleTest : LintTestBase(::FileStructureRule) {
             """.trimMargin(),
         )
     }
+
+    @Test
+    @Tag(WarningNames.UNUSED_IMPORT)
+    fun `Should correctly check infix functions`() {
+        lintMethod(
+            """
+                |package org.cqfn.diktat.example
+                |
+                |import org.cqfn.diktat.utils.logAndExit
+                |
+                |fun main() {
+                |"Type is not supported yet" logAndExit 1
+                |}
+            """.trimMargin(),
+        )
+    }
+
+    @Test
+    @Tag(WarningNames.UNUSED_IMPORT)
+    fun `unused import to infix functions`() {
+        lintMethod(
+            """
+                |package org.cqfn.diktat.example
+                |
+                |import org.cqfn.diktat.utils.logAndExit
+                |
+                |fun main() {
+                |println("Type is not supported yet")
+                |}
+            """.trimMargin(),
+            LintError(1, 1, ruleId, "${Warnings.UNUSED_IMPORT.warnText()} org.cqfn.diktat.utils.logAndExit - unused import", true)
+        )
+    }
+
+    @Test
+    @Tag(WarningNames.UNUSED_IMPORT)
+    fun `Acute`() {
+        lintMethod(
+            """
+                |package org.cqfn.diktat.example
+                |
+                |import js.externals.jquery.`${'$'}`
+                |
+                |fun main() {
+                |   `${'$'}`("document").ready {}
+                |}
+            """.trimMargin(),
+        )
+    }
+
+    @Test
+    @Tag(WarningNames.UNUSED_IMPORT)
+    fun `Ignore Imports`() {
+        lintMethod(
+            """
+                |package org.cqfn.diktat.example
+                |
+                |import com.example.get
+                |import com.example.invoke
+                |import com.example.set
+                |
+                |fun main() {
+                |   val a = list[1]
+                |}
+            """.trimMargin(),
+        )
+    }
 }