generateSumType function
String
generateSumType(
- SumTypeSpec spec
)
Implementation
String generateSumType(SumTypeSpec spec) => [
"// ignore_for_file: unused_element\n",
// The sum-type base class
classDecl(
abstract: true,
name: spec.sumTypeBaseName,
typeParams: spec.typeParams,
body: [
// The unsafe constructor
constructor(
isConst: true,
type: spec.sumTypeBaseName,
namedParams: [
for (final caseSpec in spec.cases)
param(name: "this.${caseSpec.name}"),
],
initializers: [
"assert(${invariant(spec.cases)})",
],
),
loadFromRecord(spec),
dumpToRecord(spec),
exhaustiveSwitch(spec: spec, implement: true),
inexhaustiveSwitch(spec: spec, implement: true),
// Equality test
"@override",
expressionFunction(
type: "bool",
name: "operator ==",
posParams: [param(type: "Object", name: "other")],
body: [
[
"other.runtimeType == runtimeType",
"other is ${spec.sumTypeName}",
for (final caseSpec in spec.cases)
"other.${caseSpec.name} == ${caseSpec.name}"
].join("&&"),
],
),
// Hash function
"@override",
getter(
type: "int",
name: "hashCode",
body: [
"var result = 17;",
for (final caseSpec in spec.cases)
"result = 37 * result + ${caseSpec.name}.hashCode;",
"return result;",
],
),
// To string conversion
"@override",
function(
type: "String",
name: "toString",
body: [
"final ctor = iswitch(",
...spec.cases
.map((caseSpec) => [
"${caseSpec.name}: ",
if (caseSpec.type.requiresPayload)
"(value) => \"${caseSpec.name}(\$value)\""
else
"() => \"${caseSpec.name}()\"",
].join())
.map(appendComma),
");",
"return \"\$runtimeType.\$ctor\";",
],
),
// Fields
for (final caseSpec in spec.cases) ...[
"@protected",
finalField(
type: "${caseSpec.type.name}?",
name: caseSpec.name,
),
],
],
),
// The read-only record-type interface
classDecl(
abstract: true,
name: spec.recordIfaceName,
typeParams: [
const TypeParamSpec(name: "Self"),
...spec.typeParams,
],
body: [
for (final caseSpec in spec.cases)
getter(
type:
"${caseSpec.type.isDirectlyRecursive ? "Self" : caseSpec.type.name}?",
name: caseSpec.name,
),
],
),
].join(" ");