mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
# Conflicts: # Tests/BuiltInRulesTests/FileHeaderRuleTests.swift # Tests/BuiltInRulesTests/FileNameNoSpaceRuleTests.swift # Tests/BuiltInRulesTests/IndentationWidthRuleTests.swift # Tests/CoreTests/RegexConfigurationTests.swift # Tests/CoreTests/SwiftLintFileTests.swift # Tests/FileSystemAccessTests/BaselineTests.swift # Tests/FileSystemAccessTests/ConfigurationTests+Mock.swift # Tests/FileSystemAccessTests/ConfigurationTests.swift # Tests/FileSystemAccessTests/GlobTests.swift # Tests/FileSystemAccessTests/MultipleConfigurationsTests.swift # Tests/FileSystemAccessTests/ReporterTests.swift # Tests/FileSystemAccessTests/SourceKitCrashTests.swift # Tests/FrameworkTests/CustomRulesTests.swift # Tests/FrameworkTests/LinterCacheTests.swift # Tests/FrameworkTests/RuleConfigurationTests.swift # Tests/FrameworkTests/SwiftVersionTests.swift # Tests/GeneratedTests/GeneratedTests_02.swift # Tests/GeneratedTests/GeneratedTests_03.swift # Tests/GeneratedTests/GeneratedTests_04.swift # Tests/GeneratedTests/GeneratedTests_05.swift # Tests/GeneratedTests/GeneratedTests_06.swift # Tests/GeneratedTests/GeneratedTests_07.swift # Tests/GeneratedTests/GeneratedTests_08.swift # Tests/GeneratedTests/GeneratedTests_09.swift # Tests/GeneratedTests/GeneratedTests_10.swift # Tests/IntegrationTests/ConfigPathResolutionTests.swift # Tests/IntegrationTests/IntegrationTests.swift # Tests/TestHelpers/TestHelpers.swift
399 lines
14 KiB
Swift
399 lines
14 KiB
Swift
import SourceKittenFramework
|
|
import TestHelpers
|
|
import Testing
|
|
|
|
@testable import SwiftLintBuiltInRules
|
|
@testable import SwiftLintCore
|
|
|
|
@Suite
|
|
struct RuleConfigurationTests {
|
|
private let defaultNestingConfiguration = NestingConfiguration(
|
|
typeLevel: SeverityLevelsConfiguration(warning: 0),
|
|
functionLevel: SeverityLevelsConfiguration(warning: 0)
|
|
)
|
|
|
|
@Test
|
|
func nestingConfigurationSetsCorrectly() {
|
|
let config =
|
|
[
|
|
"type_level": [
|
|
"warning": 7, "error": 17,
|
|
],
|
|
"function_level": [
|
|
"warning": 8, "error": 18,
|
|
],
|
|
"check_nesting_in_closures_and_statements": false,
|
|
"always_allow_one_type_in_functions": true,
|
|
] as [String: any Sendable]
|
|
var nestingConfig = defaultNestingConfiguration
|
|
do {
|
|
try nestingConfig.apply(configuration: config)
|
|
#expect(nestingConfig.typeLevel.warning == 7)
|
|
#expect(nestingConfig.functionLevel.warning == 8)
|
|
#expect(nestingConfig.typeLevel.error == 17)
|
|
#expect(nestingConfig.functionLevel.error == 18)
|
|
#expect(nestingConfig.alwaysAllowOneTypeInFunctions)
|
|
#expect(!nestingConfig.checkNestingInClosuresAndStatements)
|
|
} catch {
|
|
Issue.record("Failed to configure nested configurations")
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func nestingConfigurationThrowsOnBadConfig() {
|
|
let config = 17
|
|
var nestingConfig = defaultNestingConfiguration
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: NestingRule.identifier)) {
|
|
try nestingConfig.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func severityWorksAsOnlyParameter() throws {
|
|
var config = AttributesConfiguration()
|
|
#expect(config.severity == .warning)
|
|
try config.apply(configuration: "error")
|
|
#expect(config.severity == .error)
|
|
}
|
|
|
|
@Test
|
|
func severityConfigurationFromString() {
|
|
let config = "Warning"
|
|
let comp = SeverityConfiguration<MockRule>(.warning)
|
|
var severityConfig = SeverityConfiguration<MockRule>(.error)
|
|
#expect(throws: Never.self) {
|
|
try severityConfig.apply(configuration: config)
|
|
}
|
|
#expect(severityConfig == comp)
|
|
}
|
|
|
|
@Test
|
|
func severityConfigurationFromDictionary() {
|
|
let config = ["severity": "warning"]
|
|
let comp = SeverityConfiguration<MockRule>(.warning)
|
|
var severityConfig = SeverityConfiguration<MockRule>(.error)
|
|
do {
|
|
try severityConfig.apply(configuration: config)
|
|
#expect(severityConfig == comp)
|
|
} catch {
|
|
Issue.record("Failed to configure severity from dictionary")
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func severityConfigurationThrowsNothingApplied() {
|
|
let config = 17
|
|
var severityConfig = SeverityConfiguration<MockRule>(.error)
|
|
#expect(throws: Issue.nothingApplied(ruleID: MockRule.identifier)) {
|
|
try severityConfig.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func severityConfigurationThrowsInvalidConfiguration() {
|
|
let config = "foo"
|
|
var severityConfig = SeverityConfiguration<MockRule>(.warning)
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: MockRule.identifier)) {
|
|
try severityConfig.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func severityLevelConfigParams() {
|
|
let severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 7)
|
|
#expect(
|
|
severityConfig.params == [
|
|
RuleParameter(severity: .error, value: 7),
|
|
RuleParameter(severity: .warning, value: 17),
|
|
]
|
|
)
|
|
}
|
|
|
|
@Test
|
|
func severityLevelConfigPartialParams() {
|
|
let severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: nil)
|
|
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 17)])
|
|
}
|
|
|
|
@Test
|
|
func severityLevelConfigApplyNilErrorValue() throws {
|
|
var severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 20)
|
|
try severityConfig.apply(configuration: ["error": nil, "warning": 18])
|
|
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 18)])
|
|
}
|
|
|
|
@Test
|
|
func severityLevelConfigApplyMissingErrorValue() throws {
|
|
var severityConfig = SeverityLevelsConfiguration<MockRule>(warning: 17, error: 20)
|
|
try severityConfig.apply(configuration: ["warning": 18])
|
|
#expect(severityConfig.params == [RuleParameter(severity: .warning, value: 18)])
|
|
}
|
|
|
|
@Test
|
|
func regexConfigurationThrows() {
|
|
let config = 17
|
|
var regexConfig = RegexConfiguration<MockRule>(identifier: "")
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: MockRule.identifier)) {
|
|
try regexConfig.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func regexRuleDescription() {
|
|
var regexConfig = RegexConfiguration<MockRule>(identifier: "regex")
|
|
#expect(
|
|
regexConfig.description
|
|
== RuleDescription(
|
|
identifier: "regex",
|
|
name: "regex",
|
|
description: "", kind: .style))
|
|
regexConfig.name = "name"
|
|
#expect(
|
|
regexConfig.description
|
|
== RuleDescription(
|
|
identifier: "regex",
|
|
name: "name",
|
|
description: "", kind: .style))
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationThrowsOnBadConfig() {
|
|
let config = "unknown"
|
|
var configuration = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true)
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: TrailingWhitespaceRule.identifier)) {
|
|
try configuration.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationInitializerSetsIgnoresEmptyLines() {
|
|
let configuration1 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true)
|
|
#expect(!configuration1.ignoresEmptyLines)
|
|
|
|
let configuration2 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: true,
|
|
ignoresComments: true)
|
|
#expect(configuration2.ignoresEmptyLines)
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationInitializerSetsIgnoresComments() {
|
|
let configuration1 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true)
|
|
#expect(configuration1.ignoresComments)
|
|
|
|
let configuration2 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: false)
|
|
#expect(!configuration2.ignoresComments)
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationApplyConfigurationSetsIgnoresEmptyLines() {
|
|
var configuration = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true
|
|
)
|
|
let config1 = ["ignores_empty_lines": true]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: config1)
|
|
}
|
|
#expect(configuration.ignoresEmptyLines)
|
|
|
|
let config2 = ["ignores_empty_lines": false]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: config2)
|
|
}
|
|
#expect(!configuration.ignoresEmptyLines)
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationApplyConfigurationSetsIgnoresComments() {
|
|
var configuration = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true
|
|
)
|
|
let config1 = ["ignores_comments": true]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: config1)
|
|
}
|
|
#expect(configuration.ignoresComments)
|
|
|
|
let config2 = ["ignores_comments": false]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: config2)
|
|
}
|
|
#expect(!configuration.ignoresComments)
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationCompares() {
|
|
let configuration1 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true)
|
|
let configuration2 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: true,
|
|
ignoresComments: true)
|
|
#expect(configuration1 != configuration2)
|
|
|
|
let configuration3 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: true,
|
|
ignoresComments: true)
|
|
#expect(configuration2 == configuration3)
|
|
|
|
let configuration4 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: false)
|
|
|
|
#expect(configuration1 != configuration4)
|
|
|
|
let configuration5 = TrailingWhitespaceConfiguration(
|
|
ignoresEmptyLines: true,
|
|
ignoresComments: false)
|
|
|
|
#expect(configuration1 != configuration5)
|
|
}
|
|
|
|
@Test
|
|
func trailingWhitespaceConfigurationApplyConfigurationUpdatesSeverityConfiguration() {
|
|
var configuration = TrailingWhitespaceConfiguration(
|
|
severityConfiguration: .warning,
|
|
ignoresEmptyLines: false,
|
|
ignoresComments: true
|
|
)
|
|
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: ["severity": "error"])
|
|
}
|
|
#expect(configuration.severityConfiguration.severity == .error)
|
|
}
|
|
|
|
@Test
|
|
func overriddenSuperCallConfigurationFromDictionary() {
|
|
var configuration = OverriddenSuperCallConfiguration()
|
|
#expect(configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
|
|
|
|
let conf1 = ["severity": "error", "excluded": "viewWillAppear(_:)"]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: conf1)
|
|
}
|
|
#expect(configuration.severityConfiguration.severity == .error)
|
|
#expect(!configuration.resolvedMethodNames.contains("*"))
|
|
#expect(!configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
|
|
#expect(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)"))
|
|
|
|
let conf2 = [
|
|
"severity": "error",
|
|
"excluded": "viewWillAppear(_:)",
|
|
"included": ["*", "testMethod1()", "testMethod2(_:)"],
|
|
] as [String: any Sendable]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: conf2)
|
|
}
|
|
#expect(configuration.severityConfiguration.severity == .error)
|
|
#expect(!configuration.resolvedMethodNames.contains("*"))
|
|
#expect(!configuration.resolvedMethodNames.contains("viewWillAppear(_:)"))
|
|
#expect(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)"))
|
|
#expect(configuration.resolvedMethodNames.contains("testMethod1()"))
|
|
#expect(configuration.resolvedMethodNames.contains("testMethod2(_:)"))
|
|
|
|
let conf3 = [
|
|
"severity": "warning",
|
|
"excluded": "*",
|
|
"included": ["testMethod1()", "testMethod2(_:)"],
|
|
] as [String: any Sendable]
|
|
#expect(throws: Never.self) {
|
|
try configuration.apply(configuration: conf3)
|
|
}
|
|
#expect(configuration.severityConfiguration.severity == .warning)
|
|
#expect(configuration.resolvedMethodNames.count == 2)
|
|
#expect(!configuration.resolvedMethodNames.contains("*"))
|
|
#expect(configuration.resolvedMethodNames.contains("testMethod1()"))
|
|
#expect(configuration.resolvedMethodNames.contains("testMethod2(_:)"))
|
|
}
|
|
|
|
@Test
|
|
func modifierOrderConfigurationFromDictionary() throws {
|
|
var configuration = ModifierOrderConfiguration()
|
|
let config: [String: Any] = [
|
|
"severity": "warning",
|
|
"preferred_modifier_order": [
|
|
"override",
|
|
"acl",
|
|
"setterACL",
|
|
"owned",
|
|
"mutators",
|
|
"final",
|
|
"typeMethods",
|
|
"required",
|
|
"convenience",
|
|
"lazy",
|
|
"dynamic",
|
|
],
|
|
]
|
|
|
|
try configuration.apply(configuration: config)
|
|
let expected: [SwiftDeclarationAttributeKind.ModifierGroup] = [
|
|
.override,
|
|
.acl,
|
|
.setterACL,
|
|
.owned,
|
|
.mutators,
|
|
.final,
|
|
.typeMethods,
|
|
.required,
|
|
.convenience,
|
|
.lazy,
|
|
.dynamic,
|
|
]
|
|
#expect(configuration.severityConfiguration.severity == .warning)
|
|
#expect(configuration.preferredModifierOrder == expected)
|
|
}
|
|
|
|
@Test
|
|
func modifierOrderConfigurationThrowsOnUnrecognizedModifierGroup() {
|
|
var configuration = ModifierOrderConfiguration()
|
|
let config =
|
|
["severity": "warning", "preferred_modifier_order": ["specialize"]]
|
|
as [String: any Sendable]
|
|
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: ModifierOrderRule.identifier)) {
|
|
try configuration.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func modifierOrderConfigurationThrowsOnNonModifiableGroup() {
|
|
var configuration = ModifierOrderConfiguration()
|
|
let config = ["severity": "warning", "preferred_modifier_order": ["atPrefixed"]] as [String: any Sendable]
|
|
#expect(throws: Issue.invalidConfiguration(ruleID: ModifierOrderRule.identifier)) {
|
|
try configuration.apply(configuration: config)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func unusedParameterConfigurationFromDictionary() throws {
|
|
var configuration = UnusedParameterConfiguration()
|
|
try configuration.apply(configuration: ["severity": "error", "allow_underscore_prefixed_names": true])
|
|
#expect(configuration.severity == .error)
|
|
#expect(configuration.allowUnderscorePrefixedNames)
|
|
}
|
|
|
|
@Test
|
|
func computedAccessorsOrderRuleConfiguration() throws {
|
|
var configuration = ComputedAccessorsOrderConfiguration()
|
|
let config = ["severity": "error", "order": "set_get"]
|
|
try configuration.apply(configuration: config)
|
|
#expect(configuration.severityConfiguration.severity == .error)
|
|
#expect(configuration.order == .setGet)
|
|
#expect(
|
|
RuleConfigurationDescription.from(configuration: configuration).oneLiner()
|
|
== "severity: error; order: set_get")
|
|
}
|
|
}
|