export function emit()

in src/tsickle.ts [143:264]


export function emit(
    program: ts.Program, host: TsickleHost, writeFile: ts.WriteFileCallback,
    targetSourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken,
    emitOnlyDtsFiles?: boolean,
    customTransformers: EmitTransformers = {}): EmitResult {
  for (const sf of program.getSourceFiles()) {
    assertAbsolute(sf.fileName);
  }

  let tsickleDiagnostics: ts.Diagnostic[] = [];
  const typeChecker = program.getTypeChecker();
  const tsOptions = program.getCompilerOptions();
  if (!tsOptions.rootDir) {
    // Various places within tsickle assume rootDir is always present,
    // so return an error here if it wasn't provided.
    return {
      emitSkipped: false,
      diagnostics: [{
        category: ts.DiagnosticCategory.Error,
        code: 0,
        file: undefined,
        start: undefined,
        length: undefined,
        messageText: 'TypeScript options must specify rootDir',
      }],
      modulesManifest: new ModulesManifest(),
      externs: {},
      tsMigrationExportsShimFiles: new Map(),
    };
  }

  const modulesManifest = new ModulesManifest();
  const tsMigrationExportsShimFiles = new Map<string, string>();
  const tsickleSourceTransformers: Array<ts.TransformerFactory<ts.SourceFile>> =
      [];
  tsickleSourceTransformers.push(
      tsmes.createTsMigrationExportsShimTransformerFactory(
          typeChecker, host, modulesManifest, tsickleDiagnostics,
          tsMigrationExportsShimFiles));
  if (host.transformTypesToClosure) {
    // Only add @suppress {checkTypes} comments when also adding type
    // annotations.
    tsickleSourceTransformers.push(
        transformFileoverviewCommentFactory(tsOptions, tsickleDiagnostics));
    tsickleSourceTransformers.push(
        jsdocTransformer(host, tsOptions, typeChecker, tsickleDiagnostics));
    tsickleSourceTransformers.push(
        enumTransformer(typeChecker, tsickleDiagnostics));
  }
  if (host.transformDecorators) {
    tsickleSourceTransformers.push(
        decoratorDownlevelTransformer(typeChecker, tsickleDiagnostics));
  }
  const tsTransformers: ts.CustomTransformers = {
    before: [
      ...(tsickleSourceTransformers || [])
          .map(tf => skipTransformForSourceFileIfNeeded(host, tf)),
      ...(customTransformers.beforeTs || []),
    ],
    after: [...(customTransformers.afterTs || [])],
    afterDeclarations: [...(customTransformers.afterDeclarations || [])]
  };
  if (host.transformTypesToClosure) {
    // See comment on removeTypeAssertions.
    tsTransformers.before!.push(removeTypeAssertions());
  }
  if (host.googmodule) {
    tsTransformers.after!.push(googmodule.commonJsToGoogmoduleTransformer(
        host, modulesManifest, typeChecker));
    tsTransformers.after!.push(
        transformDecoratorsOutputForClosurePropertyRenaming(
            tsickleDiagnostics));
    tsTransformers.after!.push(transformDecoratorJsdoc());
  }
  if (host.addDtsClutzAliases) {
    tsTransformers.afterDeclarations!.push(
        clutz.makeDeclarationTransformerFactory(
            typeChecker, (path: string) => host.pathToModuleName('', path)));
  }

  const {diagnostics: tsDiagnostics, emitSkipped, emittedFiles} = program.emit(
      targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles,
      tsTransformers);

  const externs: {[fileName: string]: string} = {};
  if (host.transformTypesToClosure) {
    const sourceFiles =
        targetSourceFile ? [targetSourceFile] : program.getSourceFiles();
    for (const sourceFile of sourceFiles) {
      const isDts = isDtsFileName(sourceFile.fileName);
      if (isDts && host.shouldSkipTsickleProcessing(sourceFile.fileName)) {
        continue;
      }
      const {output, diagnostics} = generateExterns(
          typeChecker, sourceFile, host, host.moduleResolutionHost,
          program.getCompilerOptions());
      if (output) {
        externs[sourceFile.fileName] = output;
      }
      if (diagnostics) {
        tsickleDiagnostics.push(...diagnostics);
      }
    }
  }

  // All diagnostics (including warnings) are treated as errors.
  // If the host decides to ignore warnings, just discard them.
  // Warnings include stuff like "don't use @type in your jsdoc"; tsickle
  // warns and then fixes up the code to be Closure-compatible anyway.
  tsickleDiagnostics = tsickleDiagnostics.filter(
      d => d.category === ts.DiagnosticCategory.Error ||
          !host.shouldIgnoreWarningsForPath(d.file!.fileName));

  return {
    modulesManifest,
    emitSkipped,
    emittedFiles: emittedFiles || [],
    diagnostics: [...tsDiagnostics, ...tsickleDiagnostics],
    externs,
    tsMigrationExportsShimFiles,
  };
}