Skip to content

About

A catalog of per-rule-activatable SwiftSyntax lint rule packs for swift-linter.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

246 Commits

Folders and files

swift-linter-rules

Use this package when you want ready-made lint rules for Swift packages, to run with swift-linter or another runner built on swift-lint. Start from Lint.Rule.Bundle.universal to enable the whole set, or depend on one Linter Rule product and enable its rules by ID. To write rules of your own, use swift-lint. To run rules over a package, use swift-linter.

Laws

  • Rules read syntax only, with no type checking, and most see one file at a time. A conformance, class or associated type declared in another file is not seen. The rules "conflicting dependency url" and "undeclared module import" are the exceptions: they read other files of the package on disk.
  • Lint.Rule.Bundle.universal enables every rule in this package except "comment". Some rules are enabled at a higher severity than their own default.
  • "blocking call in async" skips files whose path starts with Tests/. It counts a call as async when it sits in an async function, initializer or accessor, in a closure marked async, in a closure passed to Task or Task.detached, or in a closure that contains an await. Any other closure is synchronous, even inside an async function, so work handed to a thread pool in a plain closure is not flagged. An awaited call is never flagged, and @concurrent does not exempt a function.
  • "mock factory zero collision" applies only to files whose path contains /Tests/.
  • "extension noncopyable constraint" skips a file whose path contains " where ", an extension on a type written without generic arguments or a where clause, an extension on one of a fixed list of standard library types such as Array and Optional, an extension that uses a parameter pack, and one that requires Copyable explicitly.
  • "sendable struct with class member" knows a type is a class only when the class is declared in the same file or is one of a few well-known system classes. Computed and observed properties are ignored.
  • "unchecked sendable noncopyable" flags every noncopyable struct that conforms to @unchecked Sendable, without looking at its stored properties.
  • "usable from inline internal import" considers only imports written with internal. It flags such an import when any identifier inside a @usableFromInline declaration in the file is the module's name.
  • "redundant refinement" compares the last component of each type name against a fixed table of standard library refinements, so a qualified name matches by its leaf.
  • "conflicting dependency url" runs only on a Package.swift. It reads the Package.resolved beside it, in format 1, 2 or 3, and the manifests under .build/checkouts, whose directories are matched case-insensitively. Two locations are the same when they agree after lowercasing and dropping the scheme, the user, .git and trailing slashes, with an scp-style host:path read as host/path. A checkout's spelling counts only when a target one of its products reaches uses it with the traits the graph enables. Without a Package.resolved, or for an unpinned identity, nothing is reported. A conflict found in a checkout is reported at the root manifest's own spelling of that package.
  • "undeclared module import" runs only on the package manifest. It checks imports in Sources and Tests, skipping nested packages, and only module names that contain an underscore and don't start with one. Each module is reported once, at the Package call.
  • "comment" flags every comment, documentation comments included. It admits only // swift-linter: directives, the // swift-tools-version: line, and one // REASON: line directly under a disable directive.
  • "malformed suppression directive" accepts exactly // swift-linter:disable:next or // swift-linter:disable:line followed by a rule ID. Any other line comment that starts with swift-linter: is flagged. Documentation comments are not scanned.
  • Lint.Scope.Index.of(_:) reads every Swift file under the package root once per process and caches the result by root. Changes on disk after that are not seen. Folders such as .build, .git and checkouts, and .docc catalogs, are skipped.
  • Lint.License.Header.recognize(in:) looks only at comment blocks before the first line of code. A block counts as a license header when it mentions both "copyright" and "licensed under". A block that mentions a license without both is refused, and so is a license marker in a comment after the code starts.

About

A catalog of per-rule-activatable SwiftSyntax lint rule packs for swift-linter.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages