Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose printing functionality of emitter as a public API #13761

Merged
merged 6 commits into from
Feb 2, 2017

Conversation

rbuckton
Copy link
Member

@rbuckton rbuckton commented Jan 30, 2017

This exposes a new public createPrinter export on the ts namespace that can be used to print a TypeScript AST as-is (without transformation):

// public API
declare namespace ts {
  // subset of CompilerOptions
  interface PrinterOptions {
    target?: ScriptTarget;
    removeComments?: boolean;
    newLine?: NewLineKind;
  }

  // custom hooks for name generation, emit notification, and substitution
  interface PrintHandlers {
    hasGlobalName?: (name: string) => boolean;
    onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
    onSubstituteNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
  }

  // printer service
  interface Printer {
    printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string;
    printFile(sourceFile: SourceFile): string;
    printBundle(bundle: Bundle): string;
  }
  
  // printer factory
  function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer;

  // bundles output (for --outFile)
  interface Bundle extends Node {
    kind: SyntaxKind.Bundle;
    sourceFiles: SourceFile[];
  }
}

To support our internal emit needs, we also have the following internal API for printing:

// internal API
declare namespace ts {
  // internal hooks to support source map and helper emit
  interface PrintHandlers {
    /*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
    /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number;
    /*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
    /*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void;
    /*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
  }

  // subset of compiler options needed to support source map emit
  export interface PrinterOptions {
    /*@internal*/ sourceMap?: boolean;
    /*@internal*/ inlineSourceMap?: boolean;
    /*@internal*/ extendedDiagnostics?: boolean;
  }

  // print a node, file, or bundle to an existing EmitTextWriter
  export interface Printer {
    /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void;
    /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void;
    /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void;
  }  
}

The public API for printing does not support source maps currently as this is heavily tied into the emitter. We may choose to support this via a later PR.

This further extends the work started in #5595 with the overall goal of making significant portions of the new transformation and emit pipeline part of the public API. This is also intended to help support ongoing effort into refactoring and code actions.

Fixes #13762

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the changes in emitter.ts a bit more? I see the reorganisation to expose the new public API, but it looks like there's two other things going on too:

  1. Refactor the pipeline* internals To make them more obviously asynchronous or something? It looks like what I would call continuation-passing style, which it didn't beforehand.
  2. Other small improvements inside, for example, emitSignatureAndBody and emitTypeAssertionExpression and the rest of the file. I think these are unrelated to the API change.

Am I totally off-base about (1) and (2)? I think more explanation would help me.

@@ -198,9 +198,9 @@ namespace ts {
}

// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitPos(commentPos);
if (emitPos) emitPos(commentPos);
Copy link
Contributor

@vladima vladima Feb 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this check (and other checks below) are necessary? If emitPos can be undefined, can you please reflect this in its type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source map support is not currently exposed publicly, so a printer created through the public API would not be able to provide an emitPos callback. I'll amend the parameter to include undefined.

Copy link
Contributor

@mhegazy mhegazy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I would like to know the plan for making the transforms API public as well, and how it would be used with the printer

}

export interface PrintHandlers {
hasGlobalName?: (name: string) => boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some comments on how the callbacks are used.

@rbuckton
Copy link
Member Author

rbuckton commented Feb 1, 2017

@mhegazy The tasks involved in making the API public can be found here.

@rbuckton
Copy link
Member Author

rbuckton commented Feb 1, 2017

@sandersn both (1) and (2) are incorrect, there were no changes to that functionality of emitter, other than moving createPrinter out of emitFiles. Github is just showing a significant amount of changes due to some minor reorganization as most of the existing functions were moved down and emitHelpers was moved up as they are now in different closures.

@zpdDG4gta8XKpMCd
Copy link

nice

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants