mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-06-16 10:34:34 +00:00
134 lines
6.2 KiB
Swift
134 lines
6.2 KiB
Swift
//
|
|
// XCTestCase+testFormatting.swift
|
|
// SwiftFormat
|
|
//
|
|
// Created by Nick Lockwood on 12/08/2016.
|
|
// Copyright 2016 Nick Lockwood
|
|
//
|
|
// Distributed under the permissive MIT license
|
|
// Get the latest version from here:
|
|
//
|
|
// https://github.com/nicklockwood/SwiftFormat
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
//
|
|
|
|
import XCTest
|
|
@testable import SwiftFormat
|
|
|
|
extension XCTestCase {
|
|
func testFormatting(for input: String, _ output: String? = nil, rule: FormatRule,
|
|
options: FormatOptions = .default, exclude: [FormatRule] = [],
|
|
file: StaticString = #file, line: UInt = #line)
|
|
{
|
|
testFormatting(for: input, output.map { [$0] } ?? [], rules: [rule],
|
|
options: options, exclude: exclude, file: file, line: line)
|
|
}
|
|
|
|
func testFormatting(for input: String, _ outputs: [String] = [], rules: [FormatRule],
|
|
options: FormatOptions = .default, exclude: [FormatRule] = [],
|
|
file: StaticString = #file, line: UInt = #line)
|
|
{
|
|
// Always make sure the rule registry is up-to-date before running the tests
|
|
do {
|
|
try FormatRules.generateRuleRegistryIfNecessary()
|
|
} catch {
|
|
XCTFail("Encountered error generating rule registry: \(error.localizedDescription)", file: file, line: line)
|
|
}
|
|
|
|
var options = options
|
|
if options.timeout == FormatOptions.default.timeout {
|
|
// Make breakpoint debugging easier by increasing timeout
|
|
options.timeout = 120
|
|
}
|
|
// The `name` property on individual rules is not populated until the first call into `rulesByName`,
|
|
// so we have to make sure to trigger this before checking the names of the given rules.
|
|
if rules.contains(where: \.name.isEmpty) {
|
|
_ = FormatRules.all
|
|
}
|
|
|
|
// Check swift versions updated
|
|
if options.swiftVersion != .undefined {
|
|
let maxVersion = Version(rawValue: swiftVersions.last!)!
|
|
XCTAssert(options.swiftVersion <= maxVersion,
|
|
"Swift version '\(options.swiftVersion)' not found in swiftVersions array",
|
|
file: file, line: line)
|
|
}
|
|
|
|
precondition(input != outputs.first || input != outputs.last, "Redundant output parameter")
|
|
precondition((0 ... 2).contains(outputs.count), "Only 0, 1 or 2 output parameters permitted")
|
|
precondition(Set(exclude).intersection(rules).isEmpty, "Cannot exclude rule under test")
|
|
let output = outputs.first ?? input, output2 = outputs.last ?? input
|
|
let defaultExclusions = FormatRules.deprecated + [
|
|
.linebreakAtEndOfFile,
|
|
.organizeDeclarations,
|
|
.extensionAccessControl,
|
|
.markTypes,
|
|
.blockComments,
|
|
.unusedPrivateDeclarations,
|
|
.preferFinalClasses,
|
|
.preferExplicitFalse,
|
|
.wrapCaseBodies,
|
|
]
|
|
let exclude = exclude + defaultExclusions.filter { !rules.contains($0) }
|
|
let formatResult: (output: String, changes: [SwiftFormat.Formatter.Change])
|
|
do {
|
|
formatResult = try format(input, rules: rules, options: options)
|
|
} catch {
|
|
XCTFail("Failed to format input, threw error \(error)", file: file, line: line)
|
|
return
|
|
}
|
|
XCTAssertEqual(formatResult.output, output, file: file, line: line)
|
|
|
|
if input != output, formatResult.output == output {
|
|
XCTAssert(!formatResult.changes.isEmpty, """
|
|
Rules applied changes but unexpectedly produced no `Formatter.Change`s. \
|
|
This would result in no messages being printed when running with --lint. \
|
|
This can happen in cases where a rule only moves lines, but doesn't modify their contents. \
|
|
You can fix this by using `formatter.moveTokens`.
|
|
""", file: file, line: line)
|
|
}
|
|
|
|
XCTAssertEqual(try format(input, rules: FormatRules.all(except: exclude), options: options).output,
|
|
output2, file: file, line: line)
|
|
if input != output {
|
|
XCTAssertEqual(try format(output, rules: rules, options: options).output,
|
|
output, file: file, line: line)
|
|
if !input.hasPrefix("#!") {
|
|
for rule in rules {
|
|
let disabled = "// swiftformat:disable \(rule)\n\(input)"
|
|
XCTAssertEqual(try format(disabled, rules: [rule], options: options).output,
|
|
disabled, "Failed to disable \(rule) rule", file: file, line: line)
|
|
}
|
|
}
|
|
}
|
|
if input != output2, output != output2 {
|
|
XCTAssertEqual(try format(output2, rules: FormatRules.all(except: exclude), options: options).output,
|
|
output2, file: file, line: line)
|
|
}
|
|
|
|
#if os(macOS)
|
|
// These tests are flakey on Linux, and it's hard to debug
|
|
XCTAssertEqual(try lint(output, rules: rules, options: options), [], file: file, line: line)
|
|
XCTAssertEqual(try lint(output2, rules: FormatRules.all(except: exclude), options: options),
|
|
[], file: file, line: line)
|
|
#endif
|
|
}
|
|
}
|