Skip to content

Commit 600819e

Browse files
committed
Start spec'ing out the GoValueFormatter
1 parent 7d6709a commit 600819e

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

generators/go-v2/ast/src/context/AbstractGoGeneratorContext.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,105 @@ export abstract class AbstractGoGeneratorContext<
106106
return undefined;
107107
}
108108

109+
public maybeUnwrapIterable(typeReference: TypeReference): TypeReference | undefined {
110+
switch (typeReference.type) {
111+
case "container":
112+
const container = typeReference.container;
113+
switch (container.type) {
114+
case "list":
115+
return container.list;
116+
case "set":
117+
return container.set;
118+
case "optional":
119+
return this.maybeUnwrapIterable(container.optional);
120+
case "nullable":
121+
return this.maybeUnwrapIterable(container.nullable);
122+
case "literal":
123+
case "map":
124+
return undefined;
125+
default:
126+
assertNever(container);
127+
}
128+
case "named":
129+
const typeDeclaration = this.getTypeDeclarationOrThrow(typeReference.typeId).shape;
130+
switch (typeDeclaration.type) {
131+
case "alias":
132+
return this.maybeUnwrapIterable(typeDeclaration.aliasOf);
133+
case "enum":
134+
case "object":
135+
case "union":
136+
case "undiscriminatedUnion":
137+
return undefined;
138+
default:
139+
assertNever(typeDeclaration);
140+
}
141+
case "primitive":
142+
case "unknown":
143+
return undefined;
144+
default:
145+
assertNever(typeReference);
146+
}
147+
}
148+
149+
public maybeUnwrapOptionalOrNullable(typeReference: TypeReference): TypeReference | undefined {
150+
switch (typeReference.type) {
151+
case "container":
152+
const container = typeReference.container;
153+
switch (container.type) {
154+
case "optional":
155+
return container.optional;
156+
case "nullable":
157+
return container.nullable;
158+
case "list":
159+
case "set":
160+
case "literal":
161+
case "map":
162+
return undefined;
163+
default:
164+
assertNever(container);
165+
}
166+
case "named":
167+
case "primitive":
168+
case "unknown":
169+
return undefined;
170+
default:
171+
assertNever(typeReference);
172+
}
173+
}
174+
175+
/**
176+
* Returns true if the type reference needs to be dereferenced to get the
177+
* underlying type.
178+
*
179+
* Container types like lists, maps, and sets are already nil-able, so they
180+
* don't require a dereference prefix.
181+
*/
182+
public needsOptionalDereference(typeReference: TypeReference): boolean {
183+
switch (typeReference.type) {
184+
case "named":
185+
const typeDeclaration = this.getTypeDeclarationOrThrow(typeReference.typeId).shape;
186+
switch (typeDeclaration.type) {
187+
case "alias":
188+
return this.needsOptionalDereference(typeDeclaration.aliasOf);
189+
case "enum":
190+
return true;
191+
case "object":
192+
case "union":
193+
case "undiscriminatedUnion":
194+
return false;
195+
default:
196+
assertNever(typeDeclaration);
197+
}
198+
case "primitive":
199+
return true;
200+
case "container":
201+
case "unknown":
202+
return false;
203+
default:
204+
assertNever(typeReference);
205+
}
206+
}
207+
109208
public getLiteralAsString(literal: Literal): string {
110209
return literal.type === "string" ? `'${literal.string}'` : literal.boolean ? "'true'" : "'false'";
111210
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { assertNever } from "@fern-api/core-utils";
2+
3+
import { ContainerType, Literal, PrimitiveType, PrimitiveTypeV1, TypeReference } from "@fern-fern/ir-sdk/api";
4+
5+
import { go } from "../";
6+
import { TypeInstantiation } from "../ast";
7+
import { BaseGoCustomConfigSchema } from "../custom-config/BaseGoCustomConfigSchema";
8+
import { AbstractGoGeneratorContext } from "./AbstractGoGeneratorContext";
9+
10+
export declare namespace GoValueFormatter {
11+
interface Args {
12+
reference: TypeReference;
13+
value: go.AstNode;
14+
}
15+
16+
interface Result {
17+
formatted: go.AstNode;
18+
zeroValue: go.AstNode;
19+
prefix: string;
20+
suffix: string;
21+
isIterable: boolean;
22+
isOptional: boolean;
23+
isPrimitive: boolean;
24+
}
25+
}
26+
27+
export class GoValueFormatter {
28+
private context: AbstractGoGeneratorContext<BaseGoCustomConfigSchema>;
29+
30+
constructor(context: AbstractGoGeneratorContext<BaseGoCustomConfigSchema>) {
31+
this.context = context;
32+
}
33+
34+
public convert({ reference, value }: GoValueFormatter.Args): GoValueFormatter.Result {
35+
const iterableType = this.context.maybeUnwrapIterable(reference);
36+
if (iterableType != null) {
37+
const format = this.convert({ reference: iterableType, value });
38+
return {
39+
...format,
40+
isIterable: true
41+
};
42+
}
43+
44+
let prefix = "";
45+
let suffix = "";
46+
let isOptional = false;
47+
let isPrimitive = false;
48+
49+
const optionalOrNullableType = this.context.maybeUnwrapOptionalOrNullable(reference);
50+
if (optionalOrNullableType != null) {
51+
if (this.context.needsOptionalDereference(optionalOrNullableType)) {
52+
prefix = "*";
53+
}
54+
isOptional = true;
55+
}
56+
57+
// TODO: Implement the rest of the logic.
58+
return {} as any;
59+
}
60+
}

0 commit comments

Comments
 (0)