Skip to content

Commit

Permalink
Ignore surrounding spaces around the "CodeStyle" and "RuleExecution" …
Browse files Browse the repository at this point in the history
…values in the '.editorconfig' file

The default EnumValueParser of ec4j does not ignore such spaces which incorrectly leads to values not parsed correctly. Additional trailing space typically result from EOL comments in the '.editorconfig' file. For example:
`codestyle = official # some comment`.
The comment (including the hash sign) is ignored correctly but the space which separates the value and the hash sign is added to the value itself.
  • Loading branch information
paul-dingemans committed Dec 11, 2022
1 parent c3e1431 commit b2e6c37
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public val CODE_STYLE_PROPERTY: EditorConfigProperty<CodeStyleValue> =
type = PropertyType.LowerCasingPropertyType(
"ktlint_code_style",
"The code style ('official' or 'android') to be applied. Defaults to 'official' when not set.",
EnumValueParser(CodeStyleValue::class.java),
SafeEnumValueParser(CodeStyleValue::class.java),
CodeStyleValue.values().map { it.name }.toSet(),
),
defaultValue = CodeStyleValue.official,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal val RULE_EXECUTION_PROPERTY_TYPE =
PropertyType.LowerCasingPropertyType(
"ktlint_rule_execution",
"When enabled, the rule is being executed.",
PropertyType.PropertyValueParser.EnumValueParser(RuleExecution::class.java),
SafeEnumValueParser(RuleExecution::class.java),
CodeStyleValue.values().map { it.name }.toSet(),
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.pinterest.ktlint.core.api.editorconfig

import java.util.Locale
import org.ec4j.core.model.PropertyType
import org.ec4j.core.model.PropertyType.PropertyValueParser

/**
* A [PropertyValueParser] implementation that allows only members of a given [Enum] type. This class is almost
* identical to the original [EnumValueParser] provided by ec4j. Difference is that values are trimmed before trying to
* match the enum values.
*
* As the ec4j project has not provided any new release since version 1.0 (2019-08-01) a custom implementation has been
* added.
*
* @param <T> the type of the value <T>
*
*/
internal class SafeEnumValueParser<T : Enum<*>?>(enumType: Class<out T?>) : PropertyValueParser<T> {
private val enumType: Class<out Enum<*>?>

init {
this.enumType = enumType
}

override fun parse(name: String?, value: String?): PropertyType.PropertyValue<T> =
if (value == null) {
PropertyType.PropertyValue.invalid(value, "Cannot make enum " + enumType.name + " out of null")
} else {
try {
PropertyType.PropertyValue.valid(
value,
java.lang.Enum.valueOf(
enumType,
value
// In case an EOL comment (separated with a space) is appended after the value then the comment
// itself is removed but not the space. This results in the enum value not being parsed
// correctly.
.trim()
.lowercase(Locale.getDefault()),
) as T,
)
} catch (e: IllegalArgumentException) {
PropertyType.PropertyValue.invalid(
value,
"Unexpected parsed \"" + value + "\" for enum " + enumType.name,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.pinterest.ktlint.core.api.editorconfig

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource

class CodeStyleEditorConfigPropertyTest {
@ParameterizedTest(name = "Value: [{0}], result: [{1}]")
@CsvSource(
value = [
"official,official",
" official,official",
"official ,official",
" official ,official",
"android,android",
" android,android",
"android ,android",
" android ,android",
],
ignoreLeadingAndTrailingWhitespace = false,
)
fun `Given a code style property`(
value: String,
expectedCodeStyleValue: CodeStyleValue,
) {
val actual = CODE_STYLE_PROPERTY.type.parse(value)

assertThat(actual.parsed).isEqualTo(expectedCodeStyleValue)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.pinterest.ktlint.core.api.editorconfig

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource

class RuleExecutionEditorConfigPropertyTest {
@ParameterizedTest(name = "Value: [{0}], result: [{1}]")
@CsvSource(
value = [
"enabled,enabled",
" enabled,enabled",
"enabled ,enabled",
" enabled ,enabled",
"disabled,disabled",
" disabled,disabled",
"disabled ,disabled",
" disabled ,disabled",
],
ignoreLeadingAndTrailingWhitespace = false,
)
fun `Given a rule execution property for which the value`(
value: String,
expectedRuleExecution: RuleExecution,
) {
val actual = RULE_EXECUTION_PROPERTY_TYPE.parse(value)

assertThat(actual.parsed).isEqualTo(expectedRuleExecution)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.pinterest.ktlint.core.api.editorconfig

import org.assertj.core.api.Assertions.assertThat
import org.ec4j.core.model.PropertyType
import org.junit.jupiter.api.Test

class SafeEnumValueParserTest {
@Test
fun `Given a rule execution property for which the value`() {
val propertyType =
PropertyType.LowerCasingPropertyType(
"some-property-type",
null,
SafeEnumValueParser(SomePropertyType::class.java),
SomePropertyType.values().map { it.name }.toSet(),
)

val actual = propertyType.parse(" value2 ")

assertThat(actual.parsed).isEqualTo(SomePropertyType.value2)
}

@Suppress("EnumEntryName")
private enum class SomePropertyType {
value1,
value2,
}
}

0 comments on commit b2e6c37

Please sign in to comment.