0001 // 0002 // String+SourceKitten.swift 0003 // SourceKitten 0004 // 0005 // Created by JP Simard on 2015-01-05. 0006 // Copyright (c) 2015 SourceKitten. All rights reserved. 0007 // 0008 0009 import Foundation 0010 0011 /// Representation of line in String 0012 public struct Line{ 0013 /// origin = 0 0014 public let index
File.swift:22 public var lines: [Line]String+SourceKitten.swift:45 let lines: [Line]String+SourceKitten.swift:73 var lines = [Line]()String+SourceKitten.swift:89 let line = Line(index: lineIndex,String+SourceKitten.swift:360 public func lines() -> [Line] {: Int 0015 /// Content 0016 public let content
String+SourceKitten.swift:164 return (line: line.index, character: offset - line.range.location + 1)String+SourceKitten.swift:183 return (line: line.index, character: character): String 0017 /// UTF16 based range in entire String. Equivalent to Range<UTF16Index> 0018 public let range
String+SourceKitten.swift:126 let endUTF16index = line.content.utf8.startIndex.advancedBy(diff)String+SourceKitten.swift:127 .samePositionIn(line.content.utf16)!String+SourceKitten.swift:128 let utf16Diff = line.content.utf16.startIndex.distanceTo(endUTF16index)String+SourceKitten.swift:154 let endUTF8index = line.content.utf16.startIndex.advancedBy(diff)String+SourceKitten.swift:155 .samePositionIn(line.content.utf8)!String+SourceKitten.swift:156 let byteDiff = line.content.utf8.startIndex.distanceTo(endUTF8index)String+SourceKitten.swift:174 let content = line.content: NSRange 0019 /// Byte based range in entire String. Equivalent to Range<UTF8Index> 0020 public let byteRange
String+SourceKitten.swift:122 return line.range.locationString+SourceKitten.swift:124 return NSMaxRange(line.range)String+SourceKitten.swift:129 return line.range.location + utf16DiffString+SourceKitten.swift:143 let index = lines.indexOf({ NSLocationInRange(location, $0.range) })String+SourceKitten.swift:148 let diff = location - line.range.locationString+SourceKitten.swift:151 } else if line.range.length == diff {String+SourceKitten.swift:161 let index = lines.indexOf { NSLocationInRange(offset, $0.range) }String+SourceKitten.swift:164 return (line: line.index, character: offset - line.range.location + 1): NSRange 0021 } 0022 0023 private let whitespaceAndNewlineCharacterSet
String+SourceKitten.swift:115 let index = lines.indexOf({ NSLocationInRange(byteOffset, $0.byteRange) })String+SourceKitten.swift:120 let diff = byteOffset - line.byteRange.locationString+SourceKitten.swift:123 } else if line.byteRange.length == diff {String+SourceKitten.swift:150 return line.byteRange.locationString+SourceKitten.swift:152 return NSMaxRange(line.byteRange)String+SourceKitten.swift:157 return line.byteRange.location + byteDiffString+SourceKitten.swift:169 let index = lines.indexOf { NSLocationInRange(offset, $0.byteRange) }String+SourceKitten.swift:175 let length = offset - line.byteRange.location + 1String+SourceKitten.swift:176 if length == line.byteRange.length {= NSCharacterSet.whitespaceAndNewlineCharacterSet() 0024 0025 private let commentLinePrefixCharacterSet
String+SourceKitten.swift:491 let leadingWhitespaceCountToAdd = nsString.substringWithRange(NSRange(location: lineStart, length: lineEnd - lineStart)).countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet)String+SourceKitten.swift:504 .stringByTrimmingTrailingCharactersInSet(whitespaceAndNewlineCharacterSet)String+SourceKitten.swift:516 let lineLeadingWhitespace = line.countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet)String+SourceKitten.swift:553 let unwantedSet = whitespaceAndNewlineCharacterSet.mutableCopy() as! NSMutableCharacterSet: NSCharacterSet = { 0026 let characterSet = NSMutableCharacterSet.whitespaceAndNewlineCharacterSet() 0027 /** 0028 * For "wall of asterisk" comment blocks, such as this one. 0029 */ 0030 characterSet.addCharactersInString("*") 0031 return characterSet 0032 }() 0033 0034 private var keyCacheContainer
String+SourceKitten.swift:517 let lineLeadingCharacters = line.countOfLeadingCharactersInSet(commentLinePrefixCharacterSet)= 0 0035 0036 extension NSString { 0037 /** 0038 CacheContainer caches: 0039 0040 - UTF16-based NSRange 0041 - UTF8-based NSRange 0042 - Line 0043 */ 0044 @objc private class CacheContainer
String+SourceKitten.swift:192 if let cache = objc_getAssociatedObject(self, &keyCacheContainer) as? CacheContainer {String+SourceKitten.swift:196 objc_setAssociatedObject(self, &keyCacheContainer, cache, .OBJC_ASSOCIATION_RETAIN_NONATOMIC): NSObject { 0045 let lines
String+SourceKitten.swift:192 if let cache = objc_getAssociatedObject(self, &keyCacheContainer) as? CacheContainer {String+SourceKitten.swift:195 let cache = CacheContainer(self)String+SourceKitten.swift:191 private var cacheContainer: CacheContainer {: [Line] 0046 let utf8View
String+SourceKitten.swift:101 self.lines = linesString+SourceKitten.swift:112 if lines.isEmpty {String+SourceKitten.swift:115 let index = lines.indexOf({ NSLocationInRange(byteOffset, $0.byteRange) })String+SourceKitten.swift:117 guard let line = (index.map { lines[$0] } ?? lines.last) else {String+SourceKitten.swift:117 guard let line = (index.map { lines[$0] } ?? lines.last) else {String+SourceKitten.swift:140 if lines.isEmpty {String+SourceKitten.swift:143 let index = lines.indexOf({ NSLocationInRange(location, $0.range) })String+SourceKitten.swift:145 guard let line = (index.map { lines[$0] } ?? lines.last) else {String+SourceKitten.swift:145 guard let line = (index.map { lines[$0] } ?? lines.last) else {String+SourceKitten.swift:161 let index = lines.indexOf { NSLocationInRange(offset, $0.range) }String+SourceKitten.swift:163 let line = lines[$0]String+SourceKitten.swift:169 let index = lines.indexOf { NSLocationInRange(offset, $0.byteRange) }String+SourceKitten.swift:171 let line = lines[$0]String+SourceKitten.swift:361 return cacheContainer.lines: String.UTF8View 0047 0048 init
String+SourceKitten.swift:62 utf8View = string.utf8String+SourceKitten.swift:84 let utf8indexEnd = utf16indexEnd.samePositionIn(utf8View)!(_ string: NSString) { 0049 // Make a copy of the string to avoid holding a circular reference, which would leak 0050 // memory. 0051 // 0052 // If the string is a `Swift.String`, strongly referencing that in `CacheContainer` does 0053 // not cause a circular reference, because casting `String` to `NSString` makes a new 0054 // `NSString` instance. 0055 // 0056 // If the string is a native `NSString` instance, a circular reference is created when 0057 // assigning `self.utf8View = (string as String).utf8`. 0058 // 0059 // A reference to `NSString` is held by every cast `String` along with their views and 0060 // indices. 0061 let string = string.mutableCopy() as! String 0062 utf8View = string.utf8 0063 0064 var start = 0 // line start 0065 var end = 0 // line end 0066 var contentsEnd = 0 // line end without line delimiter 0067 var lineIndex = 1 // start by 1 0068 var byteOffsetStart = 0 0069 var utf8indexStart = string.utf8.startIndex 0070 var utf16indexStart = string.utf16.startIndex 0071 0072 let nsstring = string as NSString 0073 var lines = [Line]() 0074 while start < nsstring.length { 0075 let range = NSRange(location: start, length: 0) 0076 nsstring.getLineStart(&start, end: &end, contentsEnd: &contentsEnd, forRange: range) 0077 0078 // range 0079 let lineRange = NSRange(location: start, length: end - start) 0080 let contentsRange = NSRange(location: start, length: contentsEnd - start) 0081 0082 // byteRange 0083 let utf16indexEnd = utf16indexStart.advancedBy(end - start) 0084 let utf8indexEnd = utf16indexEnd.samePositionIn(utf8View)! 0085 let byteLength = utf8indexStart.distanceTo(utf8indexEnd) 0086 let byteRange = NSRange(location: byteOffsetStart, length: byteLength) 0087 0088 // line 0089 let line = Line(index: lineIndex, 0090 content: nsstring.substringWithRange(contentsRange), 0091 range: lineRange, byteRange: byteRange) 0092 0093 lines.append(line) 0094 0095 lineIndex += 1 0096 start = end 0097 utf16indexStart = utf16indexEnd 0098 utf8indexStart = utf8indexEnd 0099 byteOffsetStart += byteLength 0100 } 0101 self.lines = lines 0102 } 0103 0104 /** 0105 Returns UTF16 offset from UTF8 offset. 0106 0107 - parameter byteOffset: UTF8-based offset of string. 0108 0109 - returns: UTF16 based offset of string. 0110 */ 0111 func locationFromByteOffset
String+SourceKitten.swift:195 let cache = CacheContainer(self)(byteOffset: Int) -> Int { 0112 if lines.isEmpty { 0113 return 0 0114 } 0115 let index = lines.indexOf({ NSLocationInRange(byteOffset, $0.byteRange) }) 0116 // byteOffset may be out of bounds when sourcekitd points end of string. 0117 guard let line = (index.map { lines[$0] } ?? lines.last) else { 0118 fatalError() 0119 } 0120 let diff = byteOffset - line.byteRange.location 0121 if diff == 0 { 0122 return line.range.location 0123 } else if line.byteRange.length == diff { 0124 return NSMaxRange(line.range) 0125 } 0126 let endUTF16index = line.content.utf8.startIndex.advancedBy(diff) 0127 .samePositionIn(line.content.utf16)! 0128 let utf16Diff = line.content.utf16.startIndex.distanceTo(endUTF16index) 0129 return line.range.location + utf16Diff 0130 } 0131 0132 /** 0133 Returns UTF8 offset from UTF16 offset. 0134 0135 - parameter location: UTF16-based offset of string. 0136 0137 - returns: UTF8 based offset of string. 0138 */ 0139 func byteOffsetFromLocation
String+SourceKitten.swift:261 let utf16Start = cacheContainer.locationFromByteOffset(start)String+SourceKitten.swift:265 let utf16End = cacheContainer.locationFromByteOffset(start + length)(location: Int) -> Int { 0140 if lines.isEmpty { 0141 return 0 0142 } 0143 let index = lines.indexOf({ NSLocationInRange(location, $0.range) }) 0144 // location may be out of bounds when NSRegularExpression points end of string. 0145 guard let line = (index.map { lines[$0] } ?? lines.last) else { 0146 fatalError() 0147 } 0148 let diff = location - line.range.location 0149 if diff == 0 { 0150 return line.byteRange.location 0151 } else if line.range.length == diff { 0152 return NSMaxRange(line.byteRange) 0153 } 0154 let endUTF8index = line.content.utf16.startIndex.advancedBy(diff) 0155 .samePositionIn(line.content.utf8)! 0156 let byteDiff = line.content.utf8.startIndex.distanceTo(endUTF8index) 0157 return line.byteRange.location + byteDiff 0158 } 0159 0160 func lineAndCharacterForCharacterOffset
String+SourceKitten.swift:298 byteOffset = cacheContainer.byteOffsetFromLocation(start)(offset: Int) -> (line: Int, character: Int)? { 0161 let index = lines.indexOf { NSLocationInRange(offset, $0.range) } 0162 return index.map { 0163 let line = lines[$0] 0164 return (line: line.index, character: offset - line.range.location + 1) 0165 } 0166 } 0167 0168 func lineAndCharacterForByteOffset
String+SourceKitten.swift:206 return cacheContainer.lineAndCharacterForCharacterOffset(offset)(offset: Int) -> (line: Int, character: Int)? { 0169 let index = lines.indexOf { NSLocationInRange(offset, $0.byteRange) } 0170 return index.map { 0171 let line = lines[$0] 0172 0173 let character: Int 0174 let content = line.content 0175 let length = offset - line.byteRange.location + 1 0176 if length == line.byteRange.length { 0177 character = content.utf16.count 0178 } else { 0179 let endIndex = content.utf8.startIndex.advancedBy(length) 0180 .samePositionIn(content.utf16) ?? content.utf16.endIndex 0181 character = content.utf16.startIndex.distanceTo(endIndex) 0182 } 0183 return (line: line.index, character: character) 0184 } 0185 } 0186 } 0187 0188 /** 0189 CacheContainer instance is stored to instance of NSString as associated object. 0190 */ 0191 private var cacheContainer
String+SourceKitten.swift:215 return cacheContainer.lineAndCharacterForByteOffset(offset): CacheContainer { 0192 if let cache = objc_getAssociatedObject(self, &keyCacheContainer) as? CacheContainer { 0193 return cache 0194 } 0195 let cache = CacheContainer(self) 0196 objc_setAssociatedObject(self, &keyCacheContainer, cache, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 0197 return cache 0198 } 0199 0200 /** 0201 Returns line number and character for utf16 based offset. 0202 0203 - parameter offset: utf16 based index. 0204 */ 0205 public func lineAndCharacterForCharacterOffset(offset: Int) -> (line: Int, character: Int)? { 0206 return cacheContainer.lineAndCharacterForCharacterOffset(offset) 0207 } 0208 0209 /** 0210 Returns line number and character for byte offset. 0211 0212 - parameter offset: byte offset. 0213 */ 0214 public func lineAndCharacterForByteOffset
String+SourceKitten.swift:206 return cacheContainer.lineAndCharacterForCharacterOffset(offset)String+SourceKitten.swift:215 return cacheContainer.lineAndCharacterForByteOffset(offset)String+SourceKitten.swift:261 let utf16Start = cacheContainer.locationFromByteOffset(start)String+SourceKitten.swift:265 let utf16End = cacheContainer.locationFromByteOffset(start + length)String+SourceKitten.swift:298 byteOffset = cacheContainer.byteOffsetFromLocation(start)String+SourceKitten.swift:361 return cacheContainer.lines(offset: Int) -> (line: Int, character: Int)? { 0215 return cacheContainer.lineAndCharacterForByteOffset(offset) 0216 } 0217 0218 /** 0219 Returns a copy of `self` with the trailing contiguous characters belonging to `characterSet` 0220 removed. 0221 0222 - parameter characterSet: Character set to check for membership. 0223 */ 0224 public func stringByTrimmingTrailingCharactersInSet
File.swift:321 let commentEndLine = (contents as NSString).lineAndCharacterForByteOffset(commentByteRange.endIndex)?.lineFile.swift:322 let tokenStartLine = (contents as NSString).lineAndCharacterForByteOffset(Int(offset))?.line(characterSet: NSCharacterSet) -> String { 0225 if length == 0 { 0226 return self as String 0227 } 0228 var charBuffer = [unichar](count: length, repeatedValue: 0) 0229 getCharacters(&charBuffer) 0230 for newLength in (1...length).reverse() { 0231 if !characterSet.characterIsMember(charBuffer[newLength - 1]) { 0232 return substringWithRange(NSRange(location: 0, length: newLength)) 0233 } 0234 } 0235 return "" 0236 } 0237 0238 /** 0239 Returns self represented as an absolute path. 0240 0241 - parameter rootDirectory: Absolute parent path if not already an absolute path. 0242 */ 0243 public func absolutePathRepresentation
String+SourceKitten.swift:504 .stringByTrimmingTrailingCharactersInSet(whitespaceAndNewlineCharacterSet)(rootDirectory: String = NSFileManager.defaultManager().currentDirectoryPath) -> String { 0244 if absolutePath { 0245 return self as String 0246 } 0247 return (NSString.pathWithComponents([rootDirectory, self as String]) as NSString).stringByStandardizingPath 0248 } 0249 0250 /** 0251 Converts a range of byte offsets in `self` to an `NSRange` suitable for filtering `self` as an 0252 `NSString`. 0253 0254 - parameter start: Starting byte offset. 0255 - parameter length: Length of bytes to include in range. 0256 0257 - returns: An equivalent `NSRange`. 0258 */ 0259 public func byteRangeToNSRange
File.swift:30 self.path = (path as NSString).absolutePathRepresentation()Xcode.swift:164 headerFiles.append(xcodebuildArguments.removeAtIndex(0).absolutePathRepresentation())(start start: Int, length: Int) -> NSRange? { 0260 if self.length == 0 { return nil } 0261 let utf16Start = cacheContainer.locationFromByteOffset(start) 0262 if length == 0 { 0263 return NSRange(location: utf16Start, length: 0) 0264 } 0265 let utf16End = cacheContainer.locationFromByteOffset(start + length) 0266 return NSRange(location: utf16Start, length: utf16End - utf16Start) 0267 } 0268 0269 /** 0270 Converts an `NSRange` suitable for filtering `self` as an 0271 `NSString` to a range of byte offsets in `self`. 0272 0273 - parameter start: Starting character index in the string. 0274 - parameter length: Number of characters to include in range. 0275 0276 - returns: An equivalent `NSRange`. 0277 */ 0278 public func NSRangeToByteRange
File.swift:326 return contents.byteRangeToNSRange(start: commentByteRange.startIndex, length: commentByteRange.endIndex - commentByteRange.startIndex).flatMap { nsRange inSourceDeclaration.swift:20 file.contents.byteRangeToNSRange(start: $0.range.location, length: $0.range.length) ?? NSRange()SourceDeclaration.swift:24 let range = file.contents.byteRangeToNSRange(start: declaration.range.location, length: declaration.range.length)String+SourceKitten.swift:316 return byteRangeToNSRange(start: start, length: length).map(substringWithRange)String+SourceKitten.swift:327 return byteRangeToNSRange(start: start, length: length).map { range inString+SourceKitten.swift:341 return byteRangeToNSRange(start: start, length: length).flatMap { range in(start start: Int, length: Int) -> NSRange? { 0279 let string = self as String 0280 0281 let utf16View = string.utf16 0282 let startUTF16Index = utf16View.startIndex.advancedBy(start) 0283 let endUTF16Index = startUTF16Index.advancedBy(length) 0284 0285 let utf8View = string.utf8 0286 guard let startUTF8Index = startUTF16Index.samePositionIn(utf8View), 0287 let endUTF8Index = endUTF16Index.samePositionIn(utf8View) else { 0288 return nil 0289 } 0290 0291 // Don't using `CacheContainer` if string is short. 0292 // There are two reasons for: 0293 // 1. Avoid using associatedObject on NSTaggedPointerString (< 7 bytes) because that does 0294 // not free associatedObject. 0295 // 2. Using cache is overkill for short string. 0296 let byteOffset: Int 0297 if utf16View.count > 50 { 0298 byteOffset = cacheContainer.byteOffsetFromLocation(start) 0299 } else { 0300 byteOffset = utf8View.startIndex.distanceTo(startUTF8Index) 0301 } 0302 0303 // `cacheContainer` will hit for below, but that will be calculated from startUTF8Index 0304 // in most case. 0305 let length = startUTF8Index.distanceTo(endUTF8Index) 0306 return NSRange(location: byteOffset, length: length) 0307 } 0308 0309 /** 0310 Returns a substring with the provided byte range. 0311 0312 - parameter start: Starting byte offset. 0313 - parameter length: Length of bytes to include in range. 0314 */ 0315 public func substringWithByteRange
String+SourceKitten.swift:411 guard let markByteRange = self.NSRangeToByteRange(start: markRange.location, length: markRange.length) else {(start start: Int, length: Int) -> String? { 0316 return byteRangeToNSRange(start: start, length: length).map(substringWithRange) 0317 } 0318 0319 /** 0320 Returns a substring starting at the beginning of `start`'s line and ending at the end of `end`'s 0321 line. Returns `start`'s entire line if `end` is nil. 0322 0323 - parameter start: Starting byte offset. 0324 - parameter length: Length of bytes to include in range. 0325 */ 0326 public func substringLinesWithByteRange
String+SourceKitten.swift:382 return substringWithByteRange(start: Int(start.offset), length: Int(end.offset - start.offset))String+SourceKitten.swift:435 return ((self as NSString).substringWithByteRange(start: token.offset, length: token.length))(start start: Int, length: Int) -> String? { 0327 return byteRangeToNSRange(start: start, length: length).map { range in 0328 var lineStart = 0, lineEnd = 0 0329 getLineStart(&lineStart, end: &lineEnd, contentsEnd: nil, forRange: range) 0330 return substringWithRange(NSRange(location: lineStart, length: lineEnd - lineStart)) 0331 } 0332 } 0333 0334 /** 0335 Returns line numbers containing starting and ending byte offsets. 0336 0337 - parameter start: Starting byte offset. 0338 - parameter length: Length of bytes to include in range. 0339 */ 0340 public func lineRangeWithByteRange
File.swift:69 return contents.substringLinesWithByteRange(start: start, length: length)?(start start: Int, length: Int) -> (start: Int, end: Int)? { 0341 return byteRangeToNSRange(start: start, length: length).flatMap { range in 0342 var numberOfLines = 0, index = 0, lineRangeStart = 0 0343 while index < self.length { 0344 numberOfLines += 1 0345 if index <= range.location { 0346 lineRangeStart = numberOfLines 0347 } 0348 index = NSMaxRange(lineRangeForRange(NSRange(location: index, length: 1))) 0349 if index > NSMaxRange(range) { 0350 return (lineRangeStart, numberOfLines) 0351 } 0352 } 0353 return nil 0354 } 0355 } 0356 0357 /** 0358 Returns an array of Lines for each line in the file. 0359 */ 0360 public func lines
File.swift:93 return contents.lineRangeWithByteRange(start: start, length: length)String+SourceKitten.swift:415 line: UInt32((self as NSString).lineRangeWithByteRange(start: markByteRange.location, length: 0)!.start),() -> [Line] { 0361 return cacheContainer.lines 0362 } 0363 0364 /** 0365 Returns true if self is an Objective-C header file. 0366 */ 0367 public func isObjectiveCHeaderFile
File.swift:33 lines = contents.lines()File.swift:51 lines = contents.lines()() -> Bool { 0368 return ["h", "hpp", "hh"].contains(pathExtension) 0369 } 0370 0371 /** 0372 Returns true if self is a Swift file. 0373 */ 0374 public func isSwiftFile
Xcode.swift:163 while let headerFile = xcodebuildArguments.first where headerFile.isObjectiveCHeaderFile() {() -> Bool { 0375 return pathExtension == "swift" 0376 } 0377 0378 /** 0379 Returns a substring from a start and end SourceLocation. 0380 */ 0381 public func substringWithSourceRange
Module.swift:70 sourceFiles = compilerArguments.filter({ $0.isSwiftFile() }).map { ($0 as NSString).stringByResolvingSymlinksInPath }(start: SourceLocation, end: SourceLocation) -> String? { 0382 return substringWithByteRange(start: Int(start.offset), length: Int(end.offset - start.offset)) 0383 } 0384 } 0385 0386 extension String { 0387 /// Returns the `#pragma mark`s in the string. 0388 /// Just the content; no leading dashes or leading `#pragma mark`. 0389 public func pragmaMarks
Clang+SourceKitten.swift:84 return contents.substringWithSourceRange(cursorExtent.start, end: cursorExtent.end)(filename: String, excludeRanges: [NSRange], limitRange: NSRange?) -> [SourceDeclaration] { 0390 let regex = try! NSRegularExpression(pattern: "(#pragma\\smark|@name)[ -]*([^\\n]+)", options: []) // Safe to force try 0391 let range: NSRange 0392 if let limitRange = limitRange { 0393 range = NSRange(location: limitRange.location, length: min(utf16.count - limitRange.location, limitRange.length)) 0394 } else { 0395 range = NSRange(location: 0, length: utf16.count) 0396 } 0397 let matches = regex.matchesInString(self, options: [], range: range) 0398 0399 return matches.flatMap { match in 0400 let markRange = match.rangeAtIndex(2) 0401 for excludedRange in excludeRanges { 0402 if NSIntersectionRange(excludedRange, markRange).length > 0 { 0403 return nil 0404 } 0405 } 0406 let markString = (self as NSString).substringWithRange(markRange) 0407 .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) 0408 if markString.isEmpty { 0409 return nil 0410 } 0411 guard let markByteRange = self.NSRangeToByteRange(start: markRange.location, length: markRange.length) else { 0412 return nil 0413 } 0414 let location = SourceLocation(file: filename, 0415 line: UInt32((self as NSString).lineRangeWithByteRange(start: markByteRange.location, length: 0)!.start), 0416 column: 1, offset: UInt32(markByteRange.location)) 0417 return SourceDeclaration(type: .Mark, location: location, extent: (location, location), name: markString, 0418 usr: nil, declaration: nil, documentation: nil, commentBody: nil, children: []) 0419 } 0420 } 0421 0422 /** 0423 Returns whether or not the `token` can be documented. Either because it is a 0424 `SyntaxKind.Identifier` or because it is a function treated as a `SyntaxKind.Keyword`: 0425 0426 - `subscript` 0427 - `init` 0428 - `deinit` 0429 0430 - parameter token: Token to process. 0431 */ 0432 public func isTokenDocumentable
SourceDeclaration.swift:19 let currentMarks = file.contents.pragmaMarks(path, excludeRanges: declarations.map({(token: SyntaxToken) -> Bool { 0433 if token.type == SyntaxKind.Keyword.rawValue { 0434 let keywordFunctions = ["subscript", "init", "deinit"] 0435 return ((self as NSString).substringWithByteRange(start: token.offset, length: token.length)) 0436 .map(keywordFunctions.contains) ?? false 0437 } 0438 return token.type == SyntaxKind.Identifier.rawValue 0439 } 0440 0441 /** 0442 Find integer offsets of documented Swift tokens in self. 0443 0444 - parameter syntaxMap: Syntax Map returned from SourceKit editor.open request. 0445 0446 - returns: Array of documented token offsets. 0447 */ 0448 public func documentedTokenOffsets
String+SourceKitten.swift:449 let documentableOffsets = syntaxMap.tokens.filter(isTokenDocumentable).map {(syntaxMap: SyntaxMap) -> [Int] { 0449 let documentableOffsets = syntaxMap.tokens.filter(isTokenDocumentable).map { 0450 $0.offset 0451 } 0452 0453 let regex = try! NSRegularExpression(pattern: "(///.*\\n|\\*/\\n)", options: []) // Safe to force try 0454 let range = NSRange(location: 0, length: utf16.count) 0455 let matches = regex.matchesInString(self, options: [], range: range) 0456 0457 return matches.flatMap { match in 0458 documentableOffsets.filter({ $0 >= match.range.location }).first 0459 } 0460 } 0461 0462 /** 0463 Returns the body of the comment if the string is a comment. 0464 0465 - parameter range: Range to restrict the search for a comment body. 0466 */ 0467 public func commentBody
SwiftDocs.swift:57 let documentedTokenOffsets = file.contents.documentedTokenOffsets(syntaxMap)(range: NSRange? = nil) -> String? { 0468 let nsString = self as NSString 0469 let patterns: [(pattern: String, options: NSRegularExpressionOptions)] = [ 0470 ("^\\s*\\/\\*\\*\\s*(.*?)\\*\\/", [.AnchorsMatchLines, .DotMatchesLineSeparators]), // multi: ^\s*\/\*\*\s*(.*?)\*\/ 0471 ("^\\s*\\/\\/\\/(.+)?", .AnchorsMatchLines) // single: ^\s*\/\/\/(.+)? 0472 ] 0473 let range = range ?? NSRange(location: 0, length: nsString.length) 0474 for pattern in patterns { 0475 let regex = try! NSRegularExpression(pattern: pattern.pattern, options: pattern.options) // Safe to force try 0476 let matches = regex.matchesInString(self, options: [], range: range) 0477 let bodyParts = matches.flatMap { match -> [String] in 0478 let numberOfRanges = match.numberOfRanges 0479 if numberOfRanges < 1 { 0480 return [] 0481 } 0482 return (1..<numberOfRanges).map { rangeIndex in 0483 let range = match.rangeAtIndex(rangeIndex) 0484 if range.location == NSNotFound { 0485 return "" // empty capture group, return empty string 0486 } 0487 var lineStart = 0 0488 var lineEnd = nsString.length 0489 let indexRange = NSRange(location: range.location, length: 0) 0490 nsString.getLineStart(&lineStart, end: &lineEnd, contentsEnd: nil, forRange: indexRange) 0491 let leadingWhitespaceCountToAdd = nsString.substringWithRange(NSRange(location: lineStart, length: lineEnd - lineStart)).countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet) 0492 let leadingWhitespaceToAdd = String(count: leadingWhitespaceCountToAdd, repeatedValue: Character(" ")) 0493 0494 let bodySubstring = nsString.substringWithRange(range) 0495 if bodySubstring.containsString("@name") { 0496 return "" // appledoc directive, return empty string 0497 } 0498 return leadingWhitespaceToAdd + bodySubstring 0499 } 0500 } 0501 if bodyParts.count > 0 { 0502 return bodyParts 0503 .joinWithSeparator("\n") 0504 .stringByTrimmingTrailingCharactersInSet(whitespaceAndNewlineCharacterSet) 0505 .stringByRemovingCommonLeadingWhitespaceFromLines() 0506 } 0507 } 0508 return nil 0509 } 0510 0511 /// Returns a copy of `self` with the leading whitespace common in each line removed. 0512 public func stringByRemovingCommonLeadingWhitespaceFromLines
Clang+SourceKitten.swift:149 var commentBody = rawComment?.commentBody()File.swift:327 return contents.commentBody(nsRange)() -> String { 0513 var minLeadingCharacters = Int.max 0514 0515 enumerateLines { line, _ in 0516 let lineLeadingWhitespace = line.countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet) 0517 let lineLeadingCharacters = line.countOfLeadingCharactersInSet(commentLinePrefixCharacterSet) 0518 // Is this prefix smaller than our last and not entirely whitespace? 0519 if lineLeadingCharacters < minLeadingCharacters && lineLeadingWhitespace != line.characters.count { 0520 minLeadingCharacters = lineLeadingCharacters 0521 } 0522 } 0523 var lines = [String]() 0524 enumerateLines { line, _ in 0525 if line.characters.count >= minLeadingCharacters { 0526 lines.append(line[line.startIndex.advancedBy(minLeadingCharacters)..<line.endIndex]) 0527 } else { 0528 lines.append(line) 0529 } 0530 } 0531 return lines.joinWithSeparator("\n") 0532 } 0533 0534 /** 0535 Returns the number of contiguous characters at the start of `self` belonging to `characterSet`. 0536 0537 - parameter characterSet: Character set to check for membership. 0538 */ 0539 public func countOfLeadingCharactersInSet
Clang+SourceKitten.swift:202 return [.Para(ret.stringByRemovingCommonLeadingWhitespaceFromLines(), kindString)]String+SourceKitten.swift:505 .stringByRemovingCommonLeadingWhitespaceFromLines()(characterSet: NSCharacterSet) -> Int { 0540 let utf16View = utf16 0541 var count = 0 0542 for char in utf16View { 0543 if !characterSet.characterIsMember(char) { 0544 break 0545 } 0546 count += 1 0547 } 0548 return count 0549 } 0550 0551 /// Returns a copy of the string by trimming whitespace and the opening curly brace (`{`). 0552 internal func stringByTrimmingWhitespaceAndOpeningCurlyBrace
String+SourceKitten.swift:491 let leadingWhitespaceCountToAdd = nsString.substringWithRange(NSRange(location: lineStart, length: lineEnd - lineStart)).countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet)String+SourceKitten.swift:516 let lineLeadingWhitespace = line.countOfLeadingCharactersInSet(whitespaceAndNewlineCharacterSet)String+SourceKitten.swift:517 let lineLeadingCharacters = line.countOfLeadingCharactersInSet(commentLinePrefixCharacterSet)() -> String? { 0553 let unwantedSet = whitespaceAndNewlineCharacterSet.mutableCopy() as! NSMutableCharacterSet 0554 unwantedSet.addCharactersInString("{") 0555 return stringByTrimmingCharactersInSet(unwantedSet) 0556 } 0557 } 0558
File.swift:70 .stringByTrimmingWhitespaceAndOpeningCurlyBrace()