12
12
13
13
/// Represent the user-facing part of SourceLocation that can be calculated
14
14
/// on demand.
15
- struct ComputedLocation : Codable {
15
+ struct ComputedLocation : Codable , CustomDebugStringConvertible {
16
16
/// The line in the file where this location resides. 1-based.
17
17
let line : Int
18
18
@@ -23,6 +23,11 @@ struct ComputedLocation: Codable {
23
23
/// The file in which this location resides.
24
24
let file : String
25
25
26
+ var debugDescription : String {
27
+ // Print file name?
28
+ return " \( line) : \( column) "
29
+ }
30
+
26
31
init ( line: Int , column: Int , file: String ) {
27
32
self . line = line
28
33
self . column = column
@@ -38,7 +43,7 @@ struct ComputedLocation: Codable {
38
43
}
39
44
40
45
/// Represents a source location in a Swift file.
41
- public struct SourceLocation : Codable {
46
+ public struct SourceLocation : Codable , CustomDebugStringConvertible {
42
47
43
48
/// Line and column that can be computed on demand.
44
49
private var compLoc : ComputedLocation ?
@@ -62,6 +67,13 @@ public struct SourceLocation: Codable {
62
67
return compLoc? . file
63
68
}
64
69
70
+ public var debugDescription : String {
71
+ guard let compLoc = compLoc else {
72
+ return " \( offset) "
73
+ }
74
+ return compLoc. debugDescription
75
+ }
76
+
65
77
public init ( line: Int , column: Int , offset: Int , file: String ) {
66
78
self . offset = offset
67
79
self . compLoc = ComputedLocation ( line: line, column: column, file: file)
@@ -79,13 +91,18 @@ public struct SourceLocation: Codable {
79
91
}
80
92
81
93
/// Represents a start and end location in a Swift file.
82
- public struct SourceRange : Codable {
94
+ public struct SourceRange : Codable , CustomDebugStringConvertible {
95
+
83
96
/// The beginning location in the source range.
84
97
public let start : SourceLocation
85
98
86
99
/// The beginning location in the source range.
87
100
public let end : SourceLocation
88
101
102
+ public var debugDescription : String {
103
+ return " ( \( start. debugDescription) , \( end. debugDescription) ) "
104
+ }
105
+
89
106
public init ( start: SourceLocation , end: SourceLocation ) {
90
107
self . start = start
91
108
self . end = end
@@ -111,6 +128,15 @@ public final class SourceLocationConverter {
111
128
assert ( tree. byteSize == endOfFile. utf8Offset)
112
129
}
113
130
131
+ /// - Parameters:
132
+ /// - file: The file path associated with the syntax tree.
133
+ /// - source: The source code to convert positions to line/columns for.
134
+ public init ( file: String , source: String ) {
135
+ self . file = file
136
+ ( self . lines, endOfFile) = computeLines ( source)
137
+ assert ( source. lengthOfBytes ( using: . utf8) == endOfFile. utf8Offset)
138
+ }
139
+
114
140
/// Convert a `AbsolutePosition` to a `SourceLocation`. If the position is
115
141
/// exceeding the file length then the `SourceLocation` for the end of file
116
142
/// is returned. If position is negative the location for start of file is
@@ -305,6 +331,22 @@ fileprivate func computeLines(
305
331
return ( lines, position)
306
332
}
307
333
334
+ fileprivate func computeLines( _ source: String ) ->
335
+ ( [ AbsolutePosition ] , AbsolutePosition ) {
336
+ var lines : [ AbsolutePosition ] = [ ]
337
+ // First line starts from the beginning.
338
+ lines. append ( . startOfFile)
339
+ var position : AbsolutePosition = . startOfFile
340
+ let addLine = { ( lineLength: SourceLength ) in
341
+ position += lineLength
342
+ lines. append ( position)
343
+ }
344
+ var curPrefix : SourceLength = . zero
345
+ curPrefix = source. forEachLineLength ( prefix: curPrefix, body: addLine)
346
+ position += curPrefix
347
+ return ( lines, position)
348
+ }
349
+
308
350
fileprivate extension String {
309
351
/// Walks and passes to `body` the `SourceLength` for every detected line,
310
352
/// with the newline character included.
0 commit comments