Skip to content

Commit

Permalink
refactor(compiler-cli): update emit signature to support for strong…
Browse files Browse the repository at this point in the history
…ly typed `emitCallback` (#47893)

Currently `ngc-wrapped` mostly relies on any casts/or disabled
strictness checks to be able to use `tsickle`'s emit callback and
emit result merging for ngtsc. We should change this so that supertypes
of `ts.EmitResult` can be used in these optional callbacks- allowing us
to enable strictness checks in `packages/bazel/...` too.

PR Close #47893
  • Loading branch information
devversion authored and alxhub committed Nov 1, 2022
1 parent 623602f commit f99cc40
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 40 deletions.
6 changes: 3 additions & 3 deletions packages/compiler-cli/src/main.ts
Expand Up @@ -7,7 +7,7 @@
*/

import ts from 'typescript';
import type {TsickleHost} from 'tsickle';
import type {TsickleHost, EmitResult as TsickleEmitResult} from 'tsickle';
import yargs from 'yargs';
import {exitCodeFromResult, formatDiagnostics, ParsedConfiguration, performCompilation, readConfiguration} from './perform_compile';
import {createPerformWatchHost, performWatchCompilation} from './perform_watch';
Expand Down Expand Up @@ -91,8 +91,8 @@ export function mainDiagnosticsForTest(
};
}

function createEmitCallback(
options: api.CompilerOptions, tsickle?: TsickleModule): api.TsEmitCallback|undefined {
function createEmitCallback(options: api.CompilerOptions, tsickle?: TsickleModule):
api.TsEmitCallback<TsickleEmitResult>|undefined {
if (!options.annotateForClosureCompiler) {
return undefined;
}
Expand Down
17 changes: 6 additions & 11 deletions packages/compiler-cli/src/ngtsc/program.ts
Expand Up @@ -231,14 +231,8 @@ export class NgtscProgram implements api.Program {
this.options, ctx, resolve);
}

emit(opts?: {
emitFlags?: api.EmitFlags|undefined;
forceEmit?: boolean;
cancellationToken?: ts.CancellationToken | undefined;
customTransformers?: api.CustomTransformers | undefined;
emitCallback?: api.TsEmitCallback | undefined;
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined;
}|undefined): ts.EmitResult {
emit<CbEmitRes extends ts.EmitResult>(opts?: api.EmitOptions<CbEmitRes>|
undefined): ts.EmitResult {
// Check if emission of the i18n messages bundle was requested.
if (opts !== undefined && opts.emitFlags !== undefined &&
opts.emitFlags & api.EmitFlags.I18nBundle) {
Expand All @@ -263,7 +257,8 @@ export class NgtscProgram implements api.Program {
const res = this.compiler.perfRecorder.inPhase(PerfPhase.TypeScriptEmit, () => {
const {transformers} = this.compiler.prepareEmit();
const ignoreFiles = this.compiler.ignoreForEmit;
const emitCallback = opts && opts.emitCallback || defaultEmitCallback;
const emitCallback =
(opts?.emitCallback ?? defaultEmitCallback) as api.TsEmitCallback<CbEmitRes>;

const writeFile: ts.WriteFileCallback =
(fileName: string, data: string, writeByteOrderMark: boolean,
Expand Down Expand Up @@ -291,7 +286,7 @@ export class NgtscProgram implements api.Program {
beforeTransforms.push(...customTransforms.beforeTs);
}

const emitResults: ts.EmitResult[] = [];
const emitResults: CbEmitRes[] = [];

for (const targetSourceFile of this.tsProgram.getSourceFiles()) {
if (targetSourceFile.isDeclarationFile || ignoreFiles.has(targetSourceFile)) {
Expand Down Expand Up @@ -345,7 +340,7 @@ export class NgtscProgram implements api.Program {
}
}

const defaultEmitCallback: api.TsEmitCallback = ({
const defaultEmitCallback: api.TsEmitCallback<ts.EmitResult> = ({
program,
targetSourceFile,
writeFile,
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-cli/src/perform_compile.ts
Expand Up @@ -208,7 +208,7 @@ export function exitCodeFromResult(diags: ReadonlyArray<ts.Diagnostic>|undefined
return diags.some(d => d.source === 'angular' && d.code === api.UNKNOWN_ERROR_CODE) ? 2 : 1;
}

export function performCompilation({
export function performCompilation<CbEmitRes extends ts.EmitResult = ts.EmitResult>({
rootNames,
options,
host,
Expand All @@ -225,8 +225,8 @@ export function performCompilation({
options: api.CompilerOptions,
host?: api.CompilerHost,
oldProgram?: api.Program,
emitCallback?: api.TsEmitCallback,
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback,
emitCallback?: api.TsEmitCallback<CbEmitRes>,
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback<CbEmitRes>,
gatherDiagnostics?: (program: api.Program) => ReadonlyArray<ts.Diagnostic>,
customTransformers?: api.CustomTransformers,
emitFlags?: api.EmitFlags,
Expand Down
8 changes: 4 additions & 4 deletions packages/compiler-cli/src/perform_watch.ts
Expand Up @@ -39,23 +39,23 @@ export enum FileChangeEvent {
CreateDeleteDir,
}

export interface PerformWatchHost {
export interface PerformWatchHost<CbEmitRes extends ts.EmitResult = ts.EmitResult> {
reportDiagnostics(diagnostics: ReadonlyArray<ts.Diagnostic>): void;
readConfiguration(): ParsedConfiguration;
createCompilerHost(options: api.CompilerOptions): api.CompilerHost;
createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|undefined;
createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback<CbEmitRes>|undefined;
onFileChange(
options: api.CompilerOptions, listener: (event: FileChangeEvent, fileName: string) => void,
ready: () => void): {close: () => void};
setTimeout(callback: () => void, ms: number): any;
clearTimeout(timeoutId: any): void;
}

export function createPerformWatchHost(
export function createPerformWatchHost<CbEmitRes extends ts.EmitResult = ts.EmitResult>(
configFileName: string, reportDiagnostics: (diagnostics: ReadonlyArray<ts.Diagnostic>) => void,
existingOptions?: ts.CompilerOptions,
createEmitCallback?: (options: api.CompilerOptions) =>
api.TsEmitCallback | undefined): PerformWatchHost {
api.TsEmitCallback<CbEmitRes>| undefined): PerformWatchHost {
return {
reportDiagnostics: reportDiagnostics,
createCompilerHost: options => createCompilerHost({options}),
Expand Down
33 changes: 14 additions & 19 deletions packages/compiler-cli/src/transformers/api.ts
Expand Up @@ -162,11 +162,11 @@ export interface TsEmitArguments {
customTransformers?: ts.CustomTransformers;
}

export interface TsEmitCallback {
(args: TsEmitArguments): ts.EmitResult;
export interface TsEmitCallback<T extends ts.EmitResult> {
(args: TsEmitArguments): T;
}
export interface TsMergeEmitResultsCallback {
(results: ts.EmitResult[]): ts.EmitResult;
export interface TsMergeEmitResultsCallback<T extends ts.EmitResult> {
(results: T[]): T;
}

export interface LazyRoute {
Expand All @@ -175,6 +175,15 @@ export interface LazyRoute {
referencedModule: {name: string, filePath: string};
}

export interface EmitOptions<CbEmitRes extends ts.EmitResult> {
emitFlags?: EmitFlags;
forceEmit?: boolean;
cancellationToken?: ts.CancellationToken;
customTransformers?: CustomTransformers;
emitCallback?: TsEmitCallback<CbEmitRes>;
mergeEmitResultsCallback?: TsMergeEmitResultsCallback<CbEmitRes>;
}

export interface Program {
/**
* Retrieve the TypeScript program used to produce semantic diagnostics and emit the sources.
Expand Down Expand Up @@ -250,21 +259,7 @@ export interface Program {
*
* Angular structural information is required to emit files.
*/
emit({
emitFlags,
forceEmit,
cancellationToken,
customTransformers,
emitCallback,
mergeEmitResultsCallback,
}?: {
emitFlags?: EmitFlags,
forceEmit?: boolean,
cancellationToken?: ts.CancellationToken,
customTransformers?: CustomTransformers,
emitCallback?: TsEmitCallback,
mergeEmitResultsCallback?: TsMergeEmitResultsCallback
}): ts.EmitResult;
emit<CbEmitRes extends ts.EmitResult>(opts?: EmitOptions<CbEmitRes>|undefined): ts.EmitResult;

/**
* @internal
Expand Down

0 comments on commit f99cc40

Please sign in to comment.