1
1
/*
2
2
This source file is part of the Swift.org open source project
3
3
4
- Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4
+ Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
5
5
Licensed under Apache License v2.0 with Runtime Library Exception
6
6
7
7
See https://swift.org/LICENSE.txt for license information
@@ -27,18 +27,30 @@ public final class DiagnosticConsoleWriter: DiagnosticFormattingConsumer {
27
27
/// - formattingOptions: The formatting options for the diagnostics.
28
28
/// - baseUrl: A url to be used as a base url when formatting diagnostic source path.
29
29
/// - highlight: Whether or not to highlight the default diagnostic formatting output.
30
- public init (
30
+ public convenience init (
31
31
_ stream: TextOutputStream = LogHandle . standardError,
32
32
formattingOptions options: DiagnosticFormattingOptions = [ ] ,
33
33
baseURL: URL ? = nil ,
34
34
highlight: Bool ? = nil
35
+ ) {
36
+ self . init ( stream, formattingOptions: options, baseURL: baseURL, highlight: highlight, fileManager: FileManager . default)
37
+ }
38
+
39
+ @_spi ( FileManagerProtocol)
40
+ public init (
41
+ _ stream: TextOutputStream = LogHandle . standardError,
42
+ formattingOptions options: DiagnosticFormattingOptions = [ ] ,
43
+ baseURL: URL ? = nil ,
44
+ highlight: Bool ? = nil ,
45
+ fileManager: FileManagerProtocol = FileManager . default
35
46
) {
36
47
outputStream = stream
37
48
formattingOptions = options
38
49
diagnosticFormatter = Self . makeDiagnosticFormatter (
39
50
options,
40
51
baseURL: baseURL,
41
- highlight: highlight ?? TerminalHelper . isConnectedToTerminal
52
+ highlight: highlight ?? TerminalHelper . isConnectedToTerminal,
53
+ fileManager: fileManager
42
54
)
43
55
}
44
56
@@ -72,31 +84,43 @@ public final class DiagnosticConsoleWriter: DiagnosticFormattingConsumer {
72
84
private static func makeDiagnosticFormatter(
73
85
_ options: DiagnosticFormattingOptions ,
74
86
baseURL: URL ? ,
75
- highlight: Bool
87
+ highlight: Bool ,
88
+ fileManager: FileManagerProtocol
76
89
) -> DiagnosticConsoleFormatter {
77
90
if options. contains ( . formatConsoleOutputForTools) {
78
91
return IDEDiagnosticConsoleFormatter ( options: options)
79
92
} else {
80
- return DefaultDiagnosticConsoleFormatter ( baseUrl: baseURL, highlight: highlight, options: options)
93
+ return DefaultDiagnosticConsoleFormatter ( baseUrl: baseURL, highlight: highlight, options: options, fileManager : fileManager )
81
94
}
82
95
}
83
96
}
84
97
85
98
// MARK: Formatted descriptions
86
99
87
100
extension DiagnosticConsoleWriter {
88
-
89
101
public static func formattedDescription< Problems> ( for problems: Problems , options: DiagnosticFormattingOptions = [ ] ) -> String where Problems: Sequence , Problems. Element == Problem {
90
- return problems. map { formattedDescription ( for: $0, options: options) } . joined ( separator: " \n " )
102
+ formattedDescription ( for: problems, options: options, fileManager: FileManager . default)
103
+ }
104
+ @_spi ( FileManagerProtocol)
105
+ public static func formattedDescription< Problems> ( for problems: Problems , options: DiagnosticFormattingOptions = [ ] , fileManager: FileManagerProtocol ) -> String where Problems: Sequence , Problems. Element == Problem {
106
+ return problems. map { formattedDescription ( for: $0, options: options, fileManager: fileManager) } . joined ( separator: " \n " )
91
107
}
92
108
93
109
public static func formattedDescription( for problem: Problem , options: DiagnosticFormattingOptions = [ ] ) -> String {
94
- let diagnosticFormatter = makeDiagnosticFormatter ( options, baseURL: nil , highlight: TerminalHelper . isConnectedToTerminal)
110
+ formattedDescription ( for: problem, options: options, fileManager: FileManager . default)
111
+ }
112
+ @_spi ( FileManagerProtocol)
113
+ public static func formattedDescription( for problem: Problem , options: DiagnosticFormattingOptions = [ ] , fileManager: FileManagerProtocol = FileManager . default) -> String {
114
+ let diagnosticFormatter = makeDiagnosticFormatter ( options, baseURL: nil , highlight: TerminalHelper . isConnectedToTerminal, fileManager: fileManager)
95
115
return diagnosticFormatter. formattedDescription ( for: problem)
96
116
}
97
117
98
118
public static func formattedDescription( for diagnostic: Diagnostic , options: DiagnosticFormattingOptions = [ ] ) -> String {
99
- let diagnosticFormatter = makeDiagnosticFormatter ( options, baseURL: nil , highlight: TerminalHelper . isConnectedToTerminal)
119
+ formattedDescription ( for: diagnostic, options: options, fileManager: FileManager . default)
120
+ }
121
+ @_spi ( FileManagerProtocol)
122
+ public static func formattedDescription( for diagnostic: Diagnostic , options: DiagnosticFormattingOptions = [ ] , fileManager: FileManagerProtocol ) -> String {
123
+ let diagnosticFormatter = makeDiagnosticFormatter ( options, baseURL: nil , highlight: TerminalHelper . isConnectedToTerminal, fileManager: fileManager)
100
124
return diagnosticFormatter. formattedDescription ( for: diagnostic)
101
125
}
102
126
}
@@ -205,18 +229,21 @@ final class DefaultDiagnosticConsoleFormatter: DiagnosticConsoleFormatter {
205
229
private let baseUrl : URL ?
206
230
private let highlight : Bool
207
231
private var sourceLines : [ URL : [ String ] ] = [ : ]
232
+ private var fileManager : FileManagerProtocol
208
233
209
234
/// The number of additional lines from the source file that should be displayed both before and after the diagnostic source line.
210
235
private static let contextSize = 2
211
236
212
237
init (
213
238
baseUrl: URL ? ,
214
239
highlight: Bool ,
215
- options: DiagnosticFormattingOptions
240
+ options: DiagnosticFormattingOptions ,
241
+ fileManager: FileManagerProtocol
216
242
) {
217
243
self . baseUrl = baseUrl
218
244
self . highlight = highlight
219
245
self . options = options
246
+ self . fileManager = fileManager
220
247
}
221
248
222
249
func formattedDescription< Problems> ( for problems: Problems ) -> String where Problems: Sequence , Problems. Element == Problem {
@@ -360,7 +387,7 @@ extension DefaultDiagnosticConsoleFormatter {
360
387
// Example:
361
388
// 9 | A line outside the diagnostic range.
362
389
// 10 + A line inside the diagnostic range.
363
- result. append ( " \n \( linePrefix) \( separator) \( highlightedSource) " )
390
+ result. append ( " \n \( linePrefix) \( separator) \( highlightedSource) " . removingTrailingWhitespace ( ) )
364
391
365
392
var suggestionsPerColumn = [ Int: [ String] ] ( )
366
393
@@ -466,8 +493,11 @@ extension DefaultDiagnosticConsoleFormatter {
466
493
}
467
494
468
495
// TODO: Add support for also getting the source lines from the symbol graph files.
469
- guard let content = try ? String ( contentsOf: url)
470
- else { return [ ] }
496
+ guard let data = fileManager. contents ( atPath: url. path) ,
497
+ let content = String ( data: data, encoding: . utf8)
498
+ else {
499
+ return [ ]
500
+ }
471
501
472
502
let lines = content. splitByNewlines
473
503
sourceLines [ url] = lines
0 commit comments