File: LineList.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (231 lines) | stat: -rw-r--r-- 7,346 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021-2022 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 Swift project authors
*/

import Foundation

extension SymbolGraph {
    /**
     A `LineList` is a logical grouping of text ranges in a document making up a block of textual content.

     A line list shouldn't contain any documentation comment markers or newlines.

     For example, for the following C++\-style documentation comment:

     ```c++
     /// First line
     /// Second line
     void foo() {}
     ```

     The line list would be represented by the following LineList:

     ```json
    {
      "lines": [
        {
          "text": "First line",
          "range": {
            "start": {
              "line": 0,
              "character": 4
            },
            "end": {
              "line": 0,
              "character": 14
            }
          }
        },
        {
          "text": "Second line",
          "range": {
            "start": {
              "line": 1,
              "character": 4
            },
            "end": {
              "line": 1,
              "character": 15
            }
          }
        }
      ]
    }
    ```

     The same breakdown should occur for block-style documentation comments, as in:

     ```c++
     /**
     * First line
     * Second line
     */
     void foo() {}
     ```

     or:

     ```c++
     /**
     First line
     Second line
     */
     void foo() {}
     ```

     It is the responsibility of the tool generating the symbol graph to measure and trim indentation appropriately to project a logical block of text. In all of the above cases, logically, the text is:

     ```
     First line
     Second line
     ```

     That is the text content that would be parsed as markup.

     Line lists were chosen as the representation of documentation markup because each language may have different syntactic forms for documentation comments. This form works for both sequences of single-line comments or multi-line comment blocks.
     */
    public struct LineList: Codable, Equatable {
        /// The lines making up this line list.
        public var lines: [Line]
        
        /// The URI of the source file where the documentation comment originated.
        public var uri: String?
        
        /// The file URL of the source file where the documentation comment originated.
        @available(macOS 10.11, *)
        public var url: URL? {
            guard let uri = uri else { return nil }
            // The URI string provided in the symbol graph file may be an invalid URL (rdar://69242070)
            //
            // Using `URL.init(dataRepresentation:relativeTo:)` here handles URI strings with unescaped
            // characters without trying to escape or otherwise process the URI string in SymbolKit.
            return URL(dataRepresentation: Data(uri.utf8), relativeTo: nil)
        }
        
        /// The name of the source module where the documentation comment originated.
        public var moduleName: String?
        
        enum CodingKeys: String, CodingKey {
            case lines
            case uri
            case moduleName = "module"
        }
        
        public init(_ lines: [Line], uri: String? = nil, moduleName: String? = nil) {
            self.lines = lines
            self.uri = uri
            self.moduleName = moduleName
        }

        /**
         Translate a position from its *local space* to this line list's *file space*.

         For example, take the following documentation comment from a source file:

         ```swift
            0123456789ABCDEFGHI
         68 /// This is
         69 /// a doc comment.
         70 func foo() {}
         ```

         This has the following lines and ranges:

         ```none
         68:4-68:B "This is"
         69:4-69:I "a doc comment"
         ```

         However, documentation comments are typically projected out into a single, contiguous text block, like so:

         ```none
           0123456789ABCDE
         0 This is
         1 a doc comment.
         ```

         If you need to refer to a position or selection in this text block back in the source file, you will need to translate it from this local space to the file's space.
         This API will perform that transformation, taking it back to file space.

         - note: A `LineList` may not have range information, which may occur if the tool generating a symbol graph did not have access to source files or source position information.

         - precondition: `position.line >= 0 && position.line < lines.count`
         - parameter position: A position in its local space to be translated to file space.
         - returns: The position translated to file space if this line list has range information from the file, otherwise `nil`.
         */
        public func translateToFileSpace(_ position: SourceRange.Position) -> SourceRange.Position? {
            let fileLine = lines[position.line]
            guard let fileRange = fileLine.range else {
                return nil
            }
            return .init(line: fileRange.start.line, character: position.character + fileRange.start.character)
        }

        /**
         Translate a range from its *local space* to this line list's *file space*.

         This method calls the overload ``translateToFileSpace(_:)-9dlzx`` on each bound of the `range`.

         - Note: A range in its local space may cross over documentation comment markers in file space. For example:

         A selection of "`is\na doc comment`" in

         ```none
                v
           0123456789ABCDE
         0 This is
         1 a doc comment.
            ^
         ```

         will be the selection `is\n/// a doc comment` in the original file, crossing over the doc comment markers.

         ```swift
                    v
           0123456789ABCDEFGHI
         0 /// This is
         1 /// a doc comment.
                ^
         ```
         */
        public func translateToFileSpace(_ range: SourceRange) -> SourceRange? {
            guard let start = translateToFileSpace(range.start),
                let end = translateToFileSpace(range.end) else {
                    return nil
            }
            return .init(start: start, end: end)
        }
    }
}

extension SymbolGraph.LineList {
    /**
     A line extracted from text.

     If a `Line` is a selection of a line in a documentation comment, it should not contain any comment markers, such as `//`, `///`, `/**`, `*/`, etc.

     A `Line`'s `content` should not include newline characters.
     */
    public struct Line: Codable, Equatable {
        /**
         The line's textual content, not including any documentation comment markers or newlines.

         This may be an empty string, which represents an empty line.
         */
        public var text: String

        /// The line's range in a document if available.
        public var range: SourceRange?

        public init(text: String, range: SourceRange?) {
            self.text = text
            self.range = range
        }
    }
}