Skip to content

Commit e26d9f6

Browse files
authored
Merge pull request #1915 from ahoppen/diags-from-symlinks
Return diagnostics if SwiftPM project is opened from a symlinked URL
2 parents 81fe786 + 6063c27 commit e26d9f6

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

Sources/SourceKitLSP/Swift/Diagnostic.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import LanguageServerProtocolExtensions
1717
import SKLogging
1818
import SourceKitD
1919
import SwiftDiagnostics
20+
import SwiftExtensions
2021
import SwiftSyntax
2122

2223
extension CodeAction {
@@ -154,7 +155,6 @@ fileprivate extension String {
154155
}
155156

156157
extension Diagnostic {
157-
158158
/// Creates a diagnostic from a sourcekitd response dictionary.
159159
///
160160
/// `snapshot` is the snapshot of the document for which the diagnostics are generated.
@@ -172,7 +172,22 @@ extension Diagnostic {
172172
logger.fault("Missing file path in diagnostic")
173173
return nil
174174
}
175-
guard filePath == snapshot.uri.pseudoPath else {
175+
176+
func haveSameRealpath(_ lhs: DocumentURI, _ rhs: DocumentURI) -> Bool {
177+
guard let lhsFileURL = lhs.fileURL, let rhsFileURL = rhs.fileURL else {
178+
return false
179+
}
180+
do {
181+
return try lhsFileURL.realpath == rhsFileURL.realpath
182+
} catch {
183+
return false
184+
}
185+
}
186+
187+
guard
188+
filePath == snapshot.uri.pseudoPath
189+
|| haveSameRealpath(DocumentURI(filePath: filePath, isDirectory: false), snapshot.uri)
190+
else {
176191
logger.error("Ignoring diagnostic from a different file: \(filePath)")
177192
return nil
178193
}

Tests/SourceKitLSPTests/PullDiagnosticsTests.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,39 @@ final class PullDiagnosticsTests: XCTestCase {
431431
]
432432
)
433433
}
434+
435+
func testDiagnosticsWhenOpeningProjectFromSymlink() async throws {
436+
let contents = """
437+
let x: String = 1
438+
"""
439+
let project = try await SwiftPMTestProject(
440+
files: ["FileA.swift": contents],
441+
workspaces: { scratchDirectory in
442+
let symlinkUrl = scratchDirectory.appendingPathComponent("symlink")
443+
try FileManager.default.createSymbolicLink(
444+
at: symlinkUrl,
445+
withDestinationURL: scratchDirectory
446+
)
447+
return [WorkspaceFolder(uri: DocumentURI(symlinkUrl))]
448+
}
449+
)
450+
451+
let uri = DocumentURI(
452+
project.scratchDirectory
453+
.appendingPathComponent("symlink")
454+
.appendingPathComponent("Sources")
455+
.appendingPathComponent("MyLibrary")
456+
.appendingPathComponent("FileA.swift")
457+
)
458+
project.testClient.send(
459+
DidOpenTextDocumentNotification(
460+
textDocument: TextDocumentItem(uri: uri, language: .swift, version: 0, text: contents)
461+
)
462+
)
463+
let diagnostics = try await project.testClient.send(
464+
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri))
465+
)
466+
let diagnostic = try XCTUnwrap(diagnostics.fullReport?.items.only)
467+
XCTAssertEqual(diagnostic.message, "Cannot convert value of type 'Int' to specified type 'String'")
468+
}
434469
}

0 commit comments

Comments
 (0)