Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ahoppen authored and macshome committed Dec 2, 2024
1 parent da2f133 commit 2e4e0a6
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 52 deletions.
14 changes: 0 additions & 14 deletions Sources/SwiftFormat/API/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -472,17 +472,3 @@ public struct NoAssignmentInExpressionsConfiguration: Codable, Equatable {

public init() {}
}

fileprivate extension URL {
var isRoot: Bool {
#if os(Windows)
// FIXME: We should call into Windows' native check to check if this path is a root once https://github.com/swiftlang/swift-foundation/issues/976 is fixed.
// https://github.com/swiftlang/swift-format/issues/844
return self.pathComponents.count <= 1
#else
// On Linux, we may end up with an string for the path due to https://github.com/swiftlang/swift-foundation/issues/980
// TODO: Remove the check for "" once https://github.com/swiftlang/swift-foundation/issues/980 is fixed.
return self.path == "/" || self.path == ""
#endif
}
}
3 changes: 2 additions & 1 deletion Sources/SwiftFormat/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ add_library(SwiftFormat
Rules/UseTripleSlashForDocumentationComments.swift
Rules/UseWhereClausesInForLoops.swift
Rules/ValidateDocumentationComments.swift
Utilities/FileIterator.swift)
Utilities/FileIterator.swift
Utilities/URL+isRoot.swift)
target_link_libraries(SwiftFormat PUBLIC
SwiftMarkdown::Markdown
SwiftSyntax::SwiftSyntax
Expand Down
26 changes: 5 additions & 21 deletions Sources/SwiftFormat/Utilities/FileIterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,12 @@ public struct FileIterator: Sequence, IteratorProtocol {
// if the user passes paths that are relative to the current working directory, they will
// be displayed as relative paths. Otherwise, they will still be displayed as absolute
// paths.
#if os(Windows)
let relativePath = path
#else
let relativePath =
path.hasPrefix(workingDirectory.path)
&& !URL(fileURLWithPath: FileManager.default.currentDirectoryPath).isRoot
? String(path.dropFirst(workingDirectory.path.count + 1))
: path
#endif
if !workingDirectory.isRoot, path.hasPrefix(workingDirectory.path) {
String(path.dropFirst(workingDirectory.path.count).drop(while: { $0 == "/" || $0 == #"\"# }))
} else {
path
}
output =
URL(fileURLWithPath: relativePath, isDirectory: false, relativeTo: workingDirectory)

Expand All @@ -183,16 +180,3 @@ private func fileType(at url: URL) -> FileAttributeType? {
// Linux.
return try? FileManager.default.attributesOfItem(atPath: url.path)[.type] as? FileAttributeType
}

fileprivate extension URL {
var isRoot: Bool {
guard isFileURL else { return false }
#if os(macOS)
return self.path == NSOpenStepRootDirectory()
#elseif os(Windows)
return self.path.withCString(encodedAs: UTF16.self, PathCchIsRoot)
#else
return self.path == "/"
#endif
}
}
27 changes: 27 additions & 0 deletions Sources/SwiftFormat/Utilities/URL+isRoot.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Foundation

extension URL {
@_spi(Testing) public var isRoot: Bool {
#if os(Windows)
// FIXME: We should call into Windows' native check to check if this path is a root once https://github.com/swiftlang/swift-foundation/issues/976 is fixed.
// https://github.com/swiftlang/swift-format/issues/844
return self.pathComponents.count <= 1
#else
// On Linux, we may end up with an string for the path due to https://github.com/swiftlang/swift-foundation/issues/980
// TODO: Remove the check for "" once https://github.com/swiftlang/swift-foundation/issues/980 is fixed.
return self.path == "/" || self.path == ""
#endif
}
}
53 changes: 37 additions & 16 deletions Tests/SwiftFormatTests/Utilities/FileIteratorTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
@_spi(Internal) import SwiftFormat
@_spi(Internal) @_spi(Testing) import SwiftFormat
import XCTest

extension URL {
/// Assuming this is a file URL, resolves all symlinks in the path.
///
/// - Note: We need this because `URL.resolvingSymlinksInPath()` not only resolves symlinks but also standardizes the
/// path by stripping away `private` prefixes. Since sourcekitd is not performing this standardization, using
/// `resolvingSymlinksInPath` can lead to slightly mismatched URLs between the sourcekit-lsp response and the test
/// assertion.
var realpath: URL {
#if canImport(Darwin)
return self.path.withCString { path in
guard let realpath = Darwin.realpath(path, nil) else {
return self
}
let result = URL(fileURLWithPath: String(cString: realpath))
free(realpath)
return result
}
#else
// Non-Darwin platforms don't have the `/private` stripping issue, so we can just use `self.resolvingSymlinksInPath`
// here.
return self.resolvingSymlinksInPath()
#endif
}
}

final class FileIteratorTests: XCTestCase {
private var tmpdir: URL!

Expand All @@ -10,7 +35,7 @@ final class FileIteratorTests: XCTestCase {
in: .userDomainMask,
appropriateFor: FileManager.default.temporaryDirectory,
create: true
)
).realpath

// Create a simple file tree used by the tests below.
try touch("project/real1.swift")
Expand Down Expand Up @@ -73,26 +98,22 @@ final class FileIteratorTests: XCTestCase {
}

func testDoesNotTrimFirstCharacterOfPathIfRunningInRoot() throws {
#if os(Windows) && compiler(<5.10)
try XCTSkipIf(true, "Testing issues with Foundation inserting extra slashes.")
#endif
// Make sure that we don't drop the begining of the path if we are running in root.
// Find the root of tmpdir. On Unix systems, this is always `/`. On Windows it is the drive.
var root = tmpdir!
while !root.isRoot {
root.deleteLastPathComponent()
}
// Make sure that we don't drop the beginning of the path if we are running in root.
// https://github.com/swiftlang/swift-format/issues/862
FileManager.default.changeCurrentDirectoryPath("/")
let seen = allFilesSeen(iteratingOver: [tmpdir], followSymlinks: false)
XCTAssertEqual(seen.count, 2)
XCTAssertTrue(seen.contains { $0.path.hasPrefix("/") })
XCTAssertTrue(seen.contains { $0.path.hasPrefix("/") })
let seen = allFilesSeen(iteratingOver: [tmpdir], followSymlinks: false, workingDirectory: root)
XCTAssertTrue(seen.allSatisfy { $0.relativePath.hasPrefix(root.path) }, "\(seen) does not contain root directory")
}

func testShowsRelativePaths() throws {
// Make sure that we still show the relative path if using them.
// https://github.com/swiftlang/swift-format/issues/862
FileManager.default.changeCurrentDirectoryPath(tmpdir.path)
let seen = allFilesSeen(iteratingOver: [URL(fileURLWithPath: ".")], followSymlinks: false)
XCTAssertEqual(seen.count, 2)
XCTAssertTrue(seen.contains { $0.relativePath == "project/real1.swift" })
XCTAssertTrue(seen.contains { $0.relativePath == "project/real2.swift" })
let seen = allFilesSeen(iteratingOver: [tmpdir], followSymlinks: false, workingDirectory: tmpdir)
XCTAssertEqual(Set(seen.map(\.relativePath)), ["project/real1.swift", "project/real2.swift"])
}
}

Expand Down

0 comments on commit 2e4e0a6

Please sign in to comment.