Skip to content

Commit

Permalink
Add new experimental rule "function-signature" (#1459)
Browse files Browse the repository at this point in the history
This rule rewrites the function signature to a single line when possible (e.g. when not exceeding the "max_line_length" property) or a multiline signature otherwise. In case of function with a body expression, the body expression is placed on the same line as the function signature when not exceeding the "max_line_length" property. 

Optionally the function signature can be forced to be written as a multiline signature in case the function has more than a specified number of parameters (".editorconfig" property "ktlint_function_signature_wrapping_rule_always_with_minimum_parameters")
  • Loading branch information
paul-dingemans authored May 18, 2022
1 parent cdc39b1 commit e480944
Show file tree
Hide file tree
Showing 9 changed files with 1,319 additions and 12 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ An AssertJ style API for testing KtLint rules ([#1444](https://github.com/pinter
- Add experimental rule for incorrect spacing around the function return type (`function-return-type-spacing`) ([#1341](https://github.com/pinterest/ktlint/pull/1341))
- Add experimental rule for unexpected spaces in a nullable type (`nullable-type-spacing`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))
- Do not add a space after the typealias name (`type-parameter-list-spacing`) ([#1435](https://github.com/pinterest/ktlint/issues/1435))

- Add experimental rule for consistent spacing before the start of the function body (`function-start-of-body-spacing`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))
- Add experimental rule for rewriting the function signature (`function-signature`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))

### Fixed
- Fix check of spacing in the receiver type of an anonymous function ([#1440](https://github.com/pinterest/ktlint/issues/1440))
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ by passing the `--experimental` flag to `ktlint`.
- `experimental:package-name`: No underscores in package names
- `experimental:parameter-list-spacing`: Consistent spacing inside the parameter list
- `experimental:unnecessary-parentheses-before-trailing-lambda`: An empty parentheses block before a lambda is redundant. For example `some-string".count() { it == '-' }`
- `function-signature`: rewrites the function signature to a single line when possible (e.g. when not exceeding the `max_line_length` property) or a multiline signature otherwise. In case of function with a body expression, the body expression is placed on the same line as the function signature when not exceeding the `max_line_length` property. Optionally the function signature can be forced to be written as a multiline signature in case the function has more than a specified number of parameters (`.editorconfig' property `ktlint_function_signature_wrapping_rule_always_with_minimum_parameters`)
### Spacing
- `experimental:annotation-spacing`: Annotations should be separated by the annotated declaration by a single line break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class ExperimentalRuleSetProvider : RuleSetProvider {
ParameterListSpacingRule(),
FunctionReturnTypeSpacingRule(),
FunctionStartOfBodySpacingRule(),
NullableTypeSpacingRule()
NullableTypeSpacingRule(),
FunctionSignatureRule()
)
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public class FunctionStartOfBodySpacingRule : Rule("function-start-of-body-spaci
emit(block.startOffset, "Expected a single white space before start of function body", true)
if (autoCorrect) {
if (whiteSpaceBeforeExpressionBlock == null) {
(block.firstChildNode as LeafPsiElement).upsertWhitespaceBeforeMe(" ")
(block.firstChildNode.prevLeaf(true) as LeafPsiElement).upsertWhitespaceAfterMe(" ")
} else {
(whiteSpaceBeforeExpressionBlock as LeafElement).rawReplaceWithText(" ")
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ public class IndentationRule :
id = "indent",
visitorModifiers = setOf(
VisitorModifier.RunOnRootNodeOnly,
VisitorModifier.RunAsLateAsPossible
VisitorModifier.RunAsLateAsPossible,
VisitorModifier.RunAfterRule(
ruleId = "experimental:function-signature",
loadOnlyWhenOtherRuleIsLoaded = false,
runOnlyWhenOtherRuleIsEnabled = false
)
)
),
UsesEditorConfigProperties {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ public class EditorConfigTestRule {
* values. Please, be aware that this class also contains a lot of deprecated methods which you should not use
* either.
*/
public fun writeToEditorConfig(
content: Map<PropertyType<*>, String>,
lintedFileExtension: String = ".kt"
): File {
public fun writeToEditorConfig(content: Map<PropertyType<*>, String>, lintedFileExtension: String = ".kt"): File {
throw UnsupportedOperationException("This functionality has been removed. See deprecation notice and KDoc.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,27 @@ public class KtLintAssertThat(
* Adds a rule to be executed when formatting the code. This can to be used to unit test rules which are best to be
* tested in conjunction, for example wrapping and indenting. This method can be called multiple times if needed.
*/
public fun addAdditionalFormattingRule(rule: Rule): KtLintAssertThat {
additionalFormattingRules.add(rule)
public fun addAdditionalFormattingRule(vararg rules: Rule): KtLintAssertThat {
additionalFormattingRules.addAll(rules)

return this
}

/**
* Asserts that the code does not contain any [LintViolation]s.
* Asserts that the code does not contain any [LintViolation]s in the rule associated with the KtLintAssertThat.
*
* Note: When linting succeeds without errors, formatting is also checked.
*/
public fun hasNoLintViolations(): Unit = ktLintAssertThatAssertable().hasNoLintViolations()

/**
* Asserts that the code does not contain any [LintViolation]s except in the additional formatting rules.
*
* Note: When linting succeeds without errors, formatting is also checked.
*/
public fun hasNoLintViolationsExceptInAdditionalFormattingRules(): KtLintAssertThatAssertable =
ktLintAssertThatAssertable().hasNoLintViolationsExceptInAdditionalFormattingRules()

/**
* Asserts that the code does contain given [LintViolation] which automatically can be corrected. This is a sugar
* coated version of [hasLintViolations] for the case that the code contains exactly one lint violation.
Expand Down Expand Up @@ -218,7 +226,7 @@ public class KtLintAssertThatAssertable(
) : AbstractAssert<KtLintAssertThatAssertable, String>(code, KtLintAssertThatAssertable::class.java) {

/**
* Asserts that the code does not contain any [LintViolation]s.
* Asserts that the code does not contain any [LintViolation]s in the rule associated with the KtLintAssertThat.
*
* Note: When linting succeeds without errors, formatting is also checked.
*/
Expand All @@ -233,6 +241,27 @@ public class KtLintAssertThatAssertable(
.isEqualTo(code)
}

/**
* Asserts that the code does not contain any [LintViolation]s except in the additional formatting rules.
*
* Note that this method can and should be chained with [isFormattedAs] to verify whether the code is correctly
* formatted.
*
* This method can be used when the rule which is associated with the KtLintAssertThat is not violated by the sample
* code, but the code is reformatted by the additional formatting rules. In case that rules are dependent on each
* other, a unit test cal still verify that code is formatted correctly even when the rule under test is not
* violated.
*/
public fun hasNoLintViolationsExceptInAdditionalFormattingRules(): KtLintAssertThatAssertable {
check(additionalFormattingRules.isNotEmpty()) {
"hasNoLintViolationsExceptInAdditionalFormattingRules can only be used when additional formatting rules have been added"
}

assertThat(lint()).isEmpty()

return this
}

/**
* Asserts that the code does contain given [LintViolation]. This is a sugar coated version of
* [hasLintViolation] for the case that the code contains exactly one lint violation.
Expand Down

0 comments on commit e480944

Please sign in to comment.