Repository: analysis-dev/diktat (kotlin)

Issue:
FP EMPTY_BLOCK_STRUCTURE_ERROR on SAM overrides
We allow empty blocks for overriden functions, but when anonimous SAM class implementation is used:
```kotlin
val project = KotlinCoreEnvironment.createForProduction(
            Disposable {},
            compilerConfiguration,
            EnvironmentConfigFiles.JVM_CONFIG_FILES
        ).project
```
we complain on `Disposable {}`:
`[EMPTY_BLOCK_STRUCTURE_ERROR] incorrect format of empty block: empty blocks are forbidden unless it is function with override keyword`

diktat: 0.1.5

Pull request:
### What's done:
  * Fixed the bug

## Which rule and warnings did you add?

This pull request closes #587

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/EmptyBlock.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/EmptyBlock.kt
index f60e14df43..ae92bb5a6c 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/EmptyBlock.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/EmptyBlock.kt
@@ -6,10 +6,17 @@ 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.utils.findLBrace
+import org.cqfn.diktat.ruleset.utils.findLeafWithSpecificType
+import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType
+import org.cqfn.diktat.ruleset.utils.hasParent
 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
 import com.pinterest.ktlint.core.ast.ElementType.RBRACE
 import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
 import org.jetbrains.kotlin.com.intellij.lang.ASTNode
@@ -42,7 +49,7 @@ class EmptyBlock(private val configRules: List<RulesConfig>) : Rule("empty-block
 
     @Suppress("UnsafeCallOnNullableType")
     private fun checkEmptyBlock(node: ASTNode, configuration: EmptyBlockStyleConfiguration) {
-        if (node.treeParent.isOverridden()) {
+        if (node.treeParent.isOverridden() || isAnonymousSamClass(node)) {
             return
         }
         if (node.isBlockEmpty()) {
@@ -70,6 +77,18 @@ class EmptyBlock(private val configRules: List<RulesConfig>) : Rule("empty-block
         }
     }
 
+    @Suppress("UnsafeCallOnNullableType", "WRONG_WHITESPACE")
+    private fun isAnonymousSamClass(node: ASTNode) : Boolean =
+            if (node.elementType == FUNCTION_LITERAL && node.hasParent(CALL_EXPRESSION)) {
+                // We are checking identifier because it is not class in AST
+                // , SAM conversions are indistinguishable from lambdas.
+                // So we just verify that identifier is in PascalCase
+                val valueArgument = node.findParentNodeWithSpecificType(CALL_EXPRESSION)!!
+                valueArgument.findLeafWithSpecificType(IDENTIFIER)?.text?.isPascalCase() ?: false
+            } else {
+                false
+            }
+
     /**
      * [RuleConfiguration] for empty blocks formatting
      */
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KotlinParser.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KotlinParser.kt
index 38aff0df5e..8243f21656 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KotlinParser.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/utils/KotlinParser.kt
@@ -29,7 +29,6 @@ import sun.reflect.ReflectionFactory
  * A class that wraps kotlin compiler's code parser and converts source code into AST
  */
 class KotlinParser {
-    @Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
     private val project: Project by lazy {
         val compilerConfiguration = CompilerConfiguration()
         compilerConfiguration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)  // mute the output logging to process it themselves


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/EmptyBlockWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/EmptyBlockWarnTest.kt
index f800de9853..283dcf0f9a 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/EmptyBlockWarnTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/EmptyBlockWarnTest.kt
@@ -133,15 +133,61 @@ class EmptyBlockWarnTest : LintTestBase(::EmptyBlock) {
     }
 
     @Test
+    @Tag(WarningNames.EMPTY_BLOCK_STRUCTURE_ERROR)
     fun `check empty lambda with config`() {
         lintMethod(
             """
-                    |fun foo() {
-                    |   val y = listOf<Int>().map {} 
-                    |}
-                """.trimMargin(),
+                |fun foo() {
+                |   val y = listOf<Int>().map {} 
+                |}
+            """.trimMargin(),
             LintError(2, 30, ruleId, "${EMPTY_BLOCK_STRUCTURE_ERROR.warnText()} different style for empty block", true),
             rulesConfigList = rulesConfigListEmptyBlockExist
         )
     }
+
+    @Test
+    fun `should not trigger on anonymous SAM classes #1`() {
+        lintMethod(
+            """
+                |fun foo() {
+                |   val proj = some.create(
+                |       Disposable {},
+                |       config
+                |   ).project
+                |}
+            """.trimMargin(),
+            rulesConfigList = rulesConfigListEmptyBlockExist
+        )
+    }
+
+    @Test
+    fun `should not trigger on anonymous SAM classes #2`() {
+        lintMethod(
+            """
+                |fun foo() {
+                |   val some = Disposable {}
+                |   val proj = some.create(
+                |       some,
+                |       config
+                |   ).project
+                |}
+            """.trimMargin(),
+            rulesConfigList = rulesConfigListEmptyBlockExist
+        )
+    }
+
+    @Test
+    @Tag(WarningNames.EMPTY_BLOCK_STRUCTURE_ERROR)
+    fun `should trigger on implementing anonymous SAM classes`() {
+        lintMethod(
+            """
+                |interface A
+                |
+                |val some = object : A{}
+            """.trimMargin(),
+            LintError(3, 22, ruleId, "${EMPTY_BLOCK_STRUCTURE_ERROR.warnText()} different style for empty block", true),
+            rulesConfigList = rulesConfigListEmptyBlockExist
+        )
+    }
 }