|
| 1 | +// tslint:disable-next-line:no-implicit-dependencies |
| 2 | +import * as ts from 'typescript'; // Imported for types alone |
| 3 | + |
| 4 | +export interface TypeScriptPatchConfig { |
| 5 | + /** |
| 6 | + * Ususally, the compilerHost created with typescript.createWatchCompilerHost will bail out of diagnostics collection if there has been any syntactic error. |
| 7 | + * (see [`emitFilesAndReportErrors`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L141) ) |
| 8 | + * If this plugin is running with `checkSyntacticErrors: false`, this might lead to situations where no syntactic errors are reported within webpack |
| 9 | + * (because the file causing a syntactic error might not get processed by ts-loader), but there are semantic errors that would be missed due to this behavior. |
| 10 | + * This ensures that the compilerHost always assumes that there were no syntactic errors to be found and continues to check for semantic errors. |
| 11 | + */ |
| 12 | + skipGetSyntacticDiagnostics: boolean; |
| 13 | +} |
| 14 | + |
| 15 | +/** |
| 16 | + * While it is often possible to pass a wrapped or modified copy of `typescript` or `typescript.sys` as a function argument to override/extend some typescript-internal behavior, |
| 17 | + * sometimes the typescript-internal code ignores these passed objects and directly references the internal `typescript` object reference. |
| 18 | + * In these situations, the only way of consistently overriding some behavior is to directly replace methods on the `typescript` object. |
| 19 | + * |
| 20 | + * So beware, this method directly modifies the passed `typescript` object! |
| 21 | + * @param typescript TypeScript instance to patch |
| 22 | + * @param config |
| 23 | + */ |
| 24 | +export function patchTypescript( |
| 25 | + typescript: typeof ts, |
| 26 | + config: TypeScriptPatchConfig |
| 27 | +) { |
| 28 | + if (config.skipGetSyntacticDiagnostics) { |
| 29 | + patchSkipGetSyntacticDiagnostics(typescript); |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +/** |
| 34 | + * Overrides the [`typescript.createEmitAndSemanticDiagnosticsBuilderProgram`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/builder.ts#L1176) |
| 35 | + * method to return a `ts.Program` instance that does not emit syntactic errors, |
| 36 | + * to prevent the [`typescript.createWatchCompilerHost`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L333) |
| 37 | + * method from bailing during diagnostic collection in the [`emitFilesAndReportErrors`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L141) callback. |
| 38 | + * |
| 39 | + * See the description of TypeScriptPatchConfig.skipGetSyntacticDiagnostics and |
| 40 | + * [this github discussion](https://github.com/Realytics/fork-ts-checker-webpack-plugin/issues/257#issuecomment-485414182) |
| 41 | + * for further information on this problem & solution. |
| 42 | + */ |
| 43 | +function patchSkipGetSyntacticDiagnostics(typescript: typeof ts) { |
| 44 | + const { |
| 45 | + createEmitAndSemanticDiagnosticsBuilderProgram: originalCreateEmitAndSemanticDiagnosticsBuilderProgram |
| 46 | + } = typescript; |
| 47 | + |
| 48 | + const patchedMethods: Pick< |
| 49 | + typeof ts, |
| 50 | + 'createEmitAndSemanticDiagnosticsBuilderProgram' |
| 51 | + > = { |
| 52 | + createEmitAndSemanticDiagnosticsBuilderProgram(...args: any[]) { |
| 53 | + const program = originalCreateEmitAndSemanticDiagnosticsBuilderProgram.apply( |
| 54 | + typescript, |
| 55 | + args as any |
| 56 | + ); |
| 57 | + program.getSyntacticDiagnostics = () => []; |
| 58 | + return program; |
| 59 | + } |
| 60 | + }; |
| 61 | + |
| 62 | + // directly patch the typescript object! |
| 63 | + Object.assign(typescript, patchedMethods); |
| 64 | +} |
0 commit comments