Statische Swift-6-Pruefung ohne Swift-Compiler (Rust-Port von ipad-notizen-app/native/lint-swift.py)
Find a file
Hermes 01cc0f3c22 feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler)
- 11 Regeln aus den echten Compiler-Meldungen, identische Meldungen und Exit-Codes
- Paritätstest vergleicht stdout und Exit gegen das Python-Original auf demselben Fixture
- Ausgabe auf den echten ipad-notizen-app-Quellen byte-identisch
2026-11-05 16:37:19 +01:00
src feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00
tests feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00
.gitignore feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00
Cargo.lock feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00
Cargo.toml feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00
README.md feat: Rust-Port von lint-swift.py (Swift-6-Prüfung ohne Compiler) 2026-11-05 16:37:19 +01:00

swift6-lint-rs

Rust-Port von native/lint-swift.py aus ipad-notizen-app: statische Prüfung von Swift-Quellen auf Fehler, die Swift 6 ablehnt — für Rechner ohne Swift-Compiler.

Warum

Auf diesem Host gibt es kein Xcode, aber die Fehler tauchten in Swift Playgrounds auf. Das Python-Skript hat die Regeln aus echten Compiler-Meldungen zusammengestellt; hier laufen dieselben Regeln als Binary, damit sie in einem Gate ohne Interpreter starten.

Bauen und benutzen

cargo build --release                    # target/release/swift6-lint
cargo test                               # 4 Tests, inkl. Parität gegen das Original

./target/release/swift6-lint             # prüft ./Sources neben dem Binary (wie das Original)
./target/release/swift6-lint path/Sources

Exit 0 = keine Fehler, Exit 1 = mindestens ein Fehler. Die Hinweise (Warnungen) ändern den Exit-Code nicht — genau wie im Original.

Regeln

Regel Warum
@MainActor an perform/entities/suggestedEntities/resolve, wenn der Rumpf NoteStore.shared oder @MainActor anfasst AppIntent-Methoden laufen nicht auf dem Main Actor
let-Bindungen, die in keiner Datei benutzt werden „was never used"-Warnung, dateiübergreifend gesucht
AppShortcut ohne shortTitle / systemImageName bindet an die iOS-17-deprecatete Überladung
Interpolation in AppShortcut-phrases Phrases müssen Compile-Time-Konstanten sein
PKToolPicker.shared deprecated seit iOS 14
onChange(of:) mit parameterloser Closure veraltete Signatur, braucht { _, neu in }
settings.<member> ohne Member in struct AppSettings genau der Fall, den die lokalen Gates übersahen
Timer.scheduledTimer in einer @MainActor-Klasse (Hinweis) Closure erbt die Isolation nicht
onChange() direkt in updateUIView ohne Task (Hinweis) kann State während des View-Updates ändern
Closure-Feld (let cb: (…) -> Void) ohne @MainActor (Hinweis) Swift 6 verlangt die Annotation

Parität

cargo test
  • output_is_byte_identical_to_the_python_original — kopiert das Fixture in einen Scratch-Baum, legt lint-swift.py daneben (es sucht Sources/ neben sich) und vergleicht stdout und Exit-Code beider Implementierungen byteweise. Fehlt python3 oder das Original, wird der Test übersprungen statt rot.
  • the_fixture_still_trips_every_rule — das Fixture muss jede Regel auslösen, sonst prüft der Paritätstest zwei Implementierungen, die beide nichts finden.
  • a_clean_tree_passes — sauberer Baum → Keine Swift-6-Fehler gefunden., Exit 0.

Zusätzlich manuell gegen die echten Quellen geprüft:

$ diff <(python3 lint-swift.py) <(swift6-lint Sources)   → identisch

Abweichungen

  • Sources/-Auflösung: das Original nimmt immer <script_dir>/Sources. Hier ist das der Default, ein Pfad-Argument hat Vorrang — sonst müsste man das Binary ins Repo kopieren.
  • Regex-Bau einmal statt pro Zeile (OnceLock): reine Laufzeitfrage, die Meldungen sind identisch, was der Paritätstest beweist.
  • Die Prüfung auf phrases-Interpolation sieht — wie das Original — nur Folgezeilen einer phrases:-Zeile. Eine einzeilige phrases: [...] wird von beiden nicht geprüft; das Fixture nutzt deshalb die mehrzeilige Form.

Herkunft

Portiert am 2026-11-05 aus ipad-notizen-app/native/lint-swift.py (180 Zeilen Python). Das Original bleibt liegen; der Aufruf im Repo kann auf das Binary umgestellt werden.