-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Typed declarations. #112
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// Accessibility.swift | ||
// SourceKitten | ||
// | ||
// Created by Paul Young on 12/4/15. | ||
// Copyright © 2015 SourceKitten. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum Accessibility: String { | ||
case Internal = "source.lang.swift.accessibility.internal" | ||
case Private = "source.lang.swift.accessibility.private" | ||
case Public = "source.lang.swift.accessibility.public" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// | ||
// DeclarationKindType.swift | ||
// SourceKitten | ||
// | ||
// Created by Paul Young on 12/4/15. | ||
// Copyright © 2015 SourceKitten. All rights reserved. | ||
// | ||
|
||
public protocol DeclarationKindType {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// DeclarationType.swift | ||
// SourceKitten | ||
// | ||
// Created by Paul Young on 12/4/15. | ||
// Copyright © 2015 SourceKitten. All rights reserved. | ||
// | ||
|
||
public protocol DeclarationType { | ||
var language: Language { get } | ||
var kind: DeclarationKindType? { get } | ||
var location: SourceLocation { get } | ||
var extent: (start: SourceLocation, end: SourceLocation) { get } | ||
var name: String? { get } | ||
var typeName: String? { get } | ||
var usr: String? { get } | ||
var declaration: String? { get } | ||
var documentationComment: String? { get } | ||
var children: [DeclarationType] { get } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// | ||
// ObjCDeclaration.swift | ||
// SourceKitten | ||
// | ||
// Created by Paul Young on 12/4/15. | ||
// Copyright © 2015 SourceKitten. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct ObjCDeclaration: DeclarationType { | ||
public let language: Language = .Swift | ||
public let kind: ObjCDeclarationKind? // FIXME: Type 'ObjCDeclaration' does not conform to protocol 'DeclarationType' | ||
public let location: SourceLocation | ||
public let extent: (start: SourceLocation, end: SourceLocation) | ||
public let name: String? | ||
public let typeName: String? | ||
public let usr: String? | ||
public let declaration: String? | ||
public let documentationComment: String? | ||
public let children: [DeclarationType] | ||
|
||
/// Returns the USR for the auto-generated getter for this property. | ||
/// | ||
/// - warning: can only be invoked if `type == .Property`. | ||
var getterUSR: String { | ||
return generateAccessorUSR(getter: true) | ||
} | ||
|
||
/// Returns the USR for the auto-generated setter for this property. | ||
/// | ||
/// - warning: can only be invoked if `type == .Property`. | ||
var setterUSR: String { | ||
return generateAccessorUSR(getter: false) | ||
} | ||
|
||
private func generateAccessorUSR(getter getter: Bool) -> String { | ||
assert(kind == .Property) | ||
guard let usr = usr else { | ||
fatalError("Couldn't extract USR") | ||
} | ||
guard let declaration = declaration else { | ||
fatalError("Couldn't extract declaration") | ||
} | ||
let pyStartIndex = usr.rangeOfString("(py)")!.startIndex | ||
let usrPrefix = usr.substringToIndex(pyStartIndex) | ||
let fullDeclarationRange = NSRange(location: 0, length: (declaration as NSString).length) | ||
let regex = try! NSRegularExpression(pattern: getter ? "getter\\s*=\\s*(\\w+)" : "setter\\s*=\\s*(\\w+:)", options: []) | ||
let matches = regex.matchesInString(declaration, options: [], range: fullDeclarationRange) | ||
if matches.count > 0 { | ||
let accessorName = (declaration as NSString).substringWithRange(matches[0].rangeAtIndex(1)) | ||
return usrPrefix + "(im)\(accessorName)" | ||
} else if getter { | ||
return usr.stringByReplacingOccurrencesOfString("(py)", withString: "(im)") | ||
} | ||
// Setter | ||
let capitalFirstLetter = String(usr.characters[pyStartIndex.advancedBy(4)]).capitalizedString | ||
let restOfSetterName = usr.substringFromIndex(pyStartIndex.advancedBy(5)) | ||
return "\(usrPrefix)(im)set\(capitalFirstLetter)\(restOfSetterName):" | ||
} | ||
} | ||
|
||
extension ObjCDeclaration { | ||
public init?(cursor: CXCursor) { | ||
guard cursor.shouldDocument() else { | ||
return nil | ||
} | ||
kind = cursor.objCKind() | ||
extent = cursor.extent() | ||
name = cursor.name() | ||
//typeName = cursor. // FIXME: no cursor.typeName() | ||
usr = cursor.usr() | ||
declaration = cursor.declaration() | ||
documentationComment = cursor.parsedComment() // FIXME: Cannot assign value of type 'CXComment' to type 'String?' | ||
children = cursor.flatMap(ObjCDeclaration.init).rejectPropertyMethods() // FIXME: Cannot assign value of type '[ObjCDeclaration]' to type '[DeclarationType]' | ||
} | ||
} | ||
|
||
extension SequenceType where Generator.Element == ObjCDeclaration { | ||
/// Removes implicitly generated property getters & setters | ||
func rejectPropertyMethods() -> [ObjCDeclaration] { | ||
let propertyGetterSetterUSRs = filter { | ||
$0.kind == .Property | ||
}.flatMap { | ||
[$0.getterUSR, $0.setterUSR] | ||
} | ||
return filter { !propertyGetterSetterUSRs.contains($0.usr!) } | ||
} | ||
} | ||
|
||
// MARK: Hashable | ||
|
||
extension ObjCDeclaration: Hashable { | ||
public var hashValue: Int { | ||
return usr?.hashValue ?? 0 | ||
} | ||
} | ||
|
||
public func ==(lhs: ObjCDeclaration, rhs: ObjCDeclaration) -> Bool { | ||
return lhs.usr == rhs.usr && | ||
lhs.location == rhs.location | ||
} | ||
|
||
// MARK: Comparable | ||
|
||
/// A [strict total order](http://en.wikipedia.org/wiki/Total_order#Strict_total_order) | ||
/// over instances of `Self`. | ||
public func <(lhs: ObjCDeclaration, rhs: ObjCDeclaration) -> Bool { | ||
return lhs.location < rhs.location | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My intention was for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think because of the use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did this in paulyoung#1. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,3 +65,5 @@ public enum ObjCDeclarationKind: String { | |
} | ||
} | ||
} | ||
|
||
extension ObjCDeclarationKind: DeclarationKindType {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// | ||
// SwiftDeclaration.swift | ||
// SourceKitten | ||
// | ||
// Created by Paul Young on 12/4/15. | ||
// Copyright © 2015 SourceKitten. All rights reserved. | ||
// | ||
|
||
import SwiftXPC | ||
|
||
public struct SwiftDeclaration: DeclarationType { | ||
public let language: Language = .Swift | ||
public let kind: DeclarationKindType? | ||
public let location: SourceLocation | ||
public let extent: (start: SourceLocation, end: SourceLocation) | ||
public let name: String? | ||
public let typeName: String? | ||
public let usr: String? | ||
public let declaration: String? | ||
public let documentationComment: String? | ||
public let children: [DeclarationType] | ||
public let accessibility: Accessibility? | ||
} | ||
|
||
extension SwiftDeclaration { | ||
public init(dictionary: XPCDictionary) { | ||
kind = SwiftDocKey.getKind(dictionary).flatMap { SwiftDeclarationKind(rawValue: $0) } // FIXME: why doesn't .flatMap(SwiftDeclarationKind.init) work here? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sure I've done this elsewhere. Maybe it doesn't work for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, that's odd, but not a big deal. |
||
|
||
if let file = SwiftDocKey.getDocFile(dictionary), | ||
line = SwiftDocKey.getDocLine(dictionary).map({ UInt32($0) }), | ||
column = SwiftDocKey.getDocColumn(dictionary).map({ UInt32($0) }) { | ||
|
||
if let offset = SwiftDocKey.getOffset(dictionary).map({ UInt32($0) }) { | ||
location = SourceLocation(file: file, line: line, column: column, offset: offset) | ||
} | ||
|
||
if let parsedScopeStart = SwiftDocKey.getParsedScopeStart(dictionary).map({ UInt32($0) }), | ||
parsedScopeEnd = SwiftDocKey.getParsedScopeEnd(dictionary).map({ UInt32($0) }) { | ||
|
||
let start = SourceLocation.init(file: file, line: line, column: column, offset: parsedScopeStart) | ||
let end = SourceLocation.init(file: file, line: line, column: column, offset: parsedScopeEnd) | ||
extent = (start: start, end: end) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely sure that this is the right thing to do here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW |
||
|
||
name = SwiftDocKey.getName(dictionary) | ||
typeName = SwiftDocKey.getTypeName(dictionary) | ||
usr = SwiftDocKey.getUSR(dictionary) | ||
declaration = SwiftDocKey.getParsedDeclaration(dictionary) | ||
documentationComment = // FIXME | ||
children = SwiftDocKey.getSubstructure(dictionary) // FIXME: Cannot assign value of type 'XPCArray?' to type '[DeclarationType]' | ||
accessibility = // FIXME: Accessibility(rawValue: ...) | ||
} | ||
} | ||
|
||
// MARK: Hashable | ||
|
||
extension SwiftDeclaration: Hashable { | ||
public var hashValue: Int { | ||
return usr?.hashValue ?? 0 | ||
} | ||
} | ||
|
||
public func ==(lhs: SwiftDeclaration, rhs: SwiftDeclaration) -> Bool { | ||
return lhs.usr == rhs.usr && | ||
lhs.location == rhs.location | ||
} | ||
|
||
// MARK: Comparable | ||
|
||
/// A [strict total order](http://en.wikipedia.org/wiki/Total_order#Strict_total_order) | ||
/// over instances of `Self`. | ||
public func <(lhs: SwiftDeclaration, rhs: SwiftDeclaration) -> Bool { | ||
return lhs.location < rhs.location | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,17 +62,17 @@ internal enum SwiftDocKey: String { | |
case DocName = "key.doc.name" | ||
/// Parameters of documented token (XPCArray). | ||
case DocParameters = "key.doc.parameters" | ||
/// Parsed declaration (String). | ||
/// Result discussion documentation of documented token (XPCArray). | ||
case DocResultDiscussion = "key.doc.result_discussion" | ||
/// Parsed scope start (Int64). | ||
/// Type of documented token (String). | ||
case DocType = "key.doc.type" | ||
/// Parsed scope start end (Int64). | ||
/// USR of documented token (String). | ||
case USR = "key.usr" | ||
/// Result discussion documentation of documented token (XPCArray). | ||
/// Parsed declaration (String). | ||
case ParsedDeclaration = "key.parsed_declaration" | ||
/// Type of documented token (String). | ||
/// Parsed scope end (Int64). | ||
case ParsedScopeEnd = "key.parsed_scope.end" | ||
/// USR of documented token (String). | ||
/// Parsed scope start (Int64). | ||
case ParsedScopeStart = "key.parsed_scope.start" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can move this to another PR if necessary. |
||
|
||
|
||
|
@@ -166,6 +166,17 @@ internal enum SwiftDocKey: String { | |
internal static func getSubstructure(dictionary: XPCDictionary) -> XPCArray? { | ||
return get(.Substructure, dictionary) | ||
} | ||
|
||
/** | ||
Get name string from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: Name string if successful. | ||
*/ | ||
internal static func getName(dictionary: XPCDictionary) -> String? { | ||
return get(.Name, dictionary) | ||
} | ||
|
||
/** | ||
Get name offset int from dictionary. | ||
|
@@ -232,4 +243,81 @@ internal enum SwiftDocKey: String { | |
internal static func getFullXMLDocs(dictionary: XPCDictionary) -> String? { | ||
return get(.FullXMLDocs, dictionary) | ||
} | ||
|
||
/** | ||
Get USR string from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: USR string if successful. | ||
*/ | ||
internal static func getUSR(dictionary: XPCDictionary) -> String? { | ||
return get(.USR, dictionary) | ||
} | ||
|
||
/** | ||
Get parsed declaration string from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: parsed declaration string if successful. | ||
*/ | ||
internal static func getParsedDeclaration(dictionary: XPCDictionary) -> String? { | ||
return get(.ParsedDeclaration, dictionary) | ||
} | ||
|
||
/** | ||
Get parsed scope start int from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: parsed scope start int if successful. | ||
*/ | ||
internal static func getParsedScopeStart(dictionary: XPCDictionary) -> Int64? { | ||
return get(.ParsedScopeStart, dictionary) | ||
} | ||
|
||
/** | ||
Get parsed scope end int from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: parsed scope end int if successful. | ||
*/ | ||
internal static func getParsedScopeEnd(dictionary: XPCDictionary) -> Int64? { | ||
return get(.ParsedScopeEnd, dictionary) | ||
} | ||
|
||
/** | ||
Get doc file string from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: doc file string if successful. | ||
*/ | ||
internal static func getDocFile(dictionary: XPCDictionary) -> String? { | ||
return get(.DocFile, dictionary) | ||
} | ||
|
||
/** | ||
Get doc column int from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: doc column int if successful. | ||
*/ | ||
internal static func getDocColumn(dictionary: XPCDictionary) -> Int64? { | ||
return get(.DocColumn, dictionary) | ||
} | ||
|
||
/** | ||
Get doc line int from dictionary. | ||
|
||
- parameter dictionary: Dictionary to get value from. | ||
|
||
- returns: doc line int if successful. | ||
*/ | ||
internal static func getDocLine(dictionary: XPCDictionary) -> Int64? { | ||
return get(.DocLine, dictionary) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is because the expected type here
DeclarationKindType
.