Skip to content

Commit

Permalink
#76, decorators for stage 3, part 4.
Browse files Browse the repository at this point in the history
  • Loading branch information
ajvincent committed Feb 28, 2024
1 parent fd79c47 commit 81d0f15
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export default function modifyTypeMembersForTypeStructures(
map: TypeMembersMap
): void
{
map.arrayOfKind(StructureKind.PropertySignature).forEach(prop => convertTypeToAccessors(
baseName, prop, map
));
map.arrayOfKind(StructureKind.PropertySignature).forEach(
prop => convertTypeToAccessors(baseName, prop, map)
);
}

function convertTypeToAccessors(
Expand Down
69 changes: 50 additions & 19 deletions stage_3_generation/build/decorators/createDecorators.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import assert from "node:assert/strict";

import {
type ClassFieldStatement,
type ClassStatementsGetter,
type MemberedStatementsKey,
StructureKind
} from "ts-morph";

import {
LiteralTypeStructureImpl,
MemberedTypeToClass,
type TypeMembersMap,
} from "#stage_two/snapshot/source/exports.js";
Expand All @@ -17,11 +19,17 @@ import {
getStructureNameFromModified,
} from "#utilities/source/StructureNameTransforms.js";

import DecoratorModule from "../../moduleClasses/DecoratorModule.js";
import InterfaceModule from "../../moduleClasses/InterfaceModule.js";

import modifyTypeMembersForTypeStructures from "../classTools/modifyTypeMembersForTypeStructures.js";

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

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

export default
async function createDecorators(): Promise<void>
{
Expand All @@ -44,24 +52,47 @@ async function buildDecorator(

modifyTypeMembersForTypeStructures(name, interfaceMembers);

const typeToClass = new MemberedTypeToClass(
[],
StatementsRouter
);
const router = new StatementsRouter(module.importManager);

// mixins can't have constructors, so they can't have arguments for constructors either.
const typeToClass = new MemberedTypeToClass([], router);
typeToClass.importFromTypeMembersMap(false, interfaceMembers);

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

// eslint complains when we say isAsync: boolean = false;
module.classMembersMap.arrayOfKind(StructureKind.Property).forEach(
prop => {
if ((prop.typeStructure === booleanType) && prop.initializer) {
prop.typeStructure = undefined;
}
if ((prop.typeStructure === stringType) && prop.initializer) {
prop.typeStructure = undefined;
}
}
)

module.classMembersMap.forEach(
classMember => addImportsToModule(module, classMember)
);

internalExports.addExports({
pathToExportedModule: module.importManager.absolutePathToModule,
isDefaultExport: true,
isType: false,
exportNames: [module.defaultExportName]
});

internalExports.addExports({
pathToExportedModule: module.importManager.absolutePathToModule,
isDefaultExport: false,
isType: true,
exportNames: [module.fieldsName]
});

await module.saveFile();
}

const StatementsRouter: ClassStatementsGetter = {
getStatements(
key: MemberedStatementsKey
): ClassFieldStatement[]
{
void(key);
return [];
}
}
const booleanType = LiteralTypeStructureImpl.get("boolean");
const stringType = LiteralTypeStructureImpl.get("string");
52 changes: 52 additions & 0 deletions stage_3_generation/build/fieldStatements/ArrayBooleanAndString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import assert from "node:assert/strict";

import {
ClassFieldStatementsMap,
LiteralTypeStructureImpl,
type MemberedStatementsKey,
type stringWriterOrStatementImpl,
TypeStructureKind,
} from "#stage_two/snapshot/source/exports.js";
import { StructureKind } from "ts-morph";

import GetterFilter from "./GetterFilter.js";

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

export default
class ArrayBooleanAndString extends GetterFilter
{
accept(
key: MemberedStatementsKey
): boolean
{
if (key.statementGroupKey !== ClassFieldStatementsMap.GROUP_INITIALIZER_OR_PROPERTY)
return false;
if (key.fieldType?.kind !== StructureKind.PropertySignature)
return false;
if (key.fieldType.hasQuestionToken)
return false;

const { typeStructure } = key.fieldType;
return (
typeStructure === booleanType ||
typeStructure === stringType ||
typeStructure?.kind === TypeStructureKind.Array
);
}

getStatements(
key: MemberedStatementsKey
): stringWriterOrStatementImpl[]
{
assert(key.fieldType?.kind === StructureKind.PropertySignature);
if (key.fieldType.typeStructure === booleanType)
return ["false"];

if (key.fieldType.typeStructure === stringType)
return [`""`];

return ["[]"];
}
}
24 changes: 24 additions & 0 deletions stage_3_generation/build/fieldStatements/GetterBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type {
ClassStatementsGetter,
ImportManager,
MemberedStatementsKey,
stringWriterOrStatementImpl,
} from "#stage_two/snapshot/source/exports.js";

export default
abstract class StatementGetterBase
implements ClassStatementsGetter
{
protected readonly importManager: ImportManager;

constructor(
importManager: ImportManager
)
{
this.importManager = importManager;
}

abstract getStatements(
key: MemberedStatementsKey
): stringWriterOrStatementImpl[];
}
12 changes: 12 additions & 0 deletions stage_3_generation/build/fieldStatements/GetterFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type {
MemberedStatementsKey
} from "#stage_two/snapshot/source/exports.js";
import StatementGetterBase from "./GetterBase.js";

export default
abstract class GetterFilter extends StatementGetterBase
{
abstract accept(
key: MemberedStatementsKey
): boolean;
}
38 changes: 38 additions & 0 deletions stage_3_generation/build/fieldStatements/StatementsRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
ImportManager,
MemberedStatementsKey,
stringWriterOrStatementImpl
} from "#stage_two/snapshot/source/exports.js";
import StatementGetterBase from "./GetterBase.js";
import GetterFilter from "./GetterFilter.js";

import ArrayBooleanAndString from "./ArrayBooleanAndString.js";

export default
class StatementsRouter extends StatementGetterBase
{
readonly filters: GetterFilter[];

constructor(
importManager: ImportManager
)
{
super(importManager);
this.filters = [
new ArrayBooleanAndString(importManager),
];
}

getStatements(
key: MemberedStatementsKey
): stringWriterOrStatementImpl[]
{
for (const filter of this.filters) {
if (filter.accept(key)) {
return filter.getStatements(key);
}
}

return [];
}
}
13 changes: 7 additions & 6 deletions stage_3_generation/build/interfaces/createInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ import {

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

import InterfaceModule from "../../moduleClasses/InterfaceModule.js";
import {
addImportsToModule,
InterfaceModule,
publicExports,
} from "../../moduleClasses/exports.js";

import consolidateNameDecorators from "./consolidateNameDecorators.js";
import consolidateScopeDecorators from "./consolidateScopeDecorators.js";
import mergeInterfaces from "./mergeInterfaces.js";
import setHasQuestionToken from "./setHasQuestionToken.js";
import tightenPropertyType from "./tightenPropertyType.js";
import addImportsForProperty from "./addImportsForProperty.js";
import addTypeStructures from "./addTypeStructures.js";

import { publicExports } from "../../moduleClasses/ExportsModule.js";

export default async function createInterfaces(
structureNames: readonly string[]
): Promise<void>
Expand Down Expand Up @@ -173,7 +174,7 @@ function defineImportsForModule(
): void
{
module.typeMembers.arrayOfKind(StructureKind.PropertySignature).forEach(
property => addImportsForProperty(module, property.typeStructure!)
property => addImportsToModule(module, property.typeStructure!)
);
}

Expand All @@ -182,7 +183,7 @@ function definePublicExport(
): void
{
publicExports.addExports({
pathToExportedModule: module.importsManager.absolutePathToModule,
pathToExportedModule: module.importManager.absolutePathToModule,
isDefaultExport: false,
isType: true,
exportNames: [module.defaultExportName]
Expand Down
20 changes: 10 additions & 10 deletions stage_3_generation/moduleClasses/BaseModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ abstract class BaseModule
}

readonly defaultExportName: string;
readonly importsManager: ImportManager;
readonly importManager: ImportManager;

constructor(
pathToParentDirectory: string,
Expand All @@ -81,7 +81,7 @@ abstract class BaseModule
{
this.defaultExportName = defaultExportName;

this.importsManager = new ImportManager(
this.importManager = new ImportManager(
path.join(
pathToModule(distDir, pathToParentDirectory),
`${defaultExportName}${isTypeFile ? ".d" : ""}.ts`
Expand All @@ -101,7 +101,7 @@ abstract class BaseModule
const isPackageImport = (fromModule !== "public") && (fromModule !== "internal");

if (values.length > 0) {
this.importsManager.addImports({
this.importManager.addImports({
pathToImportedModule,
isPackageImport,
isDefaultImport: false,
Expand All @@ -111,7 +111,7 @@ abstract class BaseModule
}

if (types.length > 0) {
this.importsManager.addImports({
this.importManager.addImports({
pathToImportedModule,
isPackageImport,
isDefaultImport: false,
Expand All @@ -131,7 +131,7 @@ abstract class BaseModule
const exportManager = isPublic ? publicExports : internalExports;
if (defaultExportName) {
exportManager.addExports({
pathToExportedModule: this.importsManager.absolutePathToModule,
pathToExportedModule: this.importManager.absolutePathToModule,
isDefaultExport: true,
exportNames: [defaultExportName],
isType: false
Expand All @@ -140,7 +140,7 @@ abstract class BaseModule

if (values.length) {
exportManager.addExports({
pathToExportedModule: this.importsManager.absolutePathToModule,
pathToExportedModule: this.importManager.absolutePathToModule,
isDefaultExport: false,
exportNames: values,
isType: false
Expand All @@ -149,7 +149,7 @@ abstract class BaseModule

if (types.length) {
exportManager.addExports({
pathToExportedModule: this.importsManager.absolutePathToModule,
pathToExportedModule: this.importManager.absolutePathToModule,
isDefaultExport: false,
exportNames: types,
isType: true
Expand All @@ -164,7 +164,7 @@ abstract class BaseModule
{
const exportManager = isPublic ? publicExports : internalExports;
exportManager.addExports({
pathToExportedModule: this.importsManager.absolutePathToModule,
pathToExportedModule: this.importManager.absolutePathToModule,
isDefaultExport: false,
exportNames: [],
isType
Expand All @@ -174,14 +174,14 @@ abstract class BaseModule
public async saveFile(): Promise<void>
{
const sourceStructure: SourceFileImpl = this.getSourceFileImpl();
const file = project.createSourceFile(this.importsManager.absolutePathToModule, sourceStructure);
const file = project.createSourceFile(this.importManager.absolutePathToModule, sourceStructure);
await file.save()
}

public toJSON(): object {
return {
defaultExportName: this.defaultExportName,
imports: this.importsManager.getDeclarations(),
imports: this.importManager.getDeclarations(),
}
}
}
8 changes: 6 additions & 2 deletions stage_3_generation/moduleClasses/DecoratorModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,17 @@ class DecoratorModule extends BaseClassModule
this.addImports("internal", ["StructureBase"], ["RightExtendsLeft"]);
}

get fieldsName(): string {
return this.#baseName + "Fields"
}

protected getSourceFileImpl(): SourceFileImpl
{
const sourceFile = new SourceFileImpl;

sourceFile.statements.push(
"//#region preamble",
...this.importsManager.getDeclarations(),
...this.importManager.getDeclarations(),
"//#endregion preamble",

this.#getKeySymbolStatement(),
Expand Down Expand Up @@ -139,7 +143,7 @@ class DecoratorModule extends BaseClassModule
]
);

const alias = new TypeAliasDeclarationImpl(this.#baseName + "Fields", extendsType);
const alias = new TypeAliasDeclarationImpl(this.fieldsName, extendsType);
alias.isExported = true;

return alias;
Expand Down
Loading

0 comments on commit 81d0f15

Please sign in to comment.