Skip to content

Commit

Permalink
#76, copy fields support, part 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
ajvincent committed Mar 1, 2024
1 parent a33c5e6 commit 4394ebd
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 63 deletions.
2 changes: 2 additions & 0 deletions stage_3_generation/build/decorators/createDecorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ async function buildDecorator(
const typeToClass = new MemberedTypeToClass([], router);
typeToClass.importFromTypeMembersMap(false, interfaceMembers);

typeToClass.addTypeMember(true, module.createCopyFieldsMethod())

typeToClass.defineStatementsByPurpose("body", false);
module.classMembersMap = typeToClass.buildClassMembersMap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@ import type {

import {
ClassFieldStatementsMap,
IntersectionTypeStructureImpl,
LiteralTypeStructureImpl,
MemberedStatementsKey,
type MemberedTypeToClass,
MethodSignatureImpl,
ParameterDeclarationImpl,
type PropertySignatureImpl,
TypeStructureKind,
type TypeStructures,
Expand All @@ -27,69 +23,30 @@ import {
type stringOrWriterFunction,
} from "#stage_two/snapshot/source/exports.js";

/*
import {
getStructureNameFromModified,
} from "#utilities/source/StructureNameTransforms.js";
*/

import TS_MORPH_D from "#utilities/source/ts-morph-d-file.js";

import InternalJSDocTag from "../classTools/InternalJSDocTag.js";
import PropertyHashesWithTypes from "../classTools/PropertyHashesWithTypes.js";

import GetterFilter from "../fieldStatements/GetterFilter.js";

import {
DecoratorModule,
} from "../../moduleClasses/exports.js";

import BlockStatement from "../../pseudoStatements/BlockStatement.js";
//#endregion preamble

export function addCopyFieldsMethod(
module: DecoratorModule,
typeToClass: MemberedTypeToClass
): void
{
const methodSignature = new MethodSignatureImpl("[COPY_FIELDS]");

const sourceParam = new ParameterDeclarationImpl("source");
sourceParam.typeStructure = new IntersectionTypeStructureImpl([
LiteralTypeStructureImpl.get(module.baseName),
LiteralTypeStructureImpl.get("Structures")
]);

const targetParam = new ParameterDeclarationImpl("target");
targetParam.typeStructure = new IntersectionTypeStructureImpl([
LiteralTypeStructureImpl.get(module.decoratorName),
LiteralTypeStructureImpl.get("Structures")
]);

methodSignature.docs.push(InternalJSDocTag);
methodSignature.parameters.push(sourceParam, targetParam);
methodSignature.returnTypeStructure = LiteralTypeStructureImpl.get("void");

typeToClass.addTypeMember(true, methodSignature);

module.addImports("internal", ["COPY_FIELDS"], []);
module.addImports("ts-morph", [], [
module.baseName,
"Structures"
]);
}

const booleanType = LiteralTypeStructureImpl.get("boolean");
const stringType = LiteralTypeStructureImpl.get("string");
const stringOrWriterFunction = LiteralTypeStructureImpl.get("stringOrWriterFunction");

export class CopyFieldsStatements extends GetterFilter
export default class CopyFieldsStatements extends GetterFilter
{
accept(
key: MemberedStatementsKey
): boolean
{
if (key.isFieldStatic === false)
if (key.isFieldStatic === true)
return false;
if (key.fieldKey === ClassFieldStatementsMap.FIELD_TAIL_FINAL_RETURN)
return false;
Expand All @@ -108,6 +65,10 @@ export class CopyFieldsStatements extends GetterFilter
];
}

if (/^#.*Manager$/.test(key.fieldKey)) {
return this.#getStatementsForTypeAccessor(key);
}

assert(key.fieldType?.kind === StructureKind.PropertySignature, "not a property?");
assert(key.fieldType.typeStructure, "no type structure?");

Expand All @@ -121,6 +82,31 @@ export class CopyFieldsStatements extends GetterFilter
throw new Error("unexpected field type structure: " + key.fieldType.name);
}

#getStatementsForTypeAccessor(
key: MemberedStatementsKey
): readonly stringWriterOrStatementImpl[]
{
this.module.addImports("internal", ["TypeStructureClassesMap"], []);

const propName = /^#(.*)Manager$/.exec(key.fieldKey)![1];
const structureName = propName + "Structure";

return [
`const { ${structureName }} = source as unknown as ${this.module.decoratorName};`,

new BlockStatement(
[`target.${structureName} = TypeStructureClassesMap.clone(${structureName});`],
`if (${structureName})`
).writerFunction,

new BlockStatement(
[`target.${propName} = source.${propName};`],
`else if (source.${propName})`
).writerFunction,
];
}

//#region literal type
#getStatementsForLiteralType(
fieldType: ReadonlyDeep<PropertySignatureImpl>,
typeStructure: ReadonlyDeep<LiteralTypeStructureImpl>
Expand All @@ -146,17 +132,19 @@ export class CopyFieldsStatements extends GetterFilter
return this.#getCopyTypeStatements(fieldType.name);
}

const originalField = this.#getOriginalField(fieldType.name);

switch (typeStructure) {
case booleanType:
statement = this.#getAssignmentStatement(fieldType.name);
if (fieldType.hasQuestionToken) {
if (originalField.hasQuestionToken) {
statement += " ?? false";
}
return [statement];

case stringType:
statement = `target.${fieldType.name} = source.${fieldType.name}`;
if (fieldType.hasQuestionToken) {
if (originalField.hasQuestionToken) {
statement += ` ?? ""`;
}
return [statement];
Expand All @@ -177,7 +165,7 @@ export class CopyFieldsStatements extends GetterFilter
body: string,
): WriterFunction
{
return new BlockStatement([body], `if (${name})`).writerFunction;
return new BlockStatement([body], `if (source.${name})`).writerFunction;
}

#getCopyTypeStatements(
Expand All @@ -188,29 +176,29 @@ export class CopyFieldsStatements extends GetterFilter
this.module.addImports("internal", ["TypeStructureClassesMap"], []);
return [
`const { ${name_Structure} } = source as unknown as ${this.baseName}Mixin;`,

new BlockStatement(
[`target.${name_Structure} = TypeStructureClassesMap.clone(${name_Structure});`],
`if (${name_Structure})`
).writerFunction,

new BlockStatement(
[`target.${name} = source.${name}`],
`else if (source.${name})`
).writerFunction,
];
}
//#endregion literal type

#getStatementsForArrayType(
fieldType: ReadonlyDeep<PropertySignatureImpl>,
objectType: ReadonlyDeep<TypeStructures>
): readonly stringOrWriterFunction[]
{
void(fieldType);
void(objectType);
return [];
/*
const { name } = fieldType;

const originalType = this.#getOriginalType(name);
const originalField = this.#getOriginalField(name);
void(originalField);

if (objectType.kind === TypeStructureKind.Parentheses)
objectType = objectType.childTypes[0];
Expand Down Expand Up @@ -238,6 +226,8 @@ export class CopyFieldsStatements extends GetterFilter
useStructureClassesMap = true;
}
}

void(includesString);
// DecoratableNodeStructureMixin
// JSDocableNodeStructureMixin
// ParameteredNodeStructureMixin
Expand All @@ -246,24 +236,23 @@ export class CopyFieldsStatements extends GetterFilter
// TypeParameteredNodeStructureMixin

if (useStructureClassesMap) {
} else {
return [
`target.${name} = source.${name}?.slice() ?? [];`
]
return [];
}
*/

return [
`target.${name} = source.${name}?.slice() ?? [];`
];
}

#getOriginalType(
#getOriginalField(
propertyName: string
): TypeStructures
): PropertySignatureImpl
{
return getTypeAugmentedStructure(
TS_MORPH_D.getInterfaceOrThrow(this.baseName).getPropertyOrThrow(propertyName),
VoidTypeNodeToTypeStructureConsole,
true,
StructureKind.PropertySignature
).rootStructure.typeStructure!
).rootStructure;
}
}
6 changes: 5 additions & 1 deletion stage_3_generation/build/fieldStatements/StatementsRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import {
stringWriterOrStatementImpl
} from "#stage_two/snapshot/source/exports.js";

import DecoratorModule from "../../moduleClasses/DecoratorModule.js";
import {
DecoratorModule,
} from "../../moduleClasses/exports.js";

import StatementGetterBase from "./GetterBase.js";
import GetterFilter from "./GetterFilter.js";

import ArrayBooleanAndString from "./ArrayBooleanAndString.js";
import CopyFieldsStatements from "./CopyFields.js";

export default
class StatementsRouter extends StatementGetterBase
Expand All @@ -22,6 +25,7 @@ class StatementsRouter extends StatementGetterBase
super(module);
this.filters = [
new ArrayBooleanAndString(module),
new CopyFieldsStatements(module),
];
}

Expand Down
7 changes: 7 additions & 0 deletions stage_3_generation/build/publicAndInternalExports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ function definePublicExports(): void
isDefaultExport: false,
isType: true
});

publicExports.addExports({
pathToExportedModule: pathToModule(distDir, "source/types/stringOrWriterFunction.d.ts"),
exportNames: ["stringOrWriterFunction"],
isDefaultExport: false,
isType: true
});
}

function defineInternalExports(): void
Expand Down
33 changes: 33 additions & 0 deletions stage_3_generation/moduleClasses/DecoratorModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {
ClassDeclarationImpl,
FunctionDeclarationImpl,
IndexedAccessTypeStructureImpl,
IntersectionTypeStructureImpl,
LiteralTypeStructureImpl,
MemberedObjectTypeStructureImpl,
MethodSignatureImpl,
ParameterDeclarationImpl,
PrefixOperatorsTypeStructureImpl,
PropertySignatureImpl,
Expand All @@ -24,6 +26,8 @@ import {
getStructureMixinName,
} from "#utilities/source/StructureNameTransforms.js";

import InternalJSDocTag from "../build/classTools/InternalJSDocTag.js";

import SatisfiesStatement from "../pseudoStatements/SatisfiesStatement.js";

import BaseClassModule from "./BaseClassModule.js";
Expand Down Expand Up @@ -80,6 +84,35 @@ class DecoratorModule extends BaseClassModule
return this.baseName + "Fields"
}

createCopyFieldsMethod(): MethodSignatureImpl
{
const methodSignature = new MethodSignatureImpl("[COPY_FIELDS]");

const sourceParam = new ParameterDeclarationImpl("source");
sourceParam.typeStructure = new IntersectionTypeStructureImpl([
LiteralTypeStructureImpl.get(this.baseName),
LiteralTypeStructureImpl.get("Structures")
]);

const targetParam = new ParameterDeclarationImpl("target");
targetParam.typeStructure = new IntersectionTypeStructureImpl([
LiteralTypeStructureImpl.get(this.decoratorName),
LiteralTypeStructureImpl.get("Structures")
]);

methodSignature.docs.push(InternalJSDocTag);
methodSignature.parameters.push(sourceParam, targetParam);
methodSignature.returnTypeStructure = LiteralTypeStructureImpl.get("void");

this.addImports("internal", ["COPY_FIELDS"], []);
this.addImports("ts-morph", [], [
this.baseName,
"Structures"
]);

return methodSignature;
}

protected getSourceFileImpl(): SourceFileImpl
{
const sourceFile = new SourceFileImpl;
Expand Down
5 changes: 5 additions & 0 deletions stage_3_generation/moduleClasses/addImportsToModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import {
} from "#utilities/source/StructureNameTransforms.js";

import BaseModule from "./BaseModule.js";
import DecoratorModule from "./DecoratorModule.js";

export default function addImportsToModule(
module: BaseModule,
structure: StructureImpls | TypeStructures,
): void
{
if (structure.kind === TypeStructureKind.Literal) {

if ((module instanceof DecoratorModule) && (module.decoratorName === structure.stringValue))
return;

const rawName = getStructureNameFromModified(structure.stringValue);
switch (rawName) {
case "JsxNamespacedNameStructure":
Expand Down
Loading

0 comments on commit 4394ebd

Please sign in to comment.