Skip to content

Commit

Permalink
Add new typeDetails symbol mixin to hold type details of weakly-typ…
Browse files Browse the repository at this point in the history
…ed dictionary keys and HTTP parameters. (#56) (#57)

Co-authored-by: Peter Wilson <pwilson@apple.com>
  • Loading branch information
pdwilson12 and Peter Wilson authored Apr 1, 2023
1 parent ccbbd88 commit d42e3db
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Sources/SymbolKit/SymbolGraph/Symbol/Symbol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ extension SymbolGraph.Symbol {
static let maximumLength = MaximumLength.symbolCodingInfo
static let allowedValues = AllowedValues.symbolCodingInfo
static let defaultValue = DefaultValue.symbolCodingInfo
static let typeDetails = TypeDetails.symbolCodingInfo
static let httpEndpoint = HTTP.Endpoint.symbolCodingInfo
static let httpParameterSource = HTTP.ParameterSource.symbolCodingInfo
static let httpMediaType = HTTP.MediaType.symbolCodingInfo
Expand All @@ -255,6 +256,7 @@ extension SymbolGraph.Symbol {
CodingKeys.maximumLength.codingKey.stringValue: Self.maximumLength,
CodingKeys.allowedValues.codingKey.stringValue: Self.allowedValues,
CodingKeys.defaultValue.codingKey.stringValue: Self.defaultValue,
CodingKeys.typeDetails.codingKey.stringValue: Self.typeDetails,
CodingKeys.httpEndpoint.codingKey.stringValue: Self.httpEndpoint,
CodingKeys.httpParameterSource.codingKey.stringValue: Self.httpParameterSource,
CodingKeys.httpMediaType.codingKey.stringValue: Self.httpMediaType,
Expand Down
49 changes: 49 additions & 0 deletions Sources/SymbolKit/SymbolGraph/Symbol/ValueConstraints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,58 @@ extension SymbolGraph.Symbol {
public init(_ value: ValueType) {
self.value = value
}

// Need custom init(from:) to special case `null` value.
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() {
self.init(.null)
return
}
self.init(try container.decode(ValueType.self))
}
}

public var defaultValue : SymbolGraph.AnyScalar? {
(mixins[DefaultValue.mixinKey] as? DefaultValue)?.value
}

/// A detailed description of the set of types allowed for a parameter or key.
///
/// Weakly-typed data structures, such as JSON, can allow a field to hold a value from a set of types,
/// rather than being of a singular fixed type.
/// For example, a time could be specified as an integer number of seconds from an epoch (eg, 1234)
/// or a time stamp string ("12:34pm"). A client can detect the different types and interpret them accordingly.
/// Whereas ``DeclarationFragments`` represents the declaration of the whole entity,
/// each ``TypeDetail`` member provides information, including the declaration, about the individual allowed types.
public struct TypeDetails: SingleValueMixin {
public static let mixinKey = "typeDetails"
public typealias ValueType = [TypeDetail]
public var value: ValueType
public init(_ value: ValueType) {
self.value = value
}
}

public var typeDetails : [TypeDetail]? {
(mixins[TypeDetails.mixinKey] as? TypeDetails)?.value
}

/// Detailed description of one of the types allowed for a weakly-typed parameter or key.
public struct TypeDetail: Codable {
/// The declaration of this individual type.
public var fragments: [DeclarationFragments.Fragment]?

/// The primitive type of this type, such as "string", "integer", or "dictionary".
public var baseType: String?

/// Whether the value for this type is actually an array of values.
public var arrayMode: Bool?

public init(fragments: [DeclarationFragments.Fragment]? = nil, baseType: String? = nil, arrayMode: Bool? = nil) {
self.fragments = fragments
self.baseType = baseType
self.arrayMode = arrayMode
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class ValueConstraintsTests: XCTestCase {
"maximum": 3.5,
"default": "str",
"allowedValues": ["a", 1, null],
"typeDetails": [
{ "baseType": "integer", "arrayMode": false, "fragments": [{"kind": "text", "spelling": "integer"}] }
]
}
""".data(using: .utf8)

Expand All @@ -47,6 +50,13 @@ class ValueConstraintsTests: XCTestCase {
XCTAssertEqual(allowedValues[0], .string("a"))
XCTAssertEqual(allowedValues[1], .integer(1))
XCTAssertEqual(allowedValues[2], .null)

let typeDetails = try XCTUnwrap(symbol.typeDetails)
XCTAssertEqual(typeDetails.count, 1)
XCTAssertEqual(typeDetails[0].baseType, "integer")
XCTAssertEqual(typeDetails[0].arrayMode, false)
XCTAssertEqual(typeDetails[0].fragments?.count, 1)
XCTAssertEqual(typeDetails[0].fragments?[0].spelling, "integer")
}
}

0 comments on commit d42e3db

Please sign in to comment.