Exploring
// | |
// explore.swift | |
// CmdLineTest | |
// | |
// Created by Erica Sadun on 6/25/14. | |
// Copyright (c) 2014 Erica Sadun. All rights reserved. | |
// | |
import Foundation | |
func QLString(x : QuickLookObject) -> String { | |
switch x { | |
case .Text(let s) : return "Text: " + s | |
case .Int(let i) : return "Int: " + "\(i)" | |
case .UInt(let u) : return "UInt: " + "\(u)" | |
case .Float(let f) : return "Float: " + "\(f)" | |
case .Image(let img) : return "Image: " + "[image]" | |
case .Sound(let snd) : return "Sound: " + "[sound]" | |
case .Color(let color) : return "Color: " + "\(color)" | |
case .BezierPath(let path) : return "Bezier: " + "[bezier]" | |
case .AttributedString(let s) : return "Attributed String: " + "\(s)" | |
case .Rectangle(let x, let y, let w, let h) : return "Rect: " + "[\(x), \(y), \(w), \(h)]" | |
case .Point(let x, let y) : return "Point: " + "(\(x), \(y))" | |
case .Size(let w, let h) : return "Size: " + "\(w), \(h)" | |
case .Logical(let v) : return v ? "Bool: " + "true" : "false" | |
case .Range(let a, let b) : return "Range: " + "\(a)..<\(b)" | |
case .View(let v) : return "View: " + "\(v)" | |
case .Sprite(let s) : return "Sprite: " + "[sprite]" | |
case .URL(let u) : return "URL: " + "\(u)" | |
default: return "<Unknown>" | |
} | |
} | |
func DispositionString(disposition : MirrorDisposition) -> String { | |
switch disposition { | |
case .Aggregate: return "Aggregate" | |
case .Class: return "Class" | |
case .Container: return "Container" | |
case .Enum: return "Enum" | |
case .IndexContainer : return "Index Container (Array)" | |
case .KeyContainer : return "Key Container (Dict)" | |
case .MembershipContainer : return "Membership Container" | |
case .Optional : return "Optional" | |
case .Struct: return "Struct" | |
case .Tuple: return "Tuple" | |
case .ObjCObject: return "ObjC Object" | |
} | |
} | |
func DispositionString(item : Any) -> String { | |
return DispositionString(reflect(item).disposition) | |
} | |
// Adapted from https://gist.github.com/mprudhom/69ec96f3d95c3d080e6a | |
// No where near complete. See https://www.mikeash.com/pyblog/friday-qa-2014-08-15-swift-name-mangling.html | |
func TypeDemangler(mangled: String) -> String { | |
if (!mangled.hasPrefix("_T")) {return mangled} | |
let scanner = NSScanner(string: mangled) | |
if (!scanner.scanString("_TtC", intoString: nil) && | |
!scanner.scanString("_TtV", intoString: nil)) { | |
return mangled | |
} | |
var demangled = "" | |
var len : Int = 0 | |
while (!scanner.atEnd && scanner.scanInteger(&len)) { | |
let range = Range(start:advance(mangled.startIndex, scanner.scanLocation), end: advance(mangled.startIndex, scanner.scanLocation + len)) | |
let part = mangled.substringWithRange(range) | |
if (countElements(demangled) > 0) { | |
demangled += "." | |
} | |
demangled += part | |
scanner.scanLocation += len | |
} | |
return demangled | |
} | |
extension NSObject { | |
class func demangledClassName() -> String { | |
return TypeDemangler(NSStringFromClass(self.dynamicType) as String) | |
} | |
} | |
func typestring(x : Any) -> String { | |
if let obj = x as? NSObject { | |
return TypeDemangler(NSStringFromClass(obj.dynamicType) as String) | |
} | |
// Value types | |
switch x { | |
// case let test as Array: return "Array" | |
// case let test as AssertString : return "AssertString" | |
// case let test as AutoreleasingUnsafeMutablePointer: return "AutoreleasingUnsafeMutablePointer" | |
// case let test as BidirectionalReverseView: return "" | |
case let test as Bool: return "Bool" | |
// case let test as CFunctionPointer: return "CFunctionPointer" | |
case let test as COpaquePointer : return "COpaquePointer" | |
case let test as CVaListPointer : return "CVaListPointer" | |
// case let test as ClosedInterval: return "ClosedInterval" | |
// case let test as CollectionOfOne: return "CollectionOfOne" | |
// case let test as ContiguousArray: return "ContiguousArray" | |
// case let test as Dictionary: return "Dictionary" | |
// case let test as DictionaryGenerator: return "DictionaryGenerator" | |
// case let test as DictionaryIndex: return "DictionaryIndex" | |
case let test as Double: return "Double" | |
// case let test as EmptyCollection: return "EmptyCollection" | |
// case let test as EmptyGenerator: return "EmptyGenerator" | |
// case let test as EnumerateGenerator: return "EnumerateGenerator" | |
// case let test as FilterCollectionView: return "FilterCollectionView" | |
// case let test as FilterCollectionViewIndex: return "FilterCollectionViewIndex" | |
// case let test as FilterGenerator: return "FilterGenerator" | |
// case let test as FilterSequenceView: return "FilterSequenceView" | |
case let test as Float : return "Float" | |
// case let test as Float80 : return "Float80" | |
// case let test as GeneratorOf: return "GeneratorOf" | |
// case let test as GeneratorOfOne: return "GeneratorOfOne" | |
// case let test as GeneratorSequence: return "GeneratorSequence" | |
// case let test as HalfOpenInterval: return "HalfOpenInterval" | |
// case let test as HeapBuffer: return "HeapBuffer" | |
// case let test as IndexingGenerator: return "IndexingGenerator" | |
case let test as Int : return "Int" | |
case let test as Int16 : return "Int16" | |
case let test as Int32 : return "Int32" | |
case let test as Int64 : return "Int64" | |
case let test as Int8 : return "Int8" | |
// case let test as LazyBidirectionalCollection: return "LazyBidirectionalCollection" | |
// case let test as LazyForwardCollection: return "LazyForwardCollection" | |
// case let test as LazyRandomAccessCollection: return "LazyRandomAccessCollection" | |
// case let test as LazySequence: return "LazySequence" | |
// case let test as MapCollectionView: return "MapCollectionView" | |
// case let test as MapSequenceGenerator: return "MapSequenceGenerator" | |
// case let test as MapSequenceView: return "MapSequenceView" | |
case let test as ObjectIdentifier : return "ObjectIdentifier" | |
// case let test as OnHeap: return "OnHeap" | |
// case let test as PermutationGenerator: return "PermutationGenerator" | |
// case let test as RandomAccessReverseView: return "RandomAccessReverseView" | |
// case let test as Range: return "Range" | |
// case let test as RangeGenerator: return "RangeGenerator" | |
case let test as RawByte : return "RawByte" | |
// case let test as Repeat: return "Repeat" | |
// case let test as ReverseBidirectionalIndex: return "ReverseBidirectionalIndex" | |
// case let test as ReverseRandomAccessIndex: return "ReverseRandomAccessIndex" | |
// case let test as SequenceOf: return "SequenceOf" | |
// case let test as SinkOf: return "SinkOf" | |
// case let test as Slice: return "Slice" | |
case let test as StaticString : return "StaticString" | |
// case let test as StrideThrough: return "StrideThrough" | |
// case let test as StrideThroughGenerator: return "StrideThroughGenerator" | |
// case let test as StrideTo: return "StrideTo" | |
// case let test as StrideToGenerator: return "StrideToGenerator" | |
case let test as String : return "String" | |
case let test as String.Index: return "String.Index" | |
case let test as String.UTF8View: return "String.UTF8View" | |
case let test as String.UnicodeScalarView: return "String.UnicodeScalarView" | |
case let test as String.UTF16View: return "String.UTF16View" | |
case let test as UInt : return "UInt" | |
case let test as UInt16 : return "UInt16" | |
case let test as UInt32 : return "UInt32" | |
case let test as UInt64 : return "UInt64" | |
case let test as UInt8 : return "UInt8" | |
case let test as UTF16 : return "UTF16" | |
case let test as UTF32 : return "UTF32" | |
case let test as UTF8 : return "UTF8" | |
case let test as UnicodeScalar : return "UnicodeScalar" | |
// case let test as Unmanaged: return "Unmanaged" | |
// case let test as UnsafeBufferPointer: return "UnsafeBufferPointer" | |
// case let test as UnsafeBufferPointerGenerator: return "UnsafeBufferPointerGenerator" | |
// case let test as UnsafeMutableBufferPointer: return "UnsafeMutableBufferPointer" | |
// case let test as UnsafeMutablePointer: return "UnsafeMutablePointer" | |
// case let test as UnsafePointer: return "UnsafePointer" | |
// case let test as Zip2: return "Zip2" | |
// case let test as ZipGenerator2: return "ZipGenerator2" | |
default: break | |
} | |
switch x { | |
case let test as [Double]: return "[Double]" | |
case let test as [Int]: return "[Int]" | |
case let test as [Bool]: return "[Bool]" | |
case let test as [String]: return "[String]" | |
default: break | |
} | |
return _stdlib_demangleName(_stdlib_getTypeName(x)) | |
} | |
func TupleDisposition(mirror : MirrorType) -> String { | |
if (mirror.disposition != .Tuple) {return ""} | |
var array = [String]() | |
for reference in 0..<mirror.count { | |
let (name, referenceMirror) = mirror[reference] | |
array += [typestring(referenceMirror.value)] | |
} | |
return array.reduce(""){"\($0),\($1)"} | |
// return NSArray(array:array).componentsJoinedByString(", ") as String | |
} | |
func ExploreItem(mirror : MirrorType, _ indent:Int = 0) { | |
var indentString = ""; indentString.extend(Repeat(count: indent * 4, repeatedValue:" " as Character)) | |
let rs = "" | |
var ts = typestring(mirror.value) | |
if (mirror.disposition == .Tuple) { | |
ts = TupleDisposition(mirror) | |
} | |
print("\(indentString)Item: "); dump(mirror.value) | |
if let qlobject = mirror.quickLookObject { | |
let qlstring = QLString(qlobject) | |
println("\(indentString)QuickLook: \(qlstring)\(rs)") | |
} | |
println("\(indentString)Disposition: \(DispositionString(mirror.disposition)) [\(ts)]\(rs)") | |
if let identifier = mirror.objectIdentifier { | |
println("\(indentString)Identifier: \(mirror.objectIdentifier)\(rs)") | |
} | |
println("\(indentString)ValueType: \(mirror.valueType)\(rs)") | |
println("\(indentString)Value: \(mirror.value)\(rs)") | |
println("\(indentString)Summary: \(mirror.summary)\(rs)") | |
if (mirror.count == 0) {return} | |
println("\(indentString)Subreferences: \(mirror.count) children\(rs)") | |
// All the rest is broken in beat 4, 5 | |
// dump(mirror) // broken in beta 4, 5 for multi-kids | |
for reference in 0..<mirror.count { | |
let (name, subreference) = mirror[reference] | |
println("\(indentString)Element Name: \(name)\(rs)") | |
ExploreItem(subreference, indent + 4) | |
} | |
} | |
func ExploreItem<T>(item : T) { | |
println("---------------------") | |
println("Exploring \(item)") | |
println("---------------------") | |
ExploreItem(reflect(item), 0) | |
} | |
postfix operator <*> {} | |
postfix func <*> (item : Any) { | |
ExploreItem(item) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
lilyball commentedJun 24, 2014
func _stdlib_getTypeName<T>(value: T) -> String
returns the mangled name for a value. You could passx
to that intypestring()
instead of returning"<Unknown>"
.