mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-06-16 10:34:34 +00:00
646 lines
16 KiB
Swift
646 lines
16 KiB
Swift
//
|
|
// SortImportsTests.swift
|
|
// SwiftFormatTests
|
|
//
|
|
// Created by Nick Lockwood on 8/13/23.
|
|
// Copyright © 2024 Nick Lockwood. All rights reserved.
|
|
//
|
|
|
|
import XCTest
|
|
@testable import SwiftFormat
|
|
|
|
final class SortImportsTests: XCTestCase {
|
|
func testSortImportsSimpleCase() {
|
|
let input = """
|
|
import Foo
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testDefaultGroupingBehaviorIsAccessControlThenAlpha() {
|
|
let input = """
|
|
@testable import Foo
|
|
import Zed
|
|
public import Alpha
|
|
import Bar
|
|
public import Beta
|
|
@testable import Ace
|
|
"""
|
|
let output = """
|
|
public import Alpha
|
|
public import Beta
|
|
@testable import Ace
|
|
import Bar
|
|
@testable import Foo
|
|
import Zed
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testSortImportsKeepsPreviousCommentWithImport() {
|
|
let input = """
|
|
import Foo
|
|
// important comment
|
|
// (very important)
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
// important comment
|
|
// (very important)
|
|
import Bar
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testSortImportsKeepsPreviousCommentWithImport2() {
|
|
let input = """
|
|
// important comment
|
|
// (very important)
|
|
import Foo
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
// important comment
|
|
// (very important)
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testSortImportsDoesntMoveHeaderComment() {
|
|
let input = """
|
|
// header comment
|
|
|
|
import Foo
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
// header comment
|
|
|
|
import Bar
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testSortImportsDoesntMoveHeaderCommentFollowedByImportComment() {
|
|
let input = """
|
|
// header comment
|
|
|
|
// important comment
|
|
import Foo
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
// header comment
|
|
|
|
import Bar
|
|
// important comment
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testSortImportsOnSameLine() {
|
|
let input = """
|
|
import Foo; import Bar
|
|
import Baz
|
|
"""
|
|
let output = """
|
|
import Baz
|
|
import Foo; import Bar
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testSortImportsWithSemicolonAndCommentOnSameLine() {
|
|
let input = """
|
|
import Foo; // foobar
|
|
import Bar
|
|
import Baz
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
import Baz
|
|
import Foo; // foobar
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports, exclude: [.semicolons])
|
|
}
|
|
|
|
func testSortImportEnum() {
|
|
let input = """
|
|
import enum Foo.baz
|
|
import Foo.bar
|
|
"""
|
|
let output = """
|
|
import Foo.bar
|
|
import enum Foo.baz
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testSortImportFunc() {
|
|
let input = """
|
|
import func Foo.baz
|
|
import Foo.bar
|
|
"""
|
|
let output = """
|
|
import Foo.bar
|
|
import func Foo.baz
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testAlreadySortImportsDoesNothing() {
|
|
let input = """
|
|
import Bar
|
|
import Foo
|
|
"""
|
|
testFormatting(for: input, rule: .sortImports)
|
|
}
|
|
|
|
func testPreprocessorSortImports() {
|
|
let input = """
|
|
#if os(iOS)
|
|
import Foo2
|
|
import Bar2
|
|
#else
|
|
import Foo1
|
|
import Bar1
|
|
#endif
|
|
import Foo3
|
|
import Bar3
|
|
"""
|
|
let output = """
|
|
#if os(iOS)
|
|
import Bar2
|
|
import Foo2
|
|
#else
|
|
import Bar1
|
|
import Foo1
|
|
#endif
|
|
import Bar3
|
|
import Foo3
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testTestableSortImports() {
|
|
let input = """
|
|
@testable import Foo3
|
|
import Bar3
|
|
"""
|
|
let output = """
|
|
import Bar3
|
|
@testable import Foo3
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testLengthSortImports() {
|
|
let input = """
|
|
import Foo
|
|
import Module
|
|
import Bar3
|
|
"""
|
|
let output = """
|
|
import Foo
|
|
import Bar3
|
|
import Module
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testTestableImportsWithTestableOnPreviousLine() {
|
|
let input = """
|
|
@testable
|
|
import Foo3
|
|
import Bar3
|
|
"""
|
|
let output = """
|
|
import Bar3
|
|
@testable
|
|
import Foo3
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testTestableImportsWithGroupingTestableBottom() {
|
|
let input = """
|
|
@testable import Bar
|
|
import Foo
|
|
@testable import UIKit
|
|
"""
|
|
let output = """
|
|
import Foo
|
|
@testable import Bar
|
|
@testable import UIKit
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .testableLast])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testTestableImportsWithGroupingTestableTop() {
|
|
let input = """
|
|
@testable import Bar
|
|
import Foo
|
|
@testable import UIKit
|
|
"""
|
|
let output = """
|
|
@testable import Bar
|
|
@testable import UIKit
|
|
import Foo
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .testableFirst])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testCaseInsensitiveSortImports() {
|
|
let input = """
|
|
import Zlib
|
|
import lib
|
|
"""
|
|
let output = """
|
|
import lib
|
|
import Zlib
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testCaseInsensitiveCaseDifferingSortImports() {
|
|
let input = """
|
|
import c
|
|
import B
|
|
import A.a
|
|
import A.A
|
|
"""
|
|
let output = """
|
|
import A.A
|
|
import A.a
|
|
import B
|
|
import c
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testNoDeleteCodeBetweenImports() {
|
|
let input = """
|
|
import Foo
|
|
func bar() {}
|
|
import Bar
|
|
"""
|
|
testFormatting(for: input, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testNoDeleteCodeBetweenImports2() {
|
|
let input = """
|
|
import Foo
|
|
import Bar
|
|
foo = bar
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
import Foo
|
|
foo = bar
|
|
import Bar
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testNoDeleteCodeBetweenImports3() {
|
|
let input = """
|
|
import Z
|
|
|
|
// one
|
|
|
|
#if FLAG
|
|
print("hi")
|
|
#endif
|
|
|
|
import A
|
|
"""
|
|
testFormatting(for: input, rule: .sortImports)
|
|
}
|
|
|
|
func testSortContiguousImports() {
|
|
let input = """
|
|
import Foo
|
|
import Bar
|
|
func bar() {}
|
|
import Quux
|
|
import Baz
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
import Foo
|
|
func bar() {}
|
|
import Baz
|
|
import Quux
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports,
|
|
exclude: [.blankLineAfterImports])
|
|
}
|
|
|
|
func testNoMangleImportsPrecededByComment() {
|
|
let input = """
|
|
// evil comment
|
|
|
|
#if canImport(Foundation)
|
|
import Foundation
|
|
#if canImport(UIKit) && canImport(AVFoundation)
|
|
import UIKit
|
|
import AVFoundation
|
|
#endif
|
|
#endif
|
|
"""
|
|
let output = """
|
|
// evil comment
|
|
|
|
#if canImport(Foundation)
|
|
import Foundation
|
|
#if canImport(UIKit) && canImport(AVFoundation)
|
|
import AVFoundation
|
|
import UIKit
|
|
#endif
|
|
#endif
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testNoMangleFileHeaderNotFollowedByLinebreak() {
|
|
let input = """
|
|
//
|
|
// Code.swift
|
|
// Module
|
|
//
|
|
// Created by Someone on 4/30/20.
|
|
//
|
|
import AModuleUI
|
|
import AModule
|
|
import AModuleHelper
|
|
import SomeOtherModule
|
|
"""
|
|
let output = """
|
|
//
|
|
// Code.swift
|
|
// Module
|
|
//
|
|
// Created by Someone on 4/30/20.
|
|
//
|
|
import AModule
|
|
import AModuleHelper
|
|
import AModuleUI
|
|
import SomeOtherModule
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
func testNoMangleConditionalImportsFollowedByPrivateDeclaration() {
|
|
let input = """
|
|
#if canImport(UIKit)
|
|
import UIKit
|
|
private struct Foo {}
|
|
#elseif canImport(AppKit)
|
|
import AppKit
|
|
private struct Foo {}
|
|
#endif
|
|
"""
|
|
let options = FormatOptions(swiftVersion: "6.1")
|
|
testFormatting(for: input, rule: .sortImports, options: options, exclude: [.blankLineAfterImports, .indent])
|
|
}
|
|
|
|
func testNoMoveSwiftToolsVersionLine() {
|
|
let input = """
|
|
// swift-tools-version: 6.2
|
|
import PackageDescription
|
|
import CompilerPluginSupport
|
|
"""
|
|
let output = """
|
|
// swift-tools-version: 6.2
|
|
import CompilerPluginSupport
|
|
import PackageDescription
|
|
"""
|
|
testFormatting(for: input, output, rule: .sortImports)
|
|
}
|
|
|
|
// MARK: - Access control sorting
|
|
|
|
func testAccessControlSortImports() {
|
|
let input = """
|
|
import Foo
|
|
private import Bar
|
|
public import Baz
|
|
"""
|
|
let output = """
|
|
public import Baz
|
|
private import Bar
|
|
import Foo
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testAccessControlSortAlphaWithinLevel() {
|
|
let input = """
|
|
public import Zebra
|
|
public import Alpha
|
|
public import Middle
|
|
"""
|
|
let output = """
|
|
public import Alpha
|
|
public import Middle
|
|
public import Zebra
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testAccessControlSortLengthWithinLevel() {
|
|
let input = """
|
|
public import Zebra
|
|
public import Al
|
|
public import Middle
|
|
"""
|
|
let output = """
|
|
public import Al
|
|
public import Zebra
|
|
public import Middle
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .accessControl])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testAccessControlSortLengthWithMultipleACLs() {
|
|
let input = """
|
|
private import LongPrivate
|
|
public import Baz
|
|
private import Al
|
|
public import LongPublic
|
|
import Foo
|
|
"""
|
|
let output = """
|
|
public import Baz
|
|
public import LongPublic
|
|
private import Al
|
|
private import LongPrivate
|
|
import Foo
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .accessControl])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testAccessControlWithTestableFirst() {
|
|
let input = """
|
|
import Foo
|
|
@testable import Bar
|
|
public import Baz
|
|
"""
|
|
let output = """
|
|
@testable import Bar
|
|
public import Baz
|
|
import Foo
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl, .testableFirst])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testAccessControlWithTestableLast() {
|
|
let input = """
|
|
public import Baz
|
|
@testable import Bar
|
|
import Foo
|
|
"""
|
|
let output = """
|
|
public import Baz
|
|
import Foo
|
|
@testable import Bar
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl, .testableLast])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testUnlabeledImportsSortLast() {
|
|
let input = """
|
|
import Foo
|
|
public import Bar
|
|
internal import Baz
|
|
import Qux
|
|
"""
|
|
let output = """
|
|
public import Bar
|
|
internal import Baz
|
|
import Foo
|
|
import Qux
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testTestableImportsSortedByACLAndAlpha() {
|
|
let input = """
|
|
@testable import DModule
|
|
@testable public import CModule
|
|
@testable import AModule
|
|
@testable public import BModule
|
|
import ZModule
|
|
public import UModule
|
|
import YModule
|
|
public import TModule
|
|
"""
|
|
let output = """
|
|
public import TModule
|
|
public import UModule
|
|
import YModule
|
|
import ZModule
|
|
@testable public import BModule
|
|
@testable public import CModule
|
|
@testable import AModule
|
|
@testable import DModule
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.alpha, .accessControl, .testableLast])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
// MARK: - Length + testable combinations
|
|
|
|
func testLengthSortWithTestableTop() {
|
|
let input = """
|
|
import Foo
|
|
@testable import LongModule
|
|
import Ba
|
|
@testable import Az
|
|
"""
|
|
let output = """
|
|
@testable import Az
|
|
@testable import LongModule
|
|
import Ba
|
|
import Foo
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .testableFirst])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testLengthSortWithTestableBottom() {
|
|
let input = """
|
|
@testable import LongModule
|
|
import Foo
|
|
import Ba
|
|
@testable import Az
|
|
"""
|
|
let output = """
|
|
import Ba
|
|
import Foo
|
|
@testable import Az
|
|
@testable import LongModule
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .testableLast])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testLengthThenAlphaSortImports() {
|
|
let input = """
|
|
import Module
|
|
import Foo
|
|
import Bar
|
|
import Ab
|
|
"""
|
|
let output = """
|
|
import Ab
|
|
import Bar
|
|
import Foo
|
|
import Module
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .alpha])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
|
|
func testLengthThenAlphaSortImportsWithSameLength() {
|
|
let input = """
|
|
import Zed
|
|
import Foo
|
|
import Bar
|
|
"""
|
|
let output = """
|
|
import Bar
|
|
import Foo
|
|
import Zed
|
|
"""
|
|
let options = FormatOptions(importGrouping: [.length, .alpha])
|
|
testFormatting(for: input, output, rule: .sortImports, options: options)
|
|
}
|
|
}
|