realm / realm/SwiftLint

Baseline matching fails for every violation under /private when excluded: is non-empty (regression sibling of #6782)

Open
#6,909 0 comments 0 reactions 0 assignees View on GitHub

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:

  1. 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
  2. .swiftlint.yml has a non-empty excluded: 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 /private via the standard /tmp -> /private/tmp, /var/folders ->
    /private/var/folders symlinks

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.