Skip to content

FR: hoist file-scope imports to the top of the file #2670

Description

@cursor

FR: hoist file-scope imports to the top of the file

sortImports only reorders a contiguous import run. A file-scope import after other declarations is left where it is, and --lint does not report it.

Swift allows this (imports are file-scoped either way):

import Testing

struct Example {}

@testable import MyModule

That compiles and is easy to miss. I could not find an existing SwiftFormat issue for this (nearby requests are grouping inside an import block: #905, #323).

Prior art: Apple swift-format

Apple’s swift-format already does this. OrderedImports:

Lint: If an import appears anywhere other than the beginning of the file it resides in, not lexicographically ordered, or (optionally) not in the appropriate import group, a lint error is raised.

Format: Imports will be reordered and (optionally) grouped at the top of the file.

Google’s Swift style guide says the same: import statements are the first non-comment tokens in a source file.

I am filing a matching SwiftLint rule request.

Suggested behavior

A new disabled-by-default rule (e.g. hoistImports, next to hoistAwait / hoistTry), or an option on sortImports, that:

  1. Treats every file-scope import as belonging to the leading import section (after an optional file header / comments).
  2. On format: moves stray imports up into that section (then existing sortImports / --import-grouping can order them).
  3. On --lint: fails if any file-scope import sits after a non-import declaration.

Leave #if import groups that are already in the header alone. I would not hoist an import out of a later #if without discussion.

Examples

Would change / fail lint:

  import Foundation
+ import UIKit

  struct Foo {}
-
- import UIKit
  import Testing
+ @testable import MyModule

  struct FooTests {}
-
- @testable import MyModule

Would not change:

// Copyright header.

import Foundation
import UIKit

struct Foo {}

Disabled by default so enabling it is an opt-in style change, consistent with new-rule versioning.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

fixed in developbug/feature resolved in the develop branch

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions