@@ -0,0 +1,123 @@
1+//
2+// SourceKittenResponse.swift
3+// SourceDocsSwift
4+//
5+// Created by Ilya Kos on 8/22/18.
6+// Copyright © 2018 Ilya Kos. All rights reserved.
7+//
8+
9+import Foundation
10+
11+struct SourceKittenResponse: Decodable {
12+
13+ private enum CodingKeys: String, CodingKey {
14+ case objects = "key.substructure"
15+ }
16+
17+ var objects: [Object]
18+}
19+
20+struct Object: Decodable {
21+ let type: ObjectType
22+ let name: String
23+ /// This is a documented field
24+ let declaration: String
25+ let documentation: String?
26+ let methods: [Subobject]
27+ let fields: [Subobject]
28+
29+ private enum CodingKeys: String, CodingKey {
30+ case name = "key.name"
31+ case declaration = "key.parsed_declaration"
32+ case documenatation = "key.doc.comment"
33+ case type = "key.kind"
34+ case subobjects = "key.substructure"
35+ }
36+
37+ init(from decoder: Decoder) throws {
38+ let container = try decoder.container(keyedBy: CodingKeys.self)
39+ let typeString = try container.decodeIfPresent(String.self, forKey: .type)
40+ if typeString == "source.lang.swift.decl.struct" {
41+ type = .struct
42+ } else if typeString == "source.lang.swift.decl.class" {
43+ type = .class
44+ } else {
45+ type = .other
46+ name = ""
47+ declaration = ""
48+ documentation = nil
49+ methods = []
50+ fields = []
51+ return
52+ }
53+ name = try container.decode(String.self, forKey: .name).replacingOccurrences(of: "_", with: "\\_")
54+ declaration = try container.decode(String.self, forKey: .declaration).replacingOccurrences(of: "_", with: "\\_")
55+ documentation = try container.decodeIfPresent(String.self, forKey: .documenatation)?.replacingOccurrences(of: "_", with: "\\_")
56+ let subobjects = try container.decode([Subobject].self, forKey: .subobjects)
57+ methods = subobjects.filter {$0.type == .method}
58+ fields = subobjects.filter {$0.type == .field}
59+ }
60+}
61+
62+enum ObjectType {
63+ case `class`
64+ case `struct`
65+ case other
66+}
67+
68+struct Subobject: Decodable {
69+ let type: SubobjectType
70+ let name: String
71+ let declaration: String
72+ let documentation: String?
73+ let typeName: String
74+
75+ private enum CodingKeys: String, CodingKey {
76+ case name = "key.name"
77+ case declaration = "key.parsed_declaration"
78+ case documenatation = "key.doc.comment"
79+ case type = "key.kind"
80+ case typeName = "key.typename"
81+ }
82+
83+ private static let methodKeys: Set<String> = [
84+ "source.lang.swift.decl.function.method.static",
85+ "source.lang.swift.decl.function.method.instance"
86+ ]
87+
88+ private static let fieldKeys: Set<String> = [
89+ "source.lang.swift.decl.var.instance",
90+ "source.lang.swift.decl.var.static"
91+ ]
92+
93+ init(from decoder: Decoder) throws {
94+ let container = try decoder.container(keyedBy: CodingKeys.self)
95+ let stringType = try container.decode(String.self, forKey: .type)
96+ if Subobject.methodKeys.contains(stringType) {
97+ type = .method
98+ } else if Subobject.fieldKeys.contains(stringType) {
99+ type = .field
100+ } else {
101+ type = .other
102+ name = ""
103+ declaration = ""
104+ documentation = nil
105+ typeName = ""
106+ return
107+ }
108+ name = try container.decode(String.self, forKey: .name).replacingOccurrences(of: "_", with: "\\_")
109+ declaration = try container.decode(String.self, forKey: .declaration).replacingOccurrences(of: "_", with: "\\_")
110+ documentation = try container.decodeIfPresent(String.self, forKey: .documenatation)?.replacingOccurrences(of: "_", with: "\\_")
111+ typeName = try container.decode(String.self, forKey: .typeName).replacingOccurrences(of: "_", with: "\\_")
112+ }
113+}
114+
115+enum DecodingError: Error {
116+ case DecodingError
117+}
118+
119+enum SubobjectType {
120+ case method
121+ case field
122+ case other
123+}