Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@ export class DynamicTypeLiteralMapper {
case "map":
return this.convertMap({ map: args.typeReference, value: args.value, as: args.as });
case "named": {
const named = this.context.resolveNamedType({ typeId: args.typeReference.value });
const typeId = args.typeReference.value;
const named = this.context.resolveNamedType({ typeId });
if (named == null) {
return java.TypeLiteral.nop();
}
return this.convertNamed({
typeId,
named,
value: args.value,
as: args.as,
Expand Down Expand Up @@ -278,11 +280,13 @@ export class DynamicTypeLiteralMapper {
}

private convertNamed({
typeId,
named,
value,
as,
inUndiscriminatedUnion
}: {
typeId: string;
named: FernIr.dynamic.NamedType;
value: unknown;
as?: DynamicTypeLiteralMapper.ConvertedAs;
Expand All @@ -293,30 +297,34 @@ export class DynamicTypeLiteralMapper {
return this.convert({ typeReference: named.typeReference, value, as, inUndiscriminatedUnion });
case "discriminatedUnion":
return this.convertDiscriminatedUnion({
typeId,
discriminatedUnion: named,
value
});
case "enum":
return this.convertEnum({ enum_: named, value });
return this.convertEnum({ typeId, enum_: named, value });
case "object":
return this.convertObject({ object_: named, value, as });
return this.convertObject({ typeId, object_: named, value, as });
case "undiscriminatedUnion":
// Don't pass inUndiscriminatedUnion here - we're AT the undiscriminated union level,
// not within it. The flag should only apply to the variants within the union.
return this.convertUndiscriminatedUnion({ undiscriminatedUnion: named, value });
return this.convertUndiscriminatedUnion({ typeId, undiscriminatedUnion: named, value });
default:
assertNever(named);
}
}

private convertDiscriminatedUnion({
typeId,
discriminatedUnion,
value
}: {
typeId: string;
discriminatedUnion: FernIr.dynamic.DiscriminatedUnionType;
value: unknown;
}): java.TypeLiteral {
const classReference = this.context.getJavaClassReferenceFromDeclaration({
const classReference = this.context.getJavaClassReferenceForNamedType({
typeId,
declaration: discriminatedUnion.declaration
});
const discriminatedUnionTypeInstance = this.context.resolveDiscriminatedUnionTypeInstance({
Expand All @@ -329,8 +337,9 @@ export class DynamicTypeLiteralMapper {
const unionVariant = discriminatedUnionTypeInstance.singleDiscriminatedUnionType;
switch (unionVariant.type) {
case "samePropertiesAsObject": {
const variantTypeId = unionVariant.typeId;
const named = this.context.resolveNamedType({
typeId: unionVariant.typeId
typeId: variantTypeId
});
if (named == null) {
return java.TypeLiteral.nop();
Expand All @@ -339,7 +348,13 @@ export class DynamicTypeLiteralMapper {
java.invokeMethod({
on: classReference,
method: this.context.getPropertyName(unionVariant.discriminantValue.name),
arguments_: [this.convertNamed({ named, value: discriminatedUnionTypeInstance.value })]
arguments_: [
this.convertNamed({
typeId: variantTypeId,
named,
value: discriminatedUnionTypeInstance.value
})
]
})
);
}
Expand Down Expand Up @@ -382,10 +397,12 @@ export class DynamicTypeLiteralMapper {
}

private convertObject({
typeId,
object_,
value,
as
}: {
typeId: string;
object_: FernIr.dynamic.ObjectType;
value: unknown;
as?: DynamicTypeLiteralMapper.ConvertedAs;
Expand All @@ -399,7 +416,8 @@ export class DynamicTypeLiteralMapper {
? properties.filter((property) => !this.context.isDirectLiteral(property.typeReference))
: properties;
return java.TypeLiteral.builder({
classReference: this.context.getJavaClassReferenceFromDeclaration({
classReference: this.context.getJavaClassReferenceForNamedType({
typeId,
declaration: object_.declaration
}),
parameters: filteredProperties.map((property) => {
Expand All @@ -416,13 +434,22 @@ export class DynamicTypeLiteralMapper {
});
}

private convertEnum({ enum_, value }: { enum_: FernIr.dynamic.EnumType; value: unknown }): java.TypeLiteral {
private convertEnum({
typeId,
enum_,
value
}: {
typeId: string;
enum_: FernIr.dynamic.EnumType;
value: unknown;
}): java.TypeLiteral {
const name = this.getEnumValueName({ enum_, value });
if (name == null) {
return java.TypeLiteral.nop();
}
return java.TypeLiteral.enum_({
classReference: this.context.getJavaClassReferenceFromDeclaration({
classReference: this.context.getJavaClassReferenceForNamedType({
typeId,
declaration: enum_.declaration
}),
value: name
Expand All @@ -449,9 +476,11 @@ export class DynamicTypeLiteralMapper {
}

private convertUndiscriminatedUnion({
typeId,
undiscriminatedUnion,
value
}: {
typeId: string;
undiscriminatedUnion: FernIr.dynamic.UndiscriminatedUnionType;
value: unknown;
}): java.TypeLiteral {
Expand All @@ -462,14 +491,16 @@ export class DynamicTypeLiteralMapper {
if (result == null) {
return java.TypeLiteral.nop();
}
const classReference = this.context.getJavaClassReferenceForNamedType({
typeId,
declaration: undiscriminatedUnion.declaration
});
if (this.context.isPrimitive(result.valueTypeReference)) {
// Primitive types overload the 'of' method rather than
// defining a separate method from the type.
return java.TypeLiteral.reference(
java.invokeMethod({
on: this.context.getJavaClassReferenceFromDeclaration({
declaration: undiscriminatedUnion.declaration
}),
on: classReference,
method: "of",
arguments_: [result.typeInstantiation]
})
Expand All @@ -479,9 +510,7 @@ export class DynamicTypeLiteralMapper {
// This matches the Java SDK's generated code pattern
return java.TypeLiteral.reference(
java.invokeMethod({
on: this.context.getJavaClassReferenceFromDeclaration({
declaration: undiscriminatedUnion.declaration
}),
on: classReference,
method: "of",
arguments_: [result.typeInstantiation]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ export class DynamicTypeMapper {
);
}
case "named": {
const named = this.context.resolveNamedType({ typeId: args.typeReference.value });
const typeId = args.typeReference.value;
const named = this.context.resolveNamedType({ typeId });
if (named == null) {
return this.convertUnknown();
}
return this.convertNamed({ named });
return this.convertNamed({ typeId, named });
}
case "optional":
case "nullable": {
Expand All @@ -51,7 +52,7 @@ export class DynamicTypeMapper {
}
}

private convertNamed({ named }: { named: FernIr.dynamic.NamedType }): java.Type {
private convertNamed({ typeId, named }: { typeId: string; named: FernIr.dynamic.NamedType }): java.Type {
switch (named.type) {
case "alias":
return this.convert({ typeReference: named.typeReference });
Expand All @@ -60,9 +61,9 @@ export class DynamicTypeMapper {
case "object":
case "undiscriminatedUnion":
return java.Type.reference(
java.classReference({
name: this.context.getClassName(named.declaration.name),
packageName: this.context.getTypesPackageName(named.declaration.fernFilepath)
this.context.getJavaClassReferenceForNamedType({
typeId,
declaration: named.declaration
})
);
default:
Expand Down
11 changes: 11 additions & 0 deletions generators/java/sdk/versions.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
- version: 3.23.2
changelogEntry:
- summary: |
Fix dynamic snippets to correctly reference inline types as nested classes. When `enable-inline-types`
is configured, types are generated as nested static classes within parent types (e.g.,
`GetDiscriminatedUnionRequest.Bar`). Dynamic snippets now correctly reference these nested classes
instead of trying to import them from `com.seed.object.types.*` where they don't exist.
type: fix
createdAt: "2025-12-06"
irVersion: 61

- version: 3.23.1
changelogEntry:
- summary: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,8 @@ exports[`dependencies > correctly incorporates dependencies 1`] = `
}
],
"file": null
}
},
"inline": null
},
"typeReference": {
"type": "primitive",
Expand Down Expand Up @@ -731,7 +732,8 @@ exports[`dependencies > correctly incorporates dependencies 1`] = `
"safeName": "Y"
}
}
}
},
"inline": null
},
"typeReference": {
"type": "primitive",
Expand Down Expand Up @@ -841,7 +843,8 @@ exports[`dependencies > correctly incorporates dependencies 1`] = `
"safeName": "X"
}
}
}
},
"inline": null
},
"typeReference": {
"type": "primitive",
Expand Down Expand Up @@ -917,7 +920,8 @@ exports[`dependencies > correctly incorporates dependencies 1`] = `
}
],
"file": null
}
},
"inline": null
},
"location": {
"method": "GET",
Expand Down Expand Up @@ -1249,4 +1253,4 @@ exports[`dependencies > correctly incorporates dependencies 1`] = `
}"
`;

exports[`dependencies > file dependencies 1`] = `5757723`;
exports[`dependencies > file dependencies 1`] = `5762035`;
Loading
Loading