Skip to content

Support relative paths in config file search - #6920

Open
tomotakatakahashi wants to merge 1 commit into
realm:mainfrom
tomotakatakahashi:SwiftLint2
Open

tomotakatakahashi wants to merge 1 commit into
realm:mainfrom
tomotakatakahashi:SwiftLint2

Conversation

@tomotakatakahashi

@tomotakatakahashi tomotakatakahashi commented Sep 20, 2026 •

Copy link
Copy Markdown

Summary

This PR fixes a bug where relative paths are not resolved when configuration files are searched.

When a file is passed as a relative path (e.g. swiftlint lint Sources/App.swift), the nested configuration search does not recognize that it has reached the root directory, so it keeps walking up the file tree and merges .swiftlint.yml files from directories outside the project.

Context

According to Claude Code, another PR of mine ( #6825 ) would worsen this bug (although I haven't confirmed whether it is true or not). Maybe I should fix this bug before the other PR is merged.

Test

  • The added test fails if the Source changes are not applied.
  • Running the swiftlint scheme with lint --no-cache Sources/Core/Service.swift arguments and /Users/tomotaka/projects/SwiftLint2/Tests/IntegrationTests/Resources/_2_parent_child_different_dirs/project working directory:
    • Before this PR: Found 2 violations. (file_name and no_empty_block)
      • This repo's .swiftlint.yml (opt_in_rules: all) is used instead of the working dir's .swiftlint.yml.
    • After this PR: Found 0 violations.

Comment

  • I wasn't sure which URL API to use for the comparison. standardizedFileURL, path(percentEncoded:) and absoluteString all resolve the relative URL:
import Playgrounds

#Playground {
    let baseURL = URL(string: "file:///Users/tomotaka/projects/SwiftLint2/Tests/IntegrationTests/Resources/_9_symlinked_paths/Real/")!
    let relURL = URL(fileURLWithPath: "../LinkToFile.swift", relativeTo: baseURL)

    // "/Users/tomotaka/projects/SwiftLint2/Tests/IntegrationTests/Resources/_9_symlinked_paths/LinkToFile.swift"
    relURL.path(percentEncoded: false)
    // file:///Users/tomotaka/projects/SwiftLint2/Tests/IntegrationTests/Resources/_9_symlinked_paths/LinkToFile.swift
    relURL.standardizedFileURL
    // "file:///Users/tomotaka/projects/SwiftLint2/Tests/IntegrationTests/Resources/_9_symlinked_paths/LinkToFile.swift"
    relURL.absoluteString
}
  • I considered adding this test case to MultipleConfigurationsTests, but this test case does not necessarily catch a regression. If the Source changes are reverted, the test suite becomes flaky (due to the caching mechanism of Configuration according to Claude Code).
    @Test(.workingDirectory(Constants.Dir.level0))
    func level0WithRelativeFilePath() {
        let relativePath = URL(
            filePath: Constants.Swift._0.lastPathComponent,
            relativeTo: Constants.Swift._0.deletingLastPathComponent()
        )
        #expect(
            Constants.Config._0.configuration(for: SwiftLintFile(path: relativePath)!)
                == Constants.Config._0
        )
    }

@SwiftLintBot

SwiftLintBot commented Sep 20, 2026 •

Copy link
Copy Markdown
20 Messages
📖 Building this branch resulted in the same binary size as when built on main.
📖 Linting Aerial with this PR took 0.68 s vs 0.68 s on main (0% slower).
📖 Linting Alamofire with this PR took 0.98 s vs 0.98 s on main (0% slower).
📖 Linting Brave with this PR took 5.53 s vs 5.51 s on main (0% slower).
📖 Linting Brigade with this PR took 18.34 s vs 18.19 s on main (0% slower).
📖 Linting DuckDuckGo with this PR took 31.16 s vs 31.04 s on main (0% slower).
📖 Linting Firefox with this PR took 11.75 s vs 11.75 s on main (0% slower).
📖 Linting Kickstarter with this PR took 7.41 s vs 7.45 s on main (0% faster).
📖 Linting Moya with this PR took 0.38 s vs 0.39 s on main (2% faster).
📖 Linting NetNewsWire with this PR took 2.59 s vs 2.59 s on main (0% slower).
📖 Linting Nimble with this PR took 0.56 s vs 0.57 s on main (1% faster).
📖 Linting PocketCasts with this PR took 7.45 s vs 7.42 s on main (0% slower).
📖 Linting Quick with this PR took 0.37 s vs 0.36 s on main (2% slower).
📖 Linting Realm with this PR took 2.98 s vs 2.98 s on main (0% slower).
📖 Linting Sourcery with this PR took 1.63 s vs 1.6 s on main (1% slower).
📖 Linting Swift with this PR took 4.58 s vs 4.57 s on main (0% slower).
📖 Linting SwiftLintPerformanceTests with this PR took 0.18 s vs 0.18 s on main (0% slower).
📖 Linting VLC with this PR took 1.41 s vs 1.4 s on main (0% slower).
📖 Linting Wire with this PR took 16.56 s vs 16.52 s on main (0% slower).
📖 Linting WordPress with this PR took 10.66 s vs 10.6 s on main (0% slower).

Generated by 🚫 Danger

@tomotakatakahashi
tomotakatakahashi force-pushed the SwiftLint2 branch 2 times, most recently from 501fdc4 to 7fb0d46 Compare September 22, 2026 00:40
@tomotakatakahashi
tomotakatakahashi marked this pull request as ready for review September 22, 2026 00:55

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants