Skip to content

Commit

Permalink
Merge branch 'master' of github.com:shyiko/ktlint
Browse files Browse the repository at this point in the history
* 'master' of github.com:shyiko/ktlint:
  CI with JDK 8
  Upgrade to kotlin 1.1.3-2
  🤦
  allow for named lambdas
  Fix misleading indent lint error message
  Added 0.8.3 release note(s)
  Fixed #55 - If `setValue` is declared as an extension method ktlint thinks its unused
  Fixed #59 - Semicolon at end of package declaration not reported, different error instead
  Fix regression for spacing around else keyword
  Implement spacing after setter and getter
  Add test cases for spacing after setter and getter
  Added 0.8.2 release note
  Fixed #54 - if `getValue` is declared as an extension method ktlint thinks its unused
  • Loading branch information
shyiko committed Jul 24, 2017
2 parents a789988 + 0b2f004 commit 9909af5
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 28 deletions.
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ respectively (`--ruleset-*` will be removed in 1.0.0).
- `ktlint-intellij-idea-integration` binary
([Intellij IDEA integration](https://github.com/shyiko/ktlint#option-1-recommended) task is now included in `ktlint` (as `ktlint --apply-to-idea`)).

## [0.8.3] - 2017-06-19

### Fixed

- "Missing spacing after ";"" at the end of package declaration ([#59](https://github.com/shyiko/ktlint/issues/59)).
- "Unused import" false positive (`setValue`) ([#55](https://github.com/shyiko/ktlint/issues/55)).
- `get`/`set`ter spacing ([#56](https://github.com/shyiko/ktlint/pull/56)).

## [0.8.2] - 2017-06-06

### Fixed

- "Unused import" false positive (`getValue`) ([#54](https://github.com/shyiko/ktlint/issues/54)).

## [0.8.1] - 2017-05-30

### Fixed
Expand Down Expand Up @@ -155,7 +169,9 @@ set in `[*{kt,kts}]` section).

## 0.1.0 - 2016-07-27

[0.9.0]: https://github.com/shyiko/ktlint/compare/0.8.1...0.9.0
[0.9.0]: https://github.com/shyiko/ktlint/compare/0.8.3...0.9.0
[0.8.3]: https://github.com/shyiko/ktlint/compare/0.8.2...0.8.3
[0.8.2]: https://github.com/shyiko/ktlint/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/shyiko/ktlint/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/shyiko/ktlint/compare/0.7.1...0.8.0
[0.7.1]: https://github.com/shyiko/ktlint/compare/0.7.0...0.7.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ class IndentationRule : Rule("indent") {
if (node.isPartOf(KtParameterList::class) && firstParameterColumn.value != 0) {
if (firstParameterColumn.value - 1 != it.length) {
emit(offset, "Unexpected indentation (${it.length}) (" +
"parameters should be either vertically aligned or indented by the multiple of 4" +
"parameters should be either vertically aligned or indented by the multiple of $indent" +
")", false)
}
} else {
emit(offset, "Unexpected indentation (${it.length}) (it should be multiple of 4)", false)
emit(offset, "Unexpected indentation (${it.length}) (it should be multiple of $indent)", false)
}
}
offset += it.length + 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ class NoSemicolonsRule : Rule("no-semi") {
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
if (node is LeafPsiElement && node.textMatches(";") && !node.isPartOfString() &&
!node.isPartOf(KtEnumEntry::class)) {
val nextLeaf = PsiTreeUtil.nextLeaf(node)
val nextLeaf = PsiTreeUtil.nextLeaf(node, true)
if (nextLeaf == null /* eof */ ||
(nextLeaf is PsiWhiteSpace && (nextLeaf.text.contains("\n") ||
PsiTreeUtil.nextLeaf(nextLeaf) == null /* \s+ and then eof */))
PsiTreeUtil.nextLeaf(nextLeaf, true) == null /* \s+ and then eof */))
) {
emit(node.startOffset, "Unnecessary semicolon", true)
if (autoCorrect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class NoUnusedImportsRule : Rule("no-unused-imports") {
// comparison
"compareTo",
// iteration (https://github.com/shyiko/ktlint/issues/40)
"iterator"
"iterator",
// by (https://github.com/shyiko/ktlint/issues/54)
"getValue", "setValue"
)
private val ref = mutableSetOf("*")
private var packageName = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SpacingAroundCommaRule : Rule("comma-spacing") {

override fun visit(node: ASTNode, autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
if (node is LeafPsiElement && (node.textMatches(",") || node.textMatches(";")) && !node.isPartOfString() &&
if (node is LeafPsiElement && node.textMatches(",") && !node.isPartOfString() &&
PsiTreeUtil.nextLeaf(node) !is PsiWhiteSpace) {
emit(node.startOffset + 1, "Missing spacing after \"${node.text}\"", true)
if (autoCorrect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class SpacingAroundCurlyRule : Rule("curly-spacing") {
val spacingBefore: Boolean
val spacingAfter: Boolean
if (node.textMatches("{")) {
spacingBefore = prevLeaf is PsiWhiteSpace || (prevLeaf?.node?.elementType == KtTokens.LPAR &&
spacingBefore = prevLeaf is PsiWhiteSpace || prevLeaf?.node?.elementType == KtTokens.AT || (prevLeaf?.node?.elementType == KtTokens.LPAR &&
(node.parent is KtLambdaExpression || node.parent.parent is KtLambdaExpression))
spacingAfter = nextLeaf is PsiWhiteSpace || nextLeaf?.node?.elementType == KtTokens.RBRACE
} else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl
import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.CATCH_KEYWORD
import org.jetbrains.kotlin.lexer.KtTokens.DO_KEYWORD
import org.jetbrains.kotlin.lexer.KtTokens.ELSE_KEYWORD
Expand All @@ -16,32 +17,45 @@ import org.jetbrains.kotlin.lexer.KtTokens.IF_KEYWORD
import org.jetbrains.kotlin.lexer.KtTokens.TRY_KEYWORD
import org.jetbrains.kotlin.lexer.KtTokens.WHEN_KEYWORD
import org.jetbrains.kotlin.lexer.KtTokens.WHILE_KEYWORD
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtWhenEntry
import org.jetbrains.kotlin.psi.psiUtil.nextLeaf

class SpacingAroundKeywordRule : Rule("keyword-spacing") {

private val noLFBeforeSet = TokenSet.create(ELSE_KEYWORD, CATCH_KEYWORD, FINALLY_KEYWORD)
private val tokenSet = TokenSet.create(FOR_KEYWORD, IF_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
TRY_KEYWORD, CATCH_KEYWORD, FINALLY_KEYWORD, WHEN_KEYWORD)
// todo: but not after fun(, get(, set(

private val keywordsWithoutSpaces = TokenSet.create(KtTokens.GET_KEYWORD, KtTokens.SET_KEYWORD)

override fun visit(node: ASTNode, autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
if (tokenSet.contains(node.elementType) && node is LeafPsiElement &&
PsiTreeUtil.nextLeaf(node) !is PsiWhiteSpace) {
emit(node.startOffset + node.text.length, "Missing spacing after \"${node.text}\"", true)
if (autoCorrect) {
node.rawInsertAfterMe(PsiWhiteSpaceImpl(" "))
}
}
if (noLFBeforeSet.contains(node.elementType) && node is LeafPsiElement) {
val prevLeaf = PsiTreeUtil.prevLeaf(node)
if (prevLeaf is PsiWhiteSpaceImpl && prevLeaf.textContains('\n') &&
(node.elementType != ELSE_KEYWORD || node.parent !is KtWhenEntry) &&
(PsiTreeUtil.prevLeaf(prevLeaf)?.textMatches("}") ?: false)) {
emit(node.startOffset, "Unexpected newline before \"${node.text}\"", true)
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {

if (node is LeafPsiElement) {
if (tokenSet.contains(node.elementType) && node.nextLeaf() !is PsiWhiteSpace) {
emit(node.startOffset + node.text.length, "Missing spacing after \"${node.text}\"", true)
if (autoCorrect) {
prevLeaf.rawReplaceWithText(" ")
node.rawInsertAfterMe(PsiWhiteSpaceImpl(" "))
}
} else if (keywordsWithoutSpaces.contains(node.elementType) && node.nextLeaf() is PsiWhiteSpace) {
val parent = node.parent
if (parent is KtPropertyAccessor && parent.hasBody()) {
emit(node.startOffset, "Unexpected spacing after \"${node.text}\"", true)
if (autoCorrect) {
node.nextLeaf()?.delete()
}
}
}
if (noLFBeforeSet.contains(node.elementType)) {
val prevLeaf = PsiTreeUtil.prevLeaf(node)
if (prevLeaf is PsiWhiteSpaceImpl && prevLeaf.textContains('\n') &&
(node.elementType != ELSE_KEYWORD || node.parent !is KtWhenEntry) &&
(PsiTreeUtil.prevLeaf(prevLeaf)?.textMatches("}") ?: false)) {
emit(node.startOffset, "Unexpected newline before \"${node.text}\"", true)
if (autoCorrect) {
prevLeaf.rawReplaceWithText(" ")
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,18 @@ class IndentationRuleTest {
)).isEmpty()
}

@Test
fun testErrorWithCustomIndentSize() {
assertThat(IndentationRule().lint(
"""
fun main() {
val v = ""
println(v)
}
""".trimIndent(),
mapOf("indent_size" to "3")
)).isEqualTo(listOf(
LintError(3, 1, "indent", "Unexpected indentation (4) (it should be multiple of 3)")
))
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.github.shyiko.ktlint.ruleset.standard

import com.github.shyiko.ktlint.core.LintError
import com.github.shyiko.ktlint.test.lint
import com.github.shyiko.ktlint.test.format
import com.github.shyiko.ktlint.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.testng.annotations.Test

Expand All @@ -12,14 +12,17 @@ class NoSemicolonsRuleTest {
fun testLint() {
assertThat(NoSemicolonsRule().lint(
"""
package a.b.c;
fun main() {
fun name() { a(); return b }
println(";")
println();
}
""".trimIndent()
)).isEqualTo(listOf(
LintError(4, 14, "no-semi", "Unnecessary semicolon")
LintError(1, 14, "no-semi", "Unnecessary semicolon"),
LintError(6, 14, "no-semi", "Unnecessary semicolon")
))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.github.shyiko.ktlint.ruleset.standard

import com.github.shyiko.ktlint.core.LintError
import com.github.shyiko.ktlint.test.lint
import com.github.shyiko.ktlint.test.format
import com.github.shyiko.ktlint.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.testng.annotations.Test

Expand All @@ -11,6 +11,7 @@ class SpacingAroundCurlyRuleTest {
@Test
fun testLint() {
assertThat(SpacingAroundCurlyRule().lint("fun emit() { }")).isEmpty()
assertThat(SpacingAroundCurlyRule().lint("fun emit() { val a = a@{ } }")).isEmpty()
assertThat(SpacingAroundCurlyRule().lint("fun emit() {}")).isEmpty()
assertThat(SpacingAroundCurlyRule().lint("fun main() { val v = if (true){return 0} }"))
.isEqualTo(listOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.github.shyiko.ktlint.ruleset.standard

import com.github.shyiko.ktlint.core.LintError
import com.github.shyiko.ktlint.test.lint
import com.github.shyiko.ktlint.test.format
import com.github.shyiko.ktlint.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.testng.annotations.Test

Expand Down Expand Up @@ -94,5 +94,47 @@ class SpacingAroundKeywordRuleTest {
)
}

@Test
fun getterAndSetterFunction() {
assertThat(SpacingAroundKeywordRule().format(
"""
var x: String
get () {
return ""
}
private set (value) {
x = value
}
""".trimIndent()
)).isEqualTo(
"""
var x: String
get() {
return ""
}
private set(value) {
x = value
}
""".trimIndent()
)
}

@Test
fun visibilityOrInjectProperty() {
assertThat(SpacingAroundKeywordRule().lint(
"""
var setterVisibility: String = "abc"
private set
var setterWithAnnotation: Any? = null
@Inject set
var setterOnNextLine: String
private set
(value) { setterOnNextLine = value}
"""
)).isEqualTo(listOf(
LintError(7, 21, "keyword-spacing", "Unexpected spacing after \"set\"")
))
}

}

0 comments on commit 9909af5

Please sign in to comment.