new rule: NoLineBreakAfterElse

Reports line breaks after "else" clause. Supports auto format by replacing linebreak with space.
Doesn't take into account maximum line length.
diff --git a/ktlint-core/src/test/kotlin/com/github/shyiko/ktlint/core/KtLintTest.kt b/ktlint-core/src/test/kotlin/com/github/shyiko/ktlint/core/KtLintTest.kt
index d3e30a7..3e6840a 100644
--- a/ktlint-core/src/test/kotlin/com/github/shyiko/ktlint/core/KtLintTest.kt
+++ b/ktlint-core/src/test/kotlin/com/github/shyiko/ktlint/core/KtLintTest.kt
@@ -15,8 +15,7 @@
                 emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
                 if (node.elementType == KtStubElementTypes.FILE) {
                     bus.add("file:$id")
-                } else
-                if (!done) {
+                } else if (!done) {
                     bus.add(id)
                     done = true
                 }
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/ChainWrappingRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/ChainWrappingRule.kt
index dda6839..63549b1 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/ChainWrappingRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/ChainWrappingRule.kt
@@ -46,8 +46,7 @@
                     }
                 }
             }
-        } else
-        if (sameLineTokens.contains(elementType)) {
+        } else if (sameLineTokens.contains(elementType)) {
             val prevLeaf = node.psi.prevLeaf(true)
             if (prevLeaf is PsiWhiteSpaceImpl && prevLeaf.textContains('\n')) {
                 emit(node.startOffset, "Line must not begin with \"${node.text}\"", true)
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRule.kt
new file mode 100644
index 0000000..3b904d4
--- /dev/null
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRule.kt
@@ -0,0 +1,31 @@
+package com.github.shyiko.ktlint.ruleset.standard
+
+import com.github.shyiko.ktlint.core.Rule
+import org.jetbrains.kotlin.KtNodeTypes
+import org.jetbrains.kotlin.com.intellij.lang.ASTNode
+import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
+import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
+import org.jetbrains.kotlin.lexer.KtKeywordToken
+
+class NoLineBreakAfterElseRule : Rule(RULE_ID) {
+    override fun visit(node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
+        if (node is PsiWhiteSpace) {
+            if (
+            node.nextSibling?.node?.elementType == KtNodeTypes.ELSE
+                && node.prevSibling?.node?.elementType is KtKeywordToken
+                && node.prevSibling.text == "else"
+                && node.getText().contains("\n")) {
+                emit(node.startOffset + 1,
+                    "Unexpected line break after \"else\"",
+                    true)
+                if (autoCorrect) {
+                    (node as LeafPsiElement).rawReplaceWithText(" ")
+                }
+            }
+        }
+    }
+
+    companion object {
+        const val RULE_ID = "no-line-break-after-else"
+    }
+}
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoMultipleSpacesRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoMultipleSpacesRule.kt
index 0fcd6e8..e57aed3 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoMultipleSpacesRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoMultipleSpacesRule.kt
@@ -51,8 +51,7 @@
             emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
         if (node.elementType == KtStubElementTypes.FILE) {
             fileNode = node
-        } else
-        if (node is PsiWhiteSpace && !node.textContains('\n') && node.getTextLength() > 1) {
+        } else if (node is PsiWhiteSpace && !node.textContains('\n') && node.getTextLength() > 1) {
             val nextLeaf = PsiTreeUtil.nextLeaf(node, true)
             if (nextLeaf is PsiComment) {
                 val positionMap = commentMap
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoTrailingSpacesRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoTrailingSpacesRule.kt
index 5d81af6..dc64bb7 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoTrailingSpacesRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoTrailingSpacesRule.kt
@@ -17,8 +17,7 @@
                 if (autoCorrect) {
                     (node as LeafPsiElement).rawReplaceWithText("\n".repeat(lines.size - 1) + lines.last())
                 }
-            } else
-            if (PsiTreeUtil.nextLeaf(node) == null /* eof */) {
+            } else if (PsiTreeUtil.nextLeaf(node) == null /* eof */) {
                 checkForTrailingSpaces(lines, node.startOffset, emit)
                 if (autoCorrect) {
                     (node as LeafPsiElement).rawReplaceWithText("\n".repeat(lines.size - 1))
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
index 4d9618b..9961b67 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
@@ -52,18 +52,15 @@
                 if (type == KDocTokens.MARKDOWN_LINK && psi is KDocLink) {
                     val linkText = psi.getLinkText().replace("`", "")
                     ref.add(linkText.split('.').first())
-                } else
-                if ((type == KtNodeTypes.REFERENCE_EXPRESSION || type == KtNodeTypes.OPERATION_REFERENCE) &&
+                } else if ((type == KtNodeTypes.REFERENCE_EXPRESSION || type == KtNodeTypes.OPERATION_REFERENCE) &&
                     !psi.isPartOf(KtImportDirective::class)) {
                     ref.add(vnode.text.trim('`'))
                 }
             }
-        } else
-        if (node.elementType == KtStubElementTypes.PACKAGE_DIRECTIVE) {
+        } else if (node.elementType == KtStubElementTypes.PACKAGE_DIRECTIVE) {
             val packageDirective = node.psi as KtPackageDirective
             packageName = packageDirective.qualifiedName
-        } else
-        if (node.elementType == KtStubElementTypes.IMPORT_DIRECTIVE) {
+        } else if (node.elementType == KtStubElementTypes.IMPORT_DIRECTIVE) {
             val importDirective = node.psi as KtImportDirective
             val name = importDirective.importPath?.importedName?.asString()
             val importPath = importDirective.importPath?.pathStr!!
@@ -74,8 +71,7 @@
                 if (autoCorrect) {
                     importDirective.delete()
                 }
-            } else
-            if (name != null && !ref.contains(name) && !operatorSet.contains(name)) {
+            } else if (name != null && !ref.contains(name) && !operatorSet.contains(name)) {
                 emit(importDirective.startOffset, "Unused import", true)
                 if (autoCorrect) {
                     importDirective.delete()
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/SpacingAroundCurlyRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/SpacingAroundCurlyRule.kt
index f592ca1..c46c477 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/SpacingAroundCurlyRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/SpacingAroundCurlyRule.kt
@@ -44,8 +44,7 @@
                         (prevLeaf.node as LeafPsiElement).rawReplaceWithText(" ")
                     }
                 }
-            } else
-            if (node.textMatches("}")) {
+            } else if (node.textMatches("}")) {
                 spacingBefore = prevLeaf is PsiWhiteSpace || prevLeaf?.node?.elementType == KtTokens.LBRACE
                 spacingAfter = nextLeaf == null || nextLeaf is PsiWhiteSpace || shouldNotToBeSeparatedBySpace(nextLeaf)
                 if (nextLeaf is PsiWhiteSpace && !nextLeaf.textContains('\n') &&
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/StandardRuleSetProvider.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/StandardRuleSetProvider.kt
index aa57a54..cdb5b0c 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/StandardRuleSetProvider.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/StandardRuleSetProvider.kt
@@ -10,6 +10,7 @@
         FinalNewlineRule(),
         // disabled until it's clear how to reconcile difference in Intellij & Android Studio import layout
         // ImportOrderingRule(),
+        NoLineBreakAfterElseRule(),
         IndentationRule(),
         MaxLineLengthRule(),
         ModifierOrderRule(),
diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRuleTest.kt
new file mode 100644
index 0000000..6bb70bf
--- /dev/null
+++ b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakAfterElseRuleTest.kt
@@ -0,0 +1,128 @@
+package com.github.shyiko.ktlint.ruleset.standard
+
+import com.github.shyiko.ktlint.core.LintError
+import com.github.shyiko.ktlint.test.format
+import com.github.shyiko.ktlint.test.lint
+import org.assertj.core.api.Assertions
+import org.testng.annotations.Test
+
+class NoLineBreakAfterElseRuleTest {
+    @Test
+    fun testViolationForLineBreakBetweenElseAndIf() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else
+                if (conditionB()) {
+                    doAnotherThing()
+                }
+            }
+            """.trimIndent()
+        )).isEqualTo(listOf(
+            LintError(5, 1, NoLineBreakAfterElseRule.RULE_ID, "Unexpected line break after \"else\"")
+        ))
+    }
+
+    @Test
+    fun testFixViolationForLineBreakBetweenElseAndIf() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().format(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else
+                if (conditionB()) {
+                    doAnotherThing()
+                }
+            }
+            """.trimIndent()
+        )).isEqualTo(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else if (conditionB()) {
+                    doAnotherThing()
+                }
+            }
+                """.trimIndent()
+        )
+    }
+
+    @Test
+    fun testValidElseIf() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else if (conditionB()) {
+                    doAnotherThing()
+                }
+            }
+            """.trimIndent()
+        )).isEmpty()
+    }
+
+    @Test
+    fun testValidSimpleElse() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else {
+                    doAnotherThing()
+                }
+            }
+            """.trimIndent()
+        )).isEmpty()
+    }
+
+    @Test
+    fun testViolationForLineBreakBetweenElseAndBracket() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA()) {
+                    doSomething()
+                } else
+                {
+                    doAnotherThing()
+                }
+            }
+            """.trimIndent()
+        )).isEqualTo(listOf(
+            LintError(5, 1, NoLineBreakAfterElseRule.RULE_ID, "Unexpected line break after \"else\"")
+        ))
+    }
+
+    @Test
+    fun testViolationWhenBracketOmitted() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA())
+                    doSomething()
+                else
+                    doAnotherThing()
+            }
+            """.trimIndent()
+        )).isEqualTo(listOf(
+            LintError(5, 1, NoLineBreakAfterElseRule.RULE_ID, "Unexpected line break after \"else\"")
+        ))
+    }
+
+    @Test
+    fun testValidWhenBracketOmitted() {
+        Assertions.assertThat(NoLineBreakAfterElseRule().lint(
+            """
+            fun funA() {
+                if (conditionA()) doSomething() else doAnotherThing()
+            }
+            """.trimIndent()
+        )).isEmpty()
+    }
+}
diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/package-test.kt b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/package-test.kt
index 016cbd4..3c42d4b 100644
--- a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/package-test.kt
+++ b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/package-test.kt
@@ -20,14 +20,17 @@
     }
     val input = resourceText.substring(0, dividerIndex)
     val errors = resourceText.substring(dividerIndex + 1).split('\n').mapNotNull { line ->
-        if (line.isBlank() || line == "// expect") null else
+        if (line.isBlank() || line == "// expect") {
+            null
+        } else {
             line.trimMargin("// ").split(':', limit = 3).let { expectation ->
                 if (expectation.size != 3) {
                     throw RuntimeException("$resource expectation must be a triple <line>:<column>:<message>")
-                        // " (<message> is not allowed to contain \":\")")
+                    // " (<message> is not allowed to contain \":\")")
                 }
                 LintError(expectation[0].toInt(), expectation[1].toInt(), rule.id, expectation[2])
             }
+        }
     }
     assertThat(rule.lint(input, userData)).isEqualTo(errors)
 }
diff --git a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
index 593b240..23b7f00 100644
--- a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
+++ b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
@@ -373,8 +373,7 @@
             }
             val stream = if (output != null) {
                 File(output).parentFile?.mkdirsOrFail(); PrintStream(output, "UTF-8")
-            } else
-                if (stdin) System.err else System.out
+            } else if (stdin) System.err else System.out
             return reporterProvider.get(stream, config)
                 .let { reporter ->
                     if (output != null)
@@ -384,8 +383,7 @@
                                 stream.close()
                             }
                         }
-                    else
-                        reporter
+                    else reporter
                 }
         }
         return Reporter.from(*tpls.map { it.toReporter() }.toTypedArray())
@@ -584,13 +582,11 @@
 
     private fun lint(fileName: String, text: String, ruleSets: Iterable<RuleSet>, userData: Map<String, String>,
             cb: (e: LintError) -> Unit) =
-        if (fileName.endsWith(".kt", ignoreCase = true)) KtLint.lint(text, ruleSets, userData, cb) else
-            KtLint.lintScript(text, ruleSets, userData, cb)
+        if (fileName.endsWith(".kt", ignoreCase = true)) KtLint.lint(text, ruleSets, userData, cb) else KtLint.lintScript(text, ruleSets, userData, cb)
 
     private fun format(fileName: String, text: String, ruleSets: Iterable<RuleSet>, userData: Map<String, String>,
             cb: (e: LintError, corrected: Boolean) -> Unit): String =
-        if (fileName.endsWith(".kt", ignoreCase = true)) KtLint.format(text, ruleSets, userData, cb) else
-            KtLint.formatScript(text, ruleSets, userData, cb)
+        if (fileName.endsWith(".kt", ignoreCase = true)) KtLint.format(text, ruleSets, userData, cb) else KtLint.formatScript(text, ruleSets, userData, cb)
 
     private fun java.net.URLClassLoader.addURLs(url: Iterable<java.net.URL>) {
         val method = java.net.URLClassLoader::class.java.getDeclaredMethod("addURL", java.net.URL::class.java)
diff --git a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/MavenDependencyResolver.kt b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/MavenDependencyResolver.kt
index 9d74666..9ebf5fd 100644
--- a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/MavenDependencyResolver.kt
+++ b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/MavenDependencyResolver.kt
@@ -23,7 +23,7 @@
 import java.io.File
 
 class MavenDependencyResolver(baseDir: File, val repositories: Iterable<RemoteRepository>,
-    forceUpdate: Boolean) {
+                              forceUpdate: Boolean) {
 
     private val repoSystem: RepositorySystem
     private val session: RepositorySystemSession
@@ -41,8 +41,11 @@
         repoSystem = locator.getService(RepositorySystem::class.java)
         session = MavenRepositorySystemUtils.newSession()
         session.localRepositoryManager = repoSystem.newLocalRepositoryManager(session, LocalRepository(baseDir))
-        session.updatePolicy = if (forceUpdate) RepositoryPolicy.UPDATE_POLICY_ALWAYS else
+        session.updatePolicy = if (forceUpdate) {
+            RepositoryPolicy.UPDATE_POLICY_ALWAYS
+        } else {
             RepositoryPolicy.UPDATE_POLICY_NEVER
+        }
     }
 
     fun setTransferEventListener(listener: (event: TransferEvent) -> Unit) {