-
Notifications
You must be signed in to change notification settings - Fork 3
Add Transformer Library to TypeSpec Compiler Package #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/transformer
Are you sure you want to change the base?
Changes from 2 commits
382fb8c
869089f
3a1ac82
3168ad7
9d36399
f3d792b
e235fbd
e50ab7c
7af8f6d
b1176f5
27036b8
adf2cd5
dd00983
679a025
c3eb172
6439e09
ec260f5
12a7ed4
1c3426f
fecf4f2
7157290
a5efa3c
cea1774
4a728cb
3317b78
d1110c0
9aea80e
2ab20b8
d2bd68e
b3e4cdb
d762544
08179f6
85a59e5
69e56d2
4cf169f
a2c1939
00c7c67
91cb685
d7f969b
93a9c0e
1564e6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,12 @@ import { | |
| } from "./source-loader.js"; | ||
| import { createStateAccessors } from "./state-accessors.js"; | ||
| import { ComplexityStats, RuntimeStats, Stats, startTimer, time, timeAsync } from "./stats.js"; | ||
| import { | ||
| builtInTransformerLibraryName, | ||
| createBuiltInTransformerLibrary, | ||
| createTransformer, | ||
| resolveTransformerDefinition, | ||
| } from "./transformer.js"; | ||
| import { | ||
| CompilerHost, | ||
| Diagnostic, | ||
|
|
@@ -52,8 +58,8 @@ import { | |
| EmitterFunc, | ||
| Entity, | ||
| JsSourceFileNode, | ||
| LibraryInstance, | ||
| LibraryMetadata, | ||
| LinterLibraryInstance, | ||
| LiteralType, | ||
| LocationContext, | ||
| LogSink, | ||
|
|
@@ -68,6 +74,7 @@ import { | |
| SyntaxKind, | ||
| TemplateInstanceTarget, | ||
| Tracer, | ||
| TransformerLibraryInstance, | ||
| Type, | ||
| TypeSpecLibrary, | ||
| TypeSpecScriptNode, | ||
|
|
@@ -136,13 +143,20 @@ export interface Program { | |
| readonly projectRoot: string; | ||
| } | ||
|
|
||
| export interface TransformedProgram extends Program { | ||
| /** | ||
| * Result from running transformers, including mutation engines for accessing transformed types. | ||
| */ | ||
| readonly transformerResult?: import("./transformer.js").TransformerResult; | ||
| } | ||
|
|
||
| interface EmitterRef { | ||
| emitFunction: EmitterFunc; | ||
| main: string; | ||
| metadata: LibraryMetadata; | ||
| emitterOutputDir: string; | ||
| options: Record<string, unknown>; | ||
| readonly library: LibraryInstance; | ||
| readonly library: LinterLibraryInstance & TransformerLibraryInstance; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm do we need to make this change? This implies that every library has a linter and a transformer, which I don't think is true? I'd expect this to either just be |
||
| } | ||
|
|
||
| interface Validator { | ||
|
|
@@ -207,7 +221,7 @@ async function createProgram( | |
| mainFile: string, | ||
| options: CompilerOptions = {}, | ||
| oldProgram?: Program, | ||
| ): Promise<{ program: Program; shouldAbort: boolean }> { | ||
| ): Promise<{ program: TransformedProgram; shouldAbort: boolean }> { | ||
| const runtimeStats: Partial<RuntimeStats> = {}; | ||
| const validateCbs: Validator[] = []; | ||
| const stateMaps = new Map<symbol, Map<Type, unknown>>(); | ||
|
|
@@ -303,6 +317,16 @@ async function createProgram( | |
| program.reportDiagnostics(await linter.extendRuleSet(options.linterRuleSet)); | ||
| } | ||
|
|
||
| const transformer = createTransformer(program, (name) => loadLibrary(basedir, name)); | ||
| // Register built-in transformer library (currently empty placeholder) | ||
| transformer.registerTransformLibrary( | ||
| builtInTransformerLibraryName, | ||
| createBuiltInTransformerLibrary(), | ||
| ); | ||
|
Comment on lines
+322
to
+325
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would the builtin transformer library be? The builtin linter library enables a couple of standard rules. Are you thinking of there being "standard" transforms, e.g. |
||
| if (options.transformSet) { | ||
| program.reportDiagnostics(await transformer.extendTransformSet(options.transformSet)); | ||
| } | ||
|
|
||
| program.checker = createChecker(program, resolver); | ||
| runtimeStats.checker = time(() => program.checker.checkProgram()); | ||
|
|
||
|
|
@@ -329,7 +353,17 @@ async function createProgram( | |
| runtimeStats.linter = lintResult.stats.runtime; | ||
| program.reportDiagnostics(lintResult.diagnostics); | ||
|
|
||
| return { program, shouldAbort: false }; | ||
| // Transform stage | ||
| const transformResult = transformer.transform(); | ||
| runtimeStats.transformer = transformResult.stats.runtime; | ||
| program.reportDiagnostics(transformResult.diagnostics); | ||
|
|
||
| // Attach transformer result to the program so consumers can access mutation engines | ||
| const transformedProgram: TransformedProgram = Object.assign(transformResult.program, { | ||
| transformerResult: transformResult, | ||
| }); | ||
|
|
||
| return { program: transformedProgram, shouldAbort: false }; | ||
|
|
||
| /** | ||
| * Validate the libraries loaded during the compilation process are compatible. | ||
|
|
@@ -507,7 +541,7 @@ async function createProgram( | |
| async function loadLibrary( | ||
| basedir: string, | ||
| libraryNameOrPath: string, | ||
| ): Promise<LibraryInstance | undefined> { | ||
| ): Promise<(LinterLibraryInstance & TransformerLibraryInstance) | undefined> { | ||
| const [resolution, diagnostics] = await resolveEmitterModuleAndEntrypoint( | ||
| basedir, | ||
| libraryNameOrPath, | ||
|
|
@@ -522,11 +556,14 @@ async function createProgram( | |
| const libDefinition: TypeSpecLibrary<any> | undefined = entrypoint?.esmExports.$lib; | ||
| const metadata = computeLibraryMetadata(module, libDefinition); | ||
| const linterDef = entrypoint?.esmExports.$linter; | ||
| const transformerDef = entrypoint?.esmExports.$transformer; | ||
| return { | ||
| ...resolution, | ||
| metadata, | ||
| definition: libDefinition, | ||
| linter: linterDef && resolveLinterDefinition(libraryNameOrPath, linterDef), | ||
| transformer: | ||
| transformerDef && resolveTransformerDefinition(libraryNameOrPath, transformerDef), | ||
| }; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the linter, these are
errors, notwarning`s. Should we be doing the same here?