(program: ts.Program, sourceFile: ts.SourceFile, fileName: string)
| 10 | // </auto-generated>`; |
| 11 | |
| 12 | export function generateFile(program: ts.Program, sourceFile: ts.SourceFile, fileName: string) { |
| 13 | const targetFileName = path.join(path.dirname(program.getCompilerOptions().configFilePath as string), 'src/generated', fileName); |
| 14 | |
| 15 | fs.mkdirSync(path.dirname(targetFileName), { recursive: true }); |
| 16 | |
| 17 | const fileHandle = fs.openSync(targetFileName, 'w'); |
| 18 | |
| 19 | fs.writeSync(fileHandle, `${GENERATED_FILE_HEADER}\n`); |
| 20 | |
| 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 | }; |
| 36 | |
| 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); |
| 49 | |
| 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 | } |
| 57 | |
| 58 | fs.writeSync(fileHandle, finalText); |
| 59 | fs.closeSync(fileHandle); |
| 60 | } |
| 61 | |
| 62 | export function generateClass( |
| 63 | program: ts.Program, |
no test coverage detected