Skip to content

Commit 53e5cb9

Browse files
pdwilson12Peter Wilson
andauthored
Add new typeDetails symbol mixin to hold type details of weakly-typed dictionary keys and HTTP parameters. (#56)
Co-authored-by: Peter Wilson <[email protected]>
1 parent ccbbd88 commit 53e5cb9

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

Sources/SymbolKit/SymbolGraph/Symbol/Symbol.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ extension SymbolGraph.Symbol {
232232
static let maximumLength = MaximumLength.symbolCodingInfo
233233
static let allowedValues = AllowedValues.symbolCodingInfo
234234
static let defaultValue = DefaultValue.symbolCodingInfo
235+
static let typeDetails = TypeDetails.symbolCodingInfo
235236
static let httpEndpoint = HTTP.Endpoint.symbolCodingInfo
236237
static let httpParameterSource = HTTP.ParameterSource.symbolCodingInfo
237238
static let httpMediaType = HTTP.MediaType.symbolCodingInfo
@@ -255,6 +256,7 @@ extension SymbolGraph.Symbol {
255256
CodingKeys.maximumLength.codingKey.stringValue: Self.maximumLength,
256257
CodingKeys.allowedValues.codingKey.stringValue: Self.allowedValues,
257258
CodingKeys.defaultValue.codingKey.stringValue: Self.defaultValue,
259+
CodingKeys.typeDetails.codingKey.stringValue: Self.typeDetails,
258260
CodingKeys.httpEndpoint.codingKey.stringValue: Self.httpEndpoint,
259261
CodingKeys.httpParameterSource.codingKey.stringValue: Self.httpParameterSource,
260262
CodingKeys.httpMediaType.codingKey.stringValue: Self.httpMediaType,

Sources/SymbolKit/SymbolGraph/Symbol/ValueConstraints.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,58 @@ extension SymbolGraph.Symbol {
124124
public init(_ value: ValueType) {
125125
self.value = value
126126
}
127+
128+
// Need custom init(from:) to special case `null` value.
129+
public init(from decoder: Decoder) throws {
130+
let container = try decoder.singleValueContainer()
131+
if container.decodeNil() {
132+
self.init(.null)
133+
return
134+
}
135+
self.init(try container.decode(ValueType.self))
136+
}
127137
}
128138

129139
public var defaultValue : SymbolGraph.AnyScalar? {
130140
(mixins[DefaultValue.mixinKey] as? DefaultValue)?.value
131141
}
142+
143+
/// A detailed description of the set of types allowed for a parameter or key.
144+
///
145+
/// Weakly-typed data structures, such as JSON, can allow a field to hold a value from a set of types,
146+
/// rather than being of a singular fixed type.
147+
/// For example, a time could be specified as an integer number of seconds from an epoch (eg, 1234)
148+
/// or a time stamp string ("12:34pm"). A client can detect the different types and interpret them accordingly.
149+
/// Whereas ``DeclarationFragments`` represents the declaration of the whole entity,
150+
/// each ``TypeDetail`` member provides information, including the declaration, about the individual allowed types.
151+
public struct TypeDetails: SingleValueMixin {
152+
public static let mixinKey = "typeDetails"
153+
public typealias ValueType = [TypeDetail]
154+
public var value: ValueType
155+
public init(_ value: ValueType) {
156+
self.value = value
157+
}
158+
}
159+
160+
public var typeDetails : [TypeDetail]? {
161+
(mixins[TypeDetails.mixinKey] as? TypeDetails)?.value
162+
}
163+
164+
/// Detailed description of one of the types allowed for a weakly-typed parameter or key.
165+
public struct TypeDetail: Codable {
166+
/// The declaration of this individual type.
167+
public var fragments: [DeclarationFragments.Fragment]?
168+
169+
/// The primitive type of this type, such as "string", "integer", or "dictionary".
170+
public var baseType: String?
171+
172+
/// Whether the value for this type is actually an array of values.
173+
public var arrayMode: Bool?
174+
175+
public init(fragments: [DeclarationFragments.Fragment]? = nil, baseType: String? = nil, arrayMode: Bool? = nil) {
176+
self.fragments = fragments
177+
self.baseType = baseType
178+
self.arrayMode = arrayMode
179+
}
180+
}
132181
}

Tests/SymbolKitTests/SymbolGraph/Symbol/ValueConstraintsTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class ValueConstraintsTests: XCTestCase {
3232
"maximum": 3.5,
3333
"default": "str",
3434
"allowedValues": ["a", 1, null],
35+
"typeDetails": [
36+
{ "baseType": "integer", "arrayMode": false, "fragments": [{"kind": "text", "spelling": "integer"}] }
37+
]
3538
}
3639
""".data(using: .utf8)
3740

@@ -47,6 +50,13 @@ class ValueConstraintsTests: XCTestCase {
4750
XCTAssertEqual(allowedValues[0], .string("a"))
4851
XCTAssertEqual(allowedValues[1], .integer(1))
4952
XCTAssertEqual(allowedValues[2], .null)
53+
54+
let typeDetails = try XCTUnwrap(symbol.typeDetails)
55+
XCTAssertEqual(typeDetails.count, 1)
56+
XCTAssertEqual(typeDetails[0].baseType, "integer")
57+
XCTAssertEqual(typeDetails[0].arrayMode, false)
58+
XCTAssertEqual(typeDetails[0].fragments?.count, 1)
59+
XCTAssertEqual(typeDetails[0].fragments?[0].spelling, "integer")
5060
}
5161
}
5262

0 commit comments

Comments
 (0)