Unverified Commit c0ab4a7f authored by Hong Minhee's avatar Hong Minhee
Browse files

Clone

parent c2a7f943
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
import { generateDecoder, generateEncoder } from "./codec.ts";
import { generateConstructor } from "./constructor.ts";
import { generateCloner, generateConstructor } from "./constructor.ts";
import { generateFields } from "./field.ts";
import { generateInspector } from "./inspector.ts";
import { generateProperties } from "./property.ts";
@@ -50,6 +50,7 @@ async function* generateClass(
  }
  for await (const code of generateFields(typeUri, types)) yield code;
  for await (const code of generateConstructor(typeUri, types)) yield code;
  for await (const code of generateCloner(typeUri, types)) yield code;
  for await (const code of generateProperties(typeUri, types)) yield code;
  for await (const code of generateEncoder(typeUri, types)) yield code;
  for await (const code of generateDecoder(typeUri, types)) yield code;
+61 −7
Original line number Diff line number Diff line
@@ -60,7 +60,13 @@ export async function* generateConstructor(
  types: Record<string, TypeSchema>,
): AsyncIterable<string> {
  const type = types[typeUri];
  yield `constructor(values: `;
  yield `
  /**
   * Constructs a new instance of ${type.name} with the given values.
   * @param values The values to initialize the instance with.
   */
  constructor(values:
  `;
  for await (const code of generateParametersType(typeUri, types)) yield code;
  yield ") {\n";
  if (type.extends == null) {
@@ -69,12 +75,12 @@ export async function* generateConstructor(
    yield "super(values);";
  }
  for (const property of type.properties) {
    const fieldName = await getFieldName(property.uri);
    if (property.functional || property.singularAccessor) {
      yield `
        if ("${property.singularName}" in values && \
            values.${property.singularName} != null) {
          this.${await getFieldName(property.uri)} =
            [values.${property.singularName}];
          this.${fieldName} = [values.${property.singularName}];
        }
      `;
    }
@@ -82,11 +88,59 @@ export async function* generateConstructor(
      yield `
        if ("${property.pluralName}" in values && \
            values.${property.pluralName} != null) {
          this.${await getFieldName(property.uri)} =
            values.${property.pluralName};
          this.${fieldName} = values.${property.pluralName};
        }
      `;
    }
  }
  yield "}\n";
}

export async function* generateCloner(
  typeUri: string,
  types: Record<string, TypeSchema>,
): AsyncIterable<string> {
  const type = types[typeUri];
  yield `
  /**
   * Clones this instance, optionally updating it with the given values.
   * @param values The values to update the clone with.
   * @returns The cloned instance.
   */
  clone(values:
  `;
  for await (const code of generateParametersType(typeUri, types)) yield code;
  yield ` = {}): ${type.name} {\n`;
  if (type.extends == null) {
    yield `
    // @ts-ignore
    const clone: ${type.name} = new this.constructor(values);
    `;
  } else {
    yield `const clone = super.clone(values) as unknown as ${type.name};`;
  }
  for (const property of type.properties) {
    const fieldName = await getFieldName(property.uri);
    yield `clone.${fieldName} = this.${fieldName};`;
    if (property.functional || property.singularAccessor) {
      yield `
        if ("${property.singularName}" in values && \
            values.${property.singularName} != null) {
          clone.${fieldName} = [values.${property.singularName}];
        }
      `;
    }
    if (!property.functional) {
      yield `
        if ("${property.pluralName}" in values && \
            values.${property.pluralName} != null) {
          clone.${fieldName} = values.${property.pluralName};
        }
      `;
    }
  }
  yield `
    return clone;
  }
  `;
}
+27 −0
Original line number Diff line number Diff line
@@ -148,6 +148,33 @@ Deno.test("Activity.getObjects()", async () => {
  assertEquals(objects[1].name, "Second object");
});

Deno.test("Activity.clone()", async () => {
  const activity = new Activity({
    actor: new Person({
      name: "John Doe",
    }),
    object: new Object({
      name: "Test",
    }),
    name: "Test",
    summary: "Test",
  });
  const clone = activity.clone({
    object: new Object({
      name: "Modified",
    }),
    summary: "Modified",
  });
  assertEquals((await activity.getActor())?.name, "John Doe");
  assertEquals((await clone.getActor())?.name, "John Doe");
  assertEquals((await activity.getObject())?.name, "Test");
  assertEquals((await clone.getObject())?.name, "Modified");
  assertEquals(activity.name, "Test");
  assertEquals(clone.name, "Test");
  assertEquals(activity.summary, "Test");
  assertEquals(clone.summary, "Modified");
});

Deno.test("Deno.inspect(Object)", () => {
  const obj = new Object({
    id: new URL("https://example.com/"),