Baseline matching fails for every violation under /private when excluded: is non-empty (regression sibling of #6782)
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 19.7k
- Forks
- 2.3k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 11
Description
New Issue Checklist
- Updated SwiftLint to the latest version (0.65.1)
- I searched for existing GitHub issues
Describe the bug
--baseline silently fails to filter any violation - even one written and re-read in the same
directory, same session - whenever both of these are true:
- the project's real path is under
/private(i.e. under macOS's/tmp,/var,/var/folders
symlinks -mktemp -d, CI workspaces,git worktree add /tmp/..., etc), and .swiftlint.ymlhas a non-emptyexcluded:list (the exact value doesn't matter - even a
single entry that matches nothing is enough).
Under /Users/... the identical config and files match correctly. Under /private, removing
excluded: also makes it match correctly. It's the combination that breaks it.
This looks related to #6782 (fixed in 0.65.1 for excluded: matching itself): a non-empty
excluded: list routes file discovery through FileManager.collectFiles/Excluder
(Source/SwiftLintFramework/Extensions/FileManager+SwiftLint.swift) instead of the "no exclusion"
fast path in the same file. That's the same code fork #6782 patched for the exclusion check itself,
but baseline matching downstream of it (Source/SwiftLintCore/Models/Baseline.swift) still breaks
for every violation in the linted file once that path is taken.
One additional data point that may narrow it further: with a violation on line 1 of the file, the
written baseline's text field for that violation comes out as an empty string (see repro
below) instead of the actual source line - so LineCache.text(at:)
(Source/SwiftLintCore/Models/Baseline.swift) may also be involved, though moving the violation to
a later line fixes the empty text but the baseline still fails to match, so that alone isn't the
whole story.
Complete output when running SwiftLint
Self-contained reproduction (macOS, paste into a terminal):
D=$(mktemp -d) # lands under /private/var/folders/...
cd "$D"
mkdir Sources
printf 'let value = Optional(1)!\n' > Sources/Foo.swift
cat > .swiftlint.yml <<'YML'
included:
- Sources
excluded:
- Ignored
opt_in_rules:
- force_unwrapping
YML
swiftlint lint --write-baseline .swiftlint.baseline --quiet >/dev/null
swiftlint lint --quiet --strict --baseline .swiftlint.baseline
echo "exit=$?"
Actual: the violation resurfaces immediately after being baselined, in the same directory:
.../Sources/Foo.swift:1:24: error: Force Unwrapping Violation: Force unwrapping should be avoided (force_unwrapping)
exit=2
Expected: exit=0, no output.
The written baseline's text for this one-line file is empty ("") instead of the source line:
[{"text": "", "violation": {"reason": "Force unwrapping should be avoided", "location": {"file": "Sources/Foo.swift", "line": 1, "character": 24}, "ruleIdentifier": "force_unwrapping", ...}}]
Two controls, changing one variable at a time from the repro above:
| Variant | Real path | excluded: |
Result |
|---|---|---|---|
| repro as written | /private/var/folders/... (mktemp -d) |
[Ignored] |
❌ fails (exit=2) |
remove excluded: entirely |
/private/var/folders/... |
(empty) | ✅ passes (exit=0) |
move repro to /Users/<me>/... |
/Users/... |
[Ignored] |
✅ passes (exit=0) |
Also reproduced on a much larger real-world project (thousands of violations, git worktree add --detach /tmp/wt HEAD of an unmodified main): every baselined violation in the whole project
resurfaces as new, 100% reproducible, byte-identical baseline file either side.
Environment
- SwiftLint version: 0.65.1
- Installation: Homebrew
- macOS, paths under
/privatevia the standard/tmp->/private/tmp,/var/folders->
/private/var/folderssymlinks
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with FileManager+SwiftLint.swift, especially FileManager.collectFiles and Excluder, then trace baseline handling in Source/SwiftLintCore/Models/Baseline.swift and LineCache.text(at:). Run the provided macOS reproduction under /private with a non-empty excluded list. Done means the written baseline retains the source text and filters the violation on the next lint run.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100