Skip to content

Transformation API Cleanup #11165

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

Merged
merged 7 commits into from
Sep 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2592,7 +2592,7 @@ namespace ts {
}

// Currently, we only support generators that were originally async function bodies.
if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}

Expand Down Expand Up @@ -2667,7 +2667,7 @@ namespace ts {
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}
}
Expand Down Expand Up @@ -2698,7 +2698,7 @@ namespace ts {
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}

Expand Down
53 changes: 24 additions & 29 deletions src/compiler/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace ts {
export interface CommentWriter {
reset(): void;
setSourceFile(sourceFile: SourceFile): void;
emitNodeWithComments(node: Node, emitCallback: (node: Node) => void): void;
emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
Copy link
Contributor

Choose a reason for hiding this comment

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

at first it is a bit confusing with emitContext and context which is a TransformationContext

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm open to a better name, but I feel this is the correct terminology.

emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
emitTrailingCommentsOfPosition(pos: number): void;
}
Expand Down Expand Up @@ -34,22 +34,24 @@ namespace ts {
emitTrailingCommentsOfPosition,
};

function emitNodeWithComments(node: Node, emitCallback: (node: Node) => void) {
function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
if (disabled) {
emitCallback(node);
emitCallback(emitContext, node);
return;
}

if (node) {
const { pos, end } = node.commentRange || node;
const emitFlags = node.emitFlags;
const { pos, end } = getCommentRange(node);
const emitFlags = getEmitFlags(node);
if ((pos < 0 && end < 0) || (pos === end)) {
// Both pos and end are synthesized, so just emit the node without comments.
if (emitFlags & NodeEmitFlags.NoNestedComments) {
disableCommentsAndEmit(node, emitCallback);
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(emitContext, node);
disabled = false;
}
else {
emitCallback(node);
emitCallback(emitContext, node);
}
}
else {
Expand All @@ -58,8 +60,8 @@ namespace ts {
}

const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement;
const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
const skipTrailingComments = end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0;
const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0;
const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0;

// Emit leading comments if the position is not synthesized and the node
// has not opted out from emitting leading comments.
Expand Down Expand Up @@ -90,11 +92,13 @@ namespace ts {
performance.measure("commentTime", "preEmitNodeWithComment");
}

if (emitFlags & NodeEmitFlags.NoNestedComments) {
disableCommentsAndEmit(node, emitCallback);
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(emitContext, node);
disabled = false;
}
else {
emitCallback(node);
emitCallback(emitContext, node);
}

if (extendedDiagnostics) {
Expand Down Expand Up @@ -125,9 +129,9 @@ namespace ts {
}

const { pos, end } = detachedRange;
const emitFlags = node.emitFlags;
const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
const skipTrailingComments = disabled || end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0;
const emitFlags = getEmitFlags(node);
const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0;
const skipTrailingComments = disabled || end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0;

if (!skipLeadingComments) {
emitDetachedCommentsAndUpdateCommentsInfo(detachedRange);
Expand All @@ -137,8 +141,10 @@ namespace ts {
performance.measure("commentTime", "preEmitBodyWithDetachedComments");
}

if (emitFlags & NodeEmitFlags.NoNestedComments) {
disableCommentsAndEmit(node, emitCallback);
if (emitFlags & EmitFlags.NoNestedComments && !disabled) {
disabled = true;
emitCallback(node);
disabled = false;
}
else {
emitCallback(node);
Expand Down Expand Up @@ -284,17 +290,6 @@ namespace ts {
detachedCommentsInfo = undefined;
}

function disableCommentsAndEmit(node: Node, emitCallback: (node: Node) => void): void {
if (disabled) {
emitCallback(node);
}
else {
disabled = true;
emitCallback(node);
disabled = false;
}
}

function hasDetachedComments(pos: number) {
return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos;
}
Expand Down
67 changes: 66 additions & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,72 @@ namespace ts {
};
}

/**
* High-order function, creates a function that executes a function composition.
* For example, `chain(a, b)` is the equivalent of `x => ((a', b') => y => b'(a'(y)))(a(x), b(x))`
*
* @param args The functions to chain.
*/
export function chain<T, U>(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U;
export function chain<T, U>(a: (t: T) => (u: U) => U, b: (t: T) => (u: U) => U, c: (t: T) => (u: U) => U, d: (t: T) => (u: U) => U, e: (t: T) => (u: U) => U): (t: T) => (u: U) => U {
if (e) {
const args: ((t: T) => (u: U) => U)[] = [];
for (let i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}

return t => compose(...map(args, f => f(t)));
}
else if (d) {
return t => compose(a(t), b(t), c(t), d(t));
}
else if (c) {
return t => compose(a(t), b(t), c(t));
}
else if (b) {
return t => compose(a(t), b(t));
}
else if (a) {
return t => compose(a(t));
}
else {
return t => u => u;
}
}

/**
* High-order function, composes functions. Note that functions are composed inside-out;
* for example, `compose(a, b)` is the equivalent of `x => b(a(x))`.
*
* @param args The functions to compose.
*/
export function compose<T>(...args: ((t: T) => T)[]): (t: T) => T;
export function compose<T>(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T {
if (e) {
const args: ((t: T) => T)[] = [];
for (let i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}

return t => reduceLeft<(t: T) => T, T>(args, (u, f) => f(u), t);
}
else if (d) {
return t => d(c(b(a(t))));
}
else if (c) {
return t => c(b(a(t)));
}
else if (b) {
return t => b(a(t));
}
else if (a) {
return t => a(t);
}
else {
return t => t;
}
}

function formatStringFromArgs(text: string, args: { [index: number]: any; }, baseIndex?: number): string {
baseIndex = baseIndex || 0;

Expand Down Expand Up @@ -1778,7 +1844,6 @@ namespace ts {
this.transformFlags = TransformFlags.None;
this.parent = undefined;
this.original = undefined;
this.transformId = 0;
}

export let objectAllocator: ObjectAllocator = {
Expand Down
Loading