From 083a5299e0c74a96f20c1d8f64228518efdc3470 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Fri, 20 Nov 2015 23:28:33 -0800 Subject: [PATCH] Fix issue where extensions would pick up documentation from previous tokens --- CHANGELOG.md | 5 +++++ Source/SourceKittenFramework/File.swift | 5 +++++ .../String+SourceKitten.swift | 15 +++++++++++++++ Source/SourceKittenFramework/SyntaxKind.swift | 10 +++------- Source/SourceKittenFramework/SyntaxMap.swift | 4 ++-- .../Fixtures/Commandant.json | 2 -- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1353cf15..a7b79d072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ None. [JP Simard](https://github.com/jpsim) [jazzy#374](https://github.com/realm/jazzy/issues/374) +* Fix issue where Swift extensions would pick up documentation from previous + tokens. + [JP Simard](https://github.com/jpsim) + [#65](https://github.com/jpsim/SourceKitten/issues/65) + ## 0.6.1 diff --git a/Source/SourceKittenFramework/File.swift b/Source/SourceKittenFramework/File.swift index 6a7bba44a..ab382b2df 100644 --- a/Source/SourceKittenFramework/File.swift +++ b/Source/SourceKittenFramework/File.swift @@ -309,6 +309,11 @@ public struct File { public func getDocumentationCommentBody(dictionary: XPCDictionary, syntaxMap: SyntaxMap) -> String? { return SwiftDocKey.getOffset(dictionary).flatMap { offset in return syntaxMap.commentRangeBeforeOffset(Int(offset)).flatMap { commentByteRange in + let commentEndLine = (contents as NSString).lineAndCharacterForCharacterOffset(commentByteRange.endIndex)?.line + let tokenStartLine = (contents as NSString).lineAndCharacterForCharacterOffset(Int(offset))?.line + guard commentEndLine == tokenStartLine else { + return nil + } return contents.byteRangeToNSRange(start: commentByteRange.startIndex, length: commentByteRange.endIndex - commentByteRange.startIndex).flatMap { nsRange in return contents.commentBody(nsRange) } diff --git a/Source/SourceKittenFramework/String+SourceKitten.swift b/Source/SourceKittenFramework/String+SourceKitten.swift index 78c6a9605..7cab70a91 100644 --- a/Source/SourceKittenFramework/String+SourceKitten.swift +++ b/Source/SourceKittenFramework/String+SourceKitten.swift @@ -57,6 +57,21 @@ extension NSString { return nil } + public func lineAndCharacterForCharacterOffset(offset: Int) -> (line: Int, character: Int)? { + let range = NSRange(location: offset, length: 0) + var numberOfLines = 0, index = 0, lineRangeStart = 0, previousIndex = 0 + while index < length { + numberOfLines++ + if index > range.location { + break + } + lineRangeStart = numberOfLines + previousIndex = index + index = NSMaxRange(lineRangeForRange(NSRange(location: index, length: 1))) + } + return (lineRangeStart, range.location - previousIndex + 1) + } + /** Returns a copy of `self` with the trailing contiguous characters belonging to `characterSet` removed. diff --git a/Source/SourceKittenFramework/SyntaxKind.swift b/Source/SourceKittenFramework/SyntaxKind.swift index ababd32d6..5f70cd9f7 100644 --- a/Source/SourceKittenFramework/SyntaxKind.swift +++ b/Source/SourceKittenFramework/SyntaxKind.swift @@ -48,12 +48,8 @@ public enum SyntaxKind: String { /// `typeidentifier`. case Typeidentifier = "source.lang.swift.syntaxtype.typeidentifier" - /** - Returns true if the input is a comment-like syntax kind string. - - - parameter string: Input string. - */ - internal static func isCommentLike(string: Swift.String) -> Bool { - return [Comment, CommentMark, CommentURL, DocComment, DocCommentField].map({ $0.rawValue }).contains(string) + /// Returns the valid documentation comment syntax kinds. + internal static func docComments() -> [SyntaxKind] { + return [CommentURL, DocComment, DocCommentField] } } diff --git a/Source/SourceKittenFramework/SyntaxMap.swift b/Source/SourceKittenFramework/SyntaxMap.swift index 462439cd0..34b5e9747 100644 --- a/Source/SourceKittenFramework/SyntaxMap.swift +++ b/Source/SourceKittenFramework/SyntaxMap.swift @@ -73,8 +73,8 @@ public struct SyntaxMap { */ public func commentRangeBeforeOffset(offset: Int) -> Range? { let tokensBeforeOffset = tokens.filter { $0.offset < offset } - let commentTokensImmediatelyPrecedingOffset = filterLastContiguous(tokensBeforeOffset) { - SyntaxKind.isCommentLike($0.type) + let commentTokensImmediatelyPrecedingOffset = filterLastContiguous(tokensBeforeOffset) { token in + SyntaxKind.docComments().map({$0.rawValue}).contains(token.type) } return commentTokensImmediatelyPrecedingOffset.first.flatMap { firstToken in return commentTokensImmediatelyPrecedingOffset.last.map { lastToken in diff --git a/Source/SourceKittenFrameworkTests/Fixtures/Commandant.json b/Source/SourceKittenFrameworkTests/Fixtures/Commandant.json index 3c6866fba..36b60126d 100644 --- a/Source/SourceKittenFrameworkTests/Fixtures/Commandant.json +++ b/Source/SourceKittenFrameworkTests/Fixtures/Commandant.json @@ -730,7 +730,6 @@ { "key.kind" : "source.lang.swift.decl.extension", "key.offset" : 3535, - "key.doc.comment" : "Attempts to parse a value from the given command-line argument.", "key.namelength" : 3, "key.bodyoffset" : 3564, "key.bodylength" : 119, @@ -811,7 +810,6 @@ { "key.kind" : "source.lang.swift.decl.extension", "key.offset" : 3686, - "key.doc.comment" : "Attempts to parse a value from the given command-line argument.", "key.modulename" : "Swift", "key.namelength" : 6, "key.bodyoffset" : 3718,