Skip to content

Commit

Permalink
feat: generate type imports for readonly visitors
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Jun 16, 2023
1 parent 96945e8 commit c82cf93
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/compiler/interfaces/readonly-visitor.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type DeepPluginMeta =

export interface ReadonlyVisitor {
key: string;
typeImports: Record<string, string>;
visit(program: ts.Program, sf: ts.SourceFile): void;
collect(): Record<string, Array<[ts.CallExpression, DeepPluginMeta]>>;
}
8 changes: 7 additions & 1 deletion lib/compiler/plugins/plugin-metadata-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,20 @@ export class PluginMetadataGenerator {
}
}

let typeImports: Record<string, string> = {};
const collectedMetadata: Record<
string,
Record<string, Array<[ts.CallExpression, DeepPluginMeta]>>
> = {};

visitors.forEach((visitor) => {
collectedMetadata[visitor.key] = visitor.collect();
typeImports = {
...typeImports,
...visitor.typeImports,
};
});
this.pluginMetadataPrinter.print(collectedMetadata, {
this.pluginMetadataPrinter.print(collectedMetadata, typeImports, {
outputDir,
filename,
});
Expand Down
64 changes: 59 additions & 5 deletions lib/compiler/plugins/plugin-metadata-printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@ import * as ts from 'typescript';
import { DeepPluginMeta } from '../interfaces/readonly-visitor.interface';

const SERIALIZED_METADATA_FILENAME = 'metadata.ts';
const TYPE_IMPORT_VARIABLE_NAME = 't';

export interface PluginMetadataPrintOptions {
outputDir: string;
filename?: string;
}

type ComposedPluginMeta = Record<
string,
Record<string, Array<[ts.CallExpression, DeepPluginMeta]>>
>;

/**
* Prints the metadata to a file.
*/
export class PluginMetadataPrinter {
print(
metadata: Record<
string,
Record<string, Array<[ts.CallExpression, DeepPluginMeta]>>
>,
metadata: ComposedPluginMeta,
typeImports: Record<string, string>,
options: PluginMetadataPrintOptions,
) {
const objectLiteralExpr = ts.factory.createObjectLiteralExpression(
Expand All @@ -31,10 +35,24 @@ export class PluginMetadataPrinter {
),
),
);

const exportAssignment = ts.factory.createExportAssignment(
undefined,
undefined,
objectLiteralExpr,
ts.factory.createArrowFunction(
[ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)],
undefined,
[],
undefined,
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
ts.factory.createBlock(
[
this.createTypeImportVariableStatement(typeImports),
ts.factory.createReturnStatement(objectLiteralExpr),
],
true,
),
),
);

const printer = ts.createPrinter({
Expand Down Expand Up @@ -110,4 +128,40 @@ export class PluginMetadataPrinter {
),
);
}

private createTypeImportVariableStatement(
typeImports: Record<string, string>,
): ts.Statement {
return ts.factory.createVariableStatement(
undefined,
ts.factory.createVariableDeclarationList(
[
ts.factory.createVariableDeclaration(
ts.factory.createIdentifier(TYPE_IMPORT_VARIABLE_NAME),
undefined,
undefined,
ts.factory.createObjectLiteralExpression(
Object.keys(typeImports).map((ti) =>
this.createPropertyAssignment(ti, typeImports[ti]),
),
true,
),
),
],
ts.NodeFlags.Const |
ts.NodeFlags.AwaitContext |
ts.NodeFlags.ContextFlags |
ts.NodeFlags.TypeExcludesFlags,
),
);
}

private createPropertyAssignment(identifier: string, target: string) {
return ts.factory.createPropertyAssignment(
ts.factory.createComputedPropertyName(
ts.factory.createStringLiteral(identifier),
),
ts.factory.createIdentifier(target),
);
}
}

0 comments on commit c82cf93

Please sign in to comment.