Repository: analysis-dev/diktat (kotlin)

Issue:
Newline at the beginning of code block is not removed if there are more than one
## Describe the bug
1. ```kotlin
    fun foo() {


      println()
      println()
    }
    ```
removes only one blank line, though we have a rule that removes a single blank line. These changes should be run all at once.

2. ```kotlin
    list.map {
        
        bar()
    }
    ```
the blank line in the beginning of code block is not removed.

## Environment information
* diktat version: 0.1.3

Pull request description:
### What's done:
  * Fixed bugs

This pull request closes #519

Patch:
diff --git a/diktat-rules/src/main/kotlin/generated/WarningNames.kt b/diktat-rules/src/main/kotlin/generated/WarningNames.kt
index c101070ae1..4cce40c1bb 100644
--- a/diktat-rules/src/main/kotlin/generated/WarningNames.kt
+++ b/diktat-rules/src/main/kotlin/generated/WarningNames.kt
@@ -35,14 +35,14 @@ public object WarningNames {
 
     public const val GENERIC_NAME: String = "GENERIC_NAME"
 
+    public const val BACKTICKS_PROHIBITED: String = "BACKTICKS_PROHIBITED"
+
     public const val FUNCTION_NAME_INCORRECT_CASE: String = "FUNCTION_NAME_INCORRECT_CASE"
 
     public const val FUNCTION_BOOLEAN_PREFIX: String = "FUNCTION_BOOLEAN_PREFIX"
 
     public const val FILE_NAME_INCORRECT: String = "FILE_NAME_INCORRECT"
 
-    public const val FILE_NAME_MATCH_CLASS: String = "FILE_NAME_MATCH_CLASS"
-
     public const val EXCEPTION_SUFFIX: String = "EXCEPTION_SUFFIX"
 
     public const val CONFUSING_IDENTIFIER_NAMING: String = "CONFUSING_IDENTIFIER_NAMING"
@@ -137,8 +137,6 @@ public object WarningNames {
 
     public const val LONG_LINE: String = "LONG_LINE"
 
-    public const val BACKTICKS_PROHIBITED: String = "BACKTICKS_PROHIBITED"
-
     public const val REDUNDANT_SEMICOLON: String = "REDUNDANT_SEMICOLON"
 
     public const val WRONG_NEWLINES: String = "WRONG_NEWLINES"
@@ -165,6 +163,12 @@ public object WarningNames {
 
     public const val LOCAL_VARIABLE_EARLY_DECLARATION: String = "LOCAL_VARIABLE_EARLY_DECLARATION"
 
+    public const val STRING_TEMPLATE_CURLY_BRACES: String = "STRING_TEMPLATE_CURLY_BRACES"
+
+    public const val STRING_TEMPLATE_QUOTES: String = "STRING_TEMPLATE_QUOTES"
+
+    public const val FILE_NAME_MATCH_CLASS: String = "FILE_NAME_MATCH_CLASS"
+
     public const val NULLABLE_PROPERTY_TYPE: String = "NULLABLE_PROPERTY_TYPE"
 
     public const val TYPE_ALIAS: String = "TYPE_ALIAS"
@@ -176,10 +180,6 @@ public object WarningNames {
     public const val GENERIC_VARIABLE_WRONG_DECLARATION: String =
             "GENERIC_VARIABLE_WRONG_DECLARATION"
 
-    public const val STRING_TEMPLATE_CURLY_BRACES: String = "STRING_TEMPLATE_CURLY_BRACES"
-
-    public const val STRING_TEMPLATE_QUOTES: String = "STRING_TEMPLATE_QUOTES"
-
     public const val FLOAT_IN_ACCURATE_CALCULATIONS: String = "FLOAT_IN_ACCURATE_CALCULATIONS"
 
     public const val AVOID_NULL_CHECKS: String = "AVOID_NULL_CHECKS"
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/files/BlankLinesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/files/BlankLinesRule.kt
index f5f6c22260..023da07666 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/files/BlankLinesRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/files/BlankLinesRule.kt
@@ -3,11 +3,16 @@ package org.cqfn.diktat.ruleset.rules.files
 import com.pinterest.ktlint.core.Rule
 import com.pinterest.ktlint.core.ast.ElementType.BLOCK
 import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY
+import com.pinterest.ktlint.core.ast.ElementType.FILE
+import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_LITERAL
+import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_EXPRESSION
 import com.pinterest.ktlint.core.ast.ElementType.LBRACE
 import com.pinterest.ktlint.core.ast.ElementType.RBRACE
 import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
 import org.cqfn.diktat.common.config.rules.RulesConfig
 import org.cqfn.diktat.ruleset.constants.Warnings.TOO_MANY_BLANK_LINES
+import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType
+import org.cqfn.diktat.ruleset.utils.getFirstChildWithType
 import org.cqfn.diktat.ruleset.utils.leaveExactlyNumNewLines
 import org.cqfn.diktat.ruleset.utils.leaveOnlyOneNewLine
 import org.cqfn.diktat.ruleset.utils.numNewLines
@@ -39,7 +44,7 @@ class BlankLinesRule(private val configRules: List<RulesConfig>) : Rule("blank-l
     }
 
     private fun handleBlankLine(node: ASTNode) {
-        if (node.treeParent.elementType.let { it == BLOCK || it == CLASS_BODY }) {
+        if (node.treeParent.elementType.let { it == BLOCK || it == CLASS_BODY || it == FUNCTION_LITERAL }) {
             if ((node.treeNext.elementType == RBRACE) xor (node.treePrev.elementType == LBRACE)) {
                 // if both are present, this is not beginning or end
                 // if both are null, then this block is empty and is handled in another rule
@@ -53,7 +58,10 @@ class BlankLinesRule(private val configRules: List<RulesConfig>) : Rule("blank-l
 
     private fun handleTooManyBlankLines(node: ASTNode) {
         TOO_MANY_BLANK_LINES.warnAndFix(configRules, emitWarn, isFixMode, "do not use more than two consecutive blank lines", node.startOffset, node) {
-            node.leaveExactlyNumNewLines(2)
+            if (node.treeParent.elementType != FILE && node.treeParent.getFirstChildWithType(WHITE_SPACE) == node)
+                node.leaveExactlyNumNewLines(1)
+            else
+                node.leaveExactlyNumNewLines(2)
         }
     }
 }


Test patch:
diff --git a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesExpected.kt
index e6835f1341..2a5b877daf 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesExpected.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesExpected.kt
@@ -4,4 +4,10 @@ class Example {
     fun foo() {
         bar()
     }
+
+    fun bar() {
+        println()
+        println()
+    }
 }
+
diff --git a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesTest.kt b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesTest.kt
index 49e09402a2..902d0a26bf 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesTest.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/CodeBlockWithBlankLinesTest.kt
@@ -7,4 +7,12 @@ class Example {
         bar()
 
     }
+
+    fun bar() {
+
+
+        println()
+        println()
+    }
 }
+
diff --git a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesExpected.kt
index d227da0a2c..e71d8117dd 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesExpected.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesExpected.kt
@@ -1,8 +1,14 @@
 package test.paragraph3.blank_lines
 
 class Example {
-
     val foo = 0
 
     fun bar() { }
+
+    fun foo() {
+        list.map {
+            bar()
+        }
+    }
 }
+
diff --git a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesTest.kt b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesTest.kt
index c875259e9d..7848551585 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesTest.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/blank_lines/RedundantBlankLinesTest.kt
@@ -8,4 +8,12 @@ class Example {
 
 
     fun bar() { }
+
+    fun foo() {
+        list.map {
+
+            bar()
+        }
+    }
 }
+