11import ts from "typescript" ;
2- import { createImportManager } from "./imports.ts" ;
3- import type { ImportManager } from "./imports.ts" ;
2+ import { ImportRequirements } from "./imports.ts" ;
43
54export type TransformMode = "transform" | "error" ;
65
@@ -9,11 +8,6 @@ export interface TransformationOptions {
98 readonly debug ?: boolean ;
109}
1110
12- export interface TransformationFlags {
13- jsxExpressionDepth : number ;
14- inJsxAttribute : boolean ;
15- }
16-
1711export interface TransformationDiagnostic {
1812 readonly type : string ;
1913 readonly message : string ;
@@ -28,112 +22,61 @@ export interface DiagnosticInput {
2822 readonly node : ts . Node ;
2923}
3024
31- type FlagValue = TransformationFlags [ keyof TransformationFlags ] ;
32-
33- export interface TransformationContext {
34- readonly program : ts . Program ;
35- readonly checker : ts . TypeChecker ;
36- readonly factory : ts . NodeFactory ;
37- readonly sourceFile : ts . SourceFile ;
38- readonly options : Required < TransformationOptions > ;
39- readonly imports : ImportManager ;
40- readonly diagnostics : TransformationDiagnostic [ ] ;
41- readonly flags : TransformationFlags ;
42- getType ( node : ts . Node ) : ts . Type ;
43- reportDiagnostic ( input : DiagnosticInput ) : void ;
44- withFlag < T > (
45- flag : keyof TransformationFlags ,
46- value : FlagValue ,
47- fn : ( ) => T ,
48- ) : T ;
49- }
50-
5125const DEFAULT_OPTIONS : Required < TransformationOptions > = {
5226 mode : "transform" ,
5327 debug : false ,
5428} ;
5529
56- function createInitialFlags ( ) : TransformationFlags {
57- return {
58- jsxExpressionDepth : 0 ,
59- inJsxAttribute : false ,
60- } ;
30+ export interface TransformationContextConfig {
31+ program : ts . Program ;
32+ sourceFile : ts . SourceFile ;
33+ transformation : ts . TransformationContext ;
34+ options ?: TransformationOptions ;
35+ imports ?: ImportRequirements ;
6136}
6237
63- export function createTransformationContext (
64- program : ts . Program ,
65- sourceFile : ts . SourceFile ,
66- transformation : ts . TransformationContext ,
67- options : TransformationOptions = { } ,
68- imports : ImportManager = createImportManager ( ) ,
69- ) : TransformationContext {
70- const checker = program . getTypeChecker ( ) ;
71- const factory = transformation . factory ;
72- const mergedOptions : Required < TransformationOptions > = {
73- ...DEFAULT_OPTIONS ,
74- ...options ,
75- } ;
76-
77- const typeCache = new Map < ts . Node , ts . Type > ( ) ;
78- const diagnostics : TransformationDiagnostic [ ] = [ ] ;
79- const flags = createInitialFlags ( ) ;
38+ export class TransformationContext {
39+ readonly program : ts . Program ;
40+ readonly checker : ts . TypeChecker ;
41+ readonly factory : ts . NodeFactory ;
42+ readonly sourceFile : ts . SourceFile ;
43+ readonly options : Required < TransformationOptions > ;
44+ readonly imports : ImportRequirements ;
45+ readonly diagnostics : TransformationDiagnostic [ ] = [ ] ;
46+ #typeCache = new Map < ts . Node , ts . Type > ( ) ;
8047
81- const context : TransformationContext = {
82- program,
83- checker,
84- factory,
85- sourceFile,
86- options : mergedOptions ,
87- imports,
88- diagnostics,
89- flags,
90- getType ( node : ts . Node ) : ts . Type {
91- const cached = typeCache . get ( node ) ;
92- if ( cached ) {
93- return cached ;
94- }
95- const type = checker . getTypeAtLocation ( node ) ;
96- typeCache . set ( node , type ) ;
97- return type ;
98- } ,
99- reportDiagnostic ( input : DiagnosticInput ) : void {
100- const location = sourceFile . getLineAndCharacterOfPosition (
101- input . node . getStart ( ) ,
102- ) ;
103- diagnostics . push ( {
104- type : input . type ,
105- message : input . message ,
106- fileName : sourceFile . fileName ,
107- line : location . line + 1 ,
108- column : location . character + 1 ,
109- } ) ;
110- } ,
111- withFlag < T > (
112- flag : keyof TransformationFlags ,
113- value : FlagValue ,
114- fn : ( ) => T ,
115- ) : T {
116- const key = flag as keyof TransformationFlags ;
117- const previous = flags [ key ] as FlagValue ;
118- // deno-lint-ignore no-explicit-any
119- ( flags as any ) [ key ] = value ;
120- try {
121- return fn ( ) ;
122- } finally {
123- // deno-lint-ignore no-explicit-any
124- ( flags as any ) [ key ] = previous ;
125- }
126- } ,
127- } ;
48+ constructor ( config : TransformationContextConfig ) {
49+ this . program = config . program ;
50+ this . checker = config . program . getTypeChecker ( ) ;
51+ this . factory = config . transformation . factory ;
52+ this . sourceFile = config . sourceFile ;
53+ this . imports = config . imports ?? new ImportRequirements ( ) ;
54+ this . options = {
55+ ...DEFAULT_OPTIONS ,
56+ ...config . options ,
57+ } ;
58+ }
12859
129- return context ;
130- }
60+ getType ( node : ts . Node ) : ts . Type {
61+ const cached = this . #typeCache. get ( node ) ;
62+ if ( cached ) {
63+ return cached ;
64+ }
65+ const type = this . checker . getTypeAtLocation ( node ) ;
66+ this . #typeCache. set ( node , type ) ;
67+ return type ;
68+ }
13169
132- export function withFlag < T > (
133- context : TransformationContext ,
134- flag : keyof TransformationFlags ,
135- value : FlagValue ,
136- fn : ( ) => T ,
137- ) : T {
138- return context . withFlag ( flag , value , fn ) ;
70+ reportDiagnostic ( input : DiagnosticInput ) : void {
71+ const location = this . sourceFile . getLineAndCharacterOfPosition (
72+ input . node . getStart ( ) ,
73+ ) ;
74+ this . diagnostics . push ( {
75+ type : input . type ,
76+ message : input . message ,
77+ fileName : this . sourceFile . fileName ,
78+ line : location . line + 1 ,
79+ column : location . character + 1 ,
80+ } ) ;
81+ }
13982}
0 commit comments