Skip to content

Commit

Permalink
Fix Dart Freezed naming for nested objects
Browse files Browse the repository at this point in the history
Fixes glideapps#2660

Modify the naming convention for nested objects in Dart Freezed class generation to include the parent object name.

* **DartRenderer.ts**
  - Update `dartType` method to include the parent object name for nested objects.
  - Adjust `emitFreezedClassDefinition` and `emitClassDefinition` methods to handle the new naming convention for nested objects.
  - Modify `_emitVariables` method to use the new naming convention for nested objects.

* **parser.dart**
  - Add tests for the new functionality to ensure nested objects include the parent object name.
  - Implement `testNestedObjectNaming` function to validate the new naming convention for nested objects.

TODO:

- [ ] Make sure tests work
- [ ] Make sure this offers backwards compatibility

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/glideapps/quicktype/issues/2660?shareId=XXXX-XXXX-XXXX-XXXX).
  • Loading branch information
polvallverdu committed Nov 19, 2024
1 parent 29bb816 commit 0dc83ca
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
26 changes: 18 additions & 8 deletions packages/quicktype-core/src/language/Dart/DartRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export class DartRenderer extends ConvenienceRenderer {
this.emitLine("}");
}

protected dartType(t: Type, withIssues = false, forceNullable = false): Sourcelike {
protected dartType(t: Type, withIssues = false, forceNullable = false, parentName?: Name): Sourcelike {
const nullable =
forceNullable || (this._options.nullSafety && t.isNullable && !this._options.requiredProperties);
const withNullable = (s: Sourcelike): Sourcelike => (nullable ? [s, "?"] : s);
Expand All @@ -205,7 +205,10 @@ export class DartRenderer extends ConvenienceRenderer {
_doubleType => withNullable("double"),
_stringType => withNullable("String"),
arrayType => withNullable(["List<", this.dartType(arrayType.items, withIssues), ">"]),
classType => withNullable(this.nameForNamedType(classType)),
classType => {
const className = parentName ? [parentName, "_", this.nameForNamedType(classType)] : this.nameForNamedType(classType);
return withNullable(className);
},
mapType => withNullable(["Map<String, ", this.dartType(mapType.values, withIssues), ">"]),
enumType => withNullable(this.nameForNamedType(enumType)),
unionType => {
Expand Down Expand Up @@ -441,7 +444,7 @@ export class DartRenderer extends ConvenienceRenderer {
this.ensureBlankLine();
}

private _emitVariables(c: ClassType): void {
private _emitVariables(c: ClassType, parentName?: Name): void {
this.forEachClassProperty(c, "none", (name, jsonName, p) => {
const description = this.descriptionForClassProperty(c, jsonName);
if (description !== undefined) {
Expand All @@ -458,7 +461,7 @@ export class DartRenderer extends ConvenienceRenderer {
this.emitLine(`@JsonKey(name: "${jsonName}")`);
}

this.emitLine(this._options.finalProperties ? "final " : "", this.dartType(p.type, true), " ", name, ";");
this.emitLine(this._options.finalProperties ? "final " : "", this.dartType(p.type, true, false, parentName), " ", name, ";");
});
}

Expand Down Expand Up @@ -544,7 +547,7 @@ export class DartRenderer extends ConvenienceRenderer {
this.emitLine("};");
}

protected emitClassDefinition(c: ClassType, className: Name): void {
protected emitClassDefinition(c: ClassType, className: Name, parentName?: Name): void {
this.emitDescription(this.descriptionForType(c));
if (this._options.useHive) {
this.classCounter++;
Expand All @@ -560,7 +563,7 @@ export class DartRenderer extends ConvenienceRenderer {
if (c.getProperties().size === 0) {
this._emitEmptyConstructor(className);
} else {
this._emitVariables(c);
this._emitVariables(c, parentName);
this.ensureBlankLine();
this._emitConstructor(c, className);
}
Expand Down Expand Up @@ -601,7 +604,7 @@ export class DartRenderer extends ConvenienceRenderer {
});
}

protected emitFreezedClassDefinition(c: ClassType, className: Name): void {
protected emitFreezedClassDefinition(c: ClassType, className: Name, parentName?: Name): void {
this.emitDescription(this.descriptionForType(c));

this.emitLine("@freezed");
Expand All @@ -625,7 +628,7 @@ export class DartRenderer extends ConvenienceRenderer {
this.emitLine(`@JsonKey(name: "${jsonName}")`);
}

this.emitLine(required ? "required " : "", this.dartType(prop.type, true), " ", name, ",");
this.emitLine(required ? "required " : "", this.dartType(prop.type, true, false, parentName), " ", name, ",");
});
});
this.emitLine("}) = _", className, ";");
Expand All @@ -644,6 +647,13 @@ export class DartRenderer extends ConvenienceRenderer {
"FromJson(json);"
);
});

this.forEachClassProperty(c, "none", (name, jsonName, prop) => {
if (prop.type instanceof ClassType) {
const nestedClassName = [className, "_", this.nameForNamedType(prop.type)].join("");
this.emitFreezedClassDefinition(prop.type, nestedClassName, className);
}
});
}

protected emitEnumDefinition(e: EnumType, enumName: Name): void {
Expand Down
22 changes: 22 additions & 0 deletions test/fixtures/dart/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,25 @@ void main(List<String> arguments) async {
stdout.write(result);
});
}

void testNestedObjectNaming() {
final json = '''
{
"hello": "world",
"works": {
"yes": true,
"no": false
}
}
''';

final fasfasfsa = Fasfasfsa.fromJson(jsonDecode(json));
assert(fasfasfsa.works is Fasfasfsa_Works);
assert(fasfasfsa.works.yes == true);
assert(fasfasfsa.works.no == false);
}

void main() {
testNestedObjectNaming();
print('All tests passed.');
}

0 comments on commit 0dc83ca

Please sign in to comment.