@@ -9,77 +9,86 @@ export const GENERATED_FILE_HEADER = `\
99// the code is regenerated.
1010// </auto-generated>` ;
1111
12- export default function createEmitter (
13- jsDocMarker : string ,
14- generate : ( program : ts . Program , classDeclaration : ts . ClassDeclaration ) => ts . SourceFile
15- ) {
16- function generateClass ( program : ts . Program , classDeclaration : ts . ClassDeclaration ) {
17- const sourceFileName = path . relative (
18- path . resolve ( program . getCompilerOptions ( ) . baseUrl ! , 'src' ) ,
19- path . resolve ( classDeclaration . getSourceFile ( ) . fileName )
20- ) ;
12+ export function generateFile ( program : ts . Program , sourceFile : ts . SourceFile , fileName : string ) {
13+ const targetFileName = path . join ( path . resolve ( program . getCompilerOptions ( ) . baseUrl ! ) , 'src/generated' , fileName ) ;
2114
22- const result = generate ( program , classDeclaration ) ;
23- const defaultClass = result . statements . find (
24- stmt => ( ts . isClassDeclaration ( stmt ) || ts . isInterfaceDeclaration ( stmt ) ) && stmt . modifiers ! . find ( m => m . kind === ts . SyntaxKind . ExportKeyword )
25- ) as ts . DeclarationStatement ;
15+ fs . mkdirSync ( path . dirname ( targetFileName ) , { recursive : true } ) ;
2616
27- const targetFileName = path . join (
28- path . resolve ( program . getCompilerOptions ( ) . baseUrl ! ) ,
29- 'src/generated' ,
30- path . dirname ( sourceFileName ) ,
31- `${ defaultClass . name ! . text } .ts`
32- ) ;
17+ const fileHandle = fs . openSync ( targetFileName , 'w' ) ;
3318
34- fs . mkdirSync ( path . dirname ( targetFileName ) , { recursive : true } ) ;
19+ fs . writeSync ( fileHandle , ` ${ GENERATED_FILE_HEADER } \n` ) ;
3520
36- const fileHandle = fs . openSync ( targetFileName , 'w' ) ;
21+ const printer = ts . createPrinter ( ) ;
22+ const source = printer . printNode ( ts . EmitHint . Unspecified , sourceFile , sourceFile ) ;
23+ const servicesHost : ts . LanguageServiceHost = {
24+ getScriptFileNames : ( ) => [ targetFileName ] ,
25+ getScriptVersion : ( ) => program . getSourceFiles ( ) [ 0 ] . languageVersion . toString ( ) ,
26+ getScriptSnapshot : fileName => ( fileName === targetFileName ? ts . ScriptSnapshot . fromString ( source ) : undefined ) ,
27+ getCurrentDirectory : ( ) => process . cwd ( ) ,
28+ getCompilationSettings : ( ) => program . getCompilerOptions ( ) ,
29+ getDefaultLibFileName : options => ts . getDefaultLibFilePath ( options ) ,
30+ fileExists : fileName => fileName === targetFileName ,
31+ readFile : fileName => ( fileName === targetFileName ? source : '' ) ,
32+ readDirectory : ts . sys . readDirectory ,
33+ directoryExists : ts . sys . directoryExists ,
34+ getDirectories : ts . sys . getDirectories
35+ } ;
3736
38- fs . writeSync ( fileHandle , `${ GENERATED_FILE_HEADER } \n` ) ;
37+ const languageService = ts . createLanguageService ( servicesHost , ts . createDocumentRegistry ( ) ) ;
38+ const formattingChanges : ts . TextChange [ ] = languageService . getFormattingEditsForDocument ( targetFileName , {
39+ convertTabsToSpaces : true ,
40+ insertSpaceAfterCommaDelimiter : true ,
41+ insertSpaceAfterKeywordsInControlFlowStatements : true ,
42+ insertSpaceBeforeAndAfterBinaryOperators : true ,
43+ indentStyle : ts . IndentStyle . Smart ,
44+ indentSize : 4 ,
45+ tabSize : 4 ,
46+ trimTrailingWhitespace : true
47+ } as ts . FormatCodeSettings ) ;
48+ formattingChanges . sort ( ( a , b ) => b . span . start - a . span . start ) ;
3949
40- const printer = ts . createPrinter ( ) ;
41- const source = printer . printNode ( ts . EmitHint . Unspecified , result , result ) ;
42- const servicesHost : ts . LanguageServiceHost = {
43- getScriptFileNames : ( ) => [ targetFileName ] ,
44- getScriptVersion : ( ) => result . languageVersion . toString ( ) ,
45- getScriptSnapshot : fileName =>
46- fileName === targetFileName ? ts . ScriptSnapshot . fromString ( source ) : undefined ,
47- getCurrentDirectory : ( ) => process . cwd ( ) ,
48- getCompilationSettings : ( ) => program . getCompilerOptions ( ) ,
49- getDefaultLibFileName : options => ts . getDefaultLibFilePath ( options ) ,
50- fileExists : fileName => fileName === targetFileName ,
51- readFile : fileName => ( fileName === targetFileName ? source : '' ) ,
52- readDirectory : ts . sys . readDirectory ,
53- directoryExists : ts . sys . directoryExists ,
54- getDirectories : ts . sys . getDirectories
55- } ;
50+ let finalText = source ;
51+ for ( const {
52+ span : { start, length } ,
53+ newText
54+ } of formattingChanges ) {
55+ finalText = `${ finalText . slice ( 0 , start ) } ${ newText } ${ finalText . slice ( start + length ) } ` ;
56+ }
5657
57- const languageService = ts . createLanguageService ( servicesHost , ts . createDocumentRegistry ( ) ) ;
58- const formattingChanges : ts . TextChange [ ] = languageService . getFormattingEditsForDocument ( targetFileName , {
59- convertTabsToSpaces : true ,
60- insertSpaceAfterCommaDelimiter : true ,
61- insertSpaceAfterKeywordsInControlFlowStatements : true ,
62- insertSpaceBeforeAndAfterBinaryOperators : true ,
63- indentStyle : ts . IndentStyle . Smart ,
64- indentSize : 4 ,
65- tabSize : 4 ,
66- trimTrailingWhitespace : true
67- } as ts . FormatCodeSettings ) ;
68- formattingChanges . sort ( ( a , b ) => b . span . start - a . span . start ) ;
58+ fs . writeSync ( fileHandle , finalText ) ;
59+ fs . closeSync ( fileHandle ) ;
60+ }
6961
70- let finalText = source ;
71- for ( const { span : { start, length } , newText } of formattingChanges ) {
72- finalText = `${ finalText . slice ( 0 , start ) } ${ newText } ${ finalText . slice ( start + length ) } ` ;
73- }
62+ export function generateClass (
63+ program : ts . Program ,
64+ classDeclaration : ts . ClassDeclaration ,
65+ generate : ( program : ts . Program , classDeclaration : ts . ClassDeclaration ) => ts . SourceFile
66+ ) {
67+ const sourceFileName = path . relative (
68+ path . resolve ( program . getCompilerOptions ( ) . baseUrl ! , 'src' ) ,
69+ path . resolve ( classDeclaration . getSourceFile ( ) . fileName )
70+ ) ;
7471
75- fs . writeSync ( fileHandle , finalText ) ;
76- fs . closeSync ( fileHandle ) ;
77- }
72+ const result = generate ( program , classDeclaration ) ;
73+ const defaultClass = result . statements . find (
74+ stmt =>
75+ ( ts . isClassDeclaration ( stmt ) || ts . isInterfaceDeclaration ( stmt ) ) &&
76+ stmt . modifiers ! . find ( m => m . kind === ts . SyntaxKind . ExportKeyword )
77+ ) as ts . DeclarationStatement ;
78+
79+ const targetFileName = path . join ( path . dirname ( sourceFileName ) , `${ defaultClass . name ! . text } .ts` ) ;
80+
81+ generateFile ( program , result , targetFileName ) ;
82+ }
7883
84+ export default function createEmitter (
85+ jsDocMarker : string ,
86+ generate : ( program : ts . Program , classDeclaration : ts . ClassDeclaration ) => ts . SourceFile
87+ ) {
7988 function scanSourceFile ( program : ts . Program , sourceFile : ts . SourceFile ) {
8089 sourceFile . statements . forEach ( stmt => {
8190 if ( ts . isClassDeclaration ( stmt ) && ts . getJSDocTags ( stmt ) . some ( t => t . tagName . text === jsDocMarker ) ) {
82- generateClass ( program , stmt ) ;
91+ generateClass ( program , stmt , generate ) ;
8392 }
8493 } ) ;
8594 }
0 commit comments